My way is a warrior, or how I prepared an application for life in Sailfish

    The art of warrior is to maintain a balance
    between the horror of being a man and the miracle of being a man.
    “Journey to Ixtlan”

    My way of a warrior - a brutal frontend developer on “pluses” - was to find a balance between developing an application running on Sailfish and a cross-platform application.

    Recently, I’m working for a developer’s position at Digital Design, and sometimes I have to deal with tasks I haven’t met before. It is interesting and often fun. Now, for example, I am writing a corporate application under Sailfish OS and I want to share my experience with you - this will be discussed below. Follow me under the cat if you are a novice developer or, like me, are faced with the task of adapting a corporate application under Sailfish OS and do not know where to start, as well as those who have not heard about Qt and the features of Sailfish.

    A little background, or why I did it

    When the company developed the “Areopad” solution for iPad (iOS) 5 years ago, no one could have imagined that customers would need an application to work on a device with Sailfish OS (then the OS belonged to the Finnish company Jolla, however now too). But in 2016, the Russian company Open Mobile Platform acquired a license to use it, modify it, distribute it and brought it to mind: it adapted it to domestic mobile devices and users (mainly companies and government agencies) and registered Sailfish Mobile OS RUS in the registry . And now it can be said, the only official Russian operating system for mobile devices.

    Naturally, we wanted to figure it out - we already conquered the rest of the OS, and Sailfish, it seems, has a great future (yes, I’m talking about import substitution). From all this it follows that the application for Sailfish be! The first test object was the mobile application “Information system for the work of collegial bodies“ Areopad ”(it was just at the modernization stage).

    Now about Qt

    A wonderful cross-platform tool that includes the development environment, a ton of useful and convenient libraries, and even your own QML markup language. I will not dwell on it for a long time, because many articles on Habré have been written about this miracle, and you can also read documentation that is easy to read and easy to read.

    Just in case, I’ll clarify that the calculations and the display take place in different languages ​​in different modules (C ++ and QML), interacting with each other with special cunning methods (property, signal-slot).

    And Qt is the main framework used when developing software for Sailfish.

    Approaches to the solution of the problem: if you go to the left - you will make a crutch, if you go to the right - you will lose the features

    At first, inspired by the idea of ​​cross-platform and the fact that I would embody it, I thought that the application written for Sailfish would not take off, but would happily pop up on any other OS, but at least on a refrigerator or a kettle. But my happiness lasted exactly until the moment when I sat down to run it on Android - then I felt sad. Sailfish is not well suited for this case and definitely does not intend to change anything.

    If Android or iOS allow using conditional compilation and provide some kind of tool for this, then Sailfish cannot be distinguished from Linux (within Qt, of course).

    Next, there is a QML compatibility problem: in Sailfish, the outdated version of Qt Quick (2.6 for Sailfish and already 2.11 for all others), Android does not know Silica, Sailfish does not know QtQuick.Controls. Therefore, for different operating systems you have to pull the same components from different libraries, which produces almost the same files for each operating system.
    At the same time, Silica probably has all the same features as QtQuick.Controls, but refuses to run on any other platform.

    Sailfish Features

    Being a lazy, most creative creative person with a desire to optimize labor costs, I took the path of least resistancefunctionality and wrote my masterpiece on pure Qt, without using QtQuick.Controls and Silica. As a result, everything works grandly and nobly on Sailfish, but on Android, half of the elements, despite my strict order to sit still, have departed to some other important business, so the next step will be to do it in an adult way and dissolve markup files for each OS at different angles. [Which I subsequently did while preparing the article for publication. This story draws on a separate article]. Please remember and accept: magic constants are evil (for example, width: 15). And on two almost identical devices, even with the same OS, they can differ by 2 times.

    However, I can not fail to note that there are definitely interesting things in the Sailfish version. Of course, in such a short time that I know him, it is almost impossible to know the whole rich inner world of Sailfish - our relationship with him is at the “candy-bouquet period” stage, and I have not learned a lot of things in his complex character. In addition, it was decided to draw a universal application for all operating systems, so using more intricate mechanisms to use the chance never fell out, but I’ll tell you about a couple of interesting points.

    We will discuss only one library for the implementation of the Silica graphical interface, for the rest, which I managed to learn and understand, is no different from standard QML programming.

    • Theme.

    I was interested in this tool most of all, because I didn’t see any analogue in other OSes, but it was also simple. The bottom line is that the design of applications is not a constant, but depends on the chosen topic.

    The Theme element contains information about the currently selected topic: primary colors, font sizes, indents, and components. Thus, when writing applications, you do not need to hardcod colors, adjust dimensions to fit the screen size, and generally look at the layout (forgive me designers, you already have a lot of work), you can just pull it all up from the Theme element. Well, isn't it cool!

    • Menu.

    Also a feature of Sailfish (although it may be possible in Android, but I have not seen it).

    There are three types of menus:
    PullDownMenu - PushUpMenu - ContextMenu

    As for Silica ... View, they do not differ from the standard ... View (± a pair of not very noticeable properties), and the Button component makes pretty nervous - the button height cannot be changed, you have to write Rectangle everywhere and MouseArea. If I only made an application for Sailfish using the standard design of this OS, it would not be necessary to change the height of the button or you could use a component from Silica. But since I am writing an application for all devices, it was decided to use the most massive design (Android), so that everyone was familiar and comfortable. Many will disagree with me and say that you need to use native UI elements for each platform, but this is a completely different topic, it has been the subject of holivars for many years, during which time more than one generation of developers has grown.

    Spoon of tar to mobile development on qt

    • Assynchronism

    In Qt, to communicate with the server, calling a single function is not enough; you need to send a request and ask for a special object responsible for the server response, call the response processing function (which, of course, we write ourselves) when the answer is received:

          QNetworkRequest request("");
          QNetworkReply *reply = mngr->get(request);
          connect(reply, &QNetworkReply::finished, this, &Class:: onReplyFinished);
        QNetworkReply *reply = (QNetworkReply*)sender();
        QByteArray ans = reply->readAll();
        qDebug() << ans;

    The onReplyFinished function will be called at the time of receiving a response from the server, and this may take an unknown amount of time depending on the quality of the connection and the server part. Now imagine how it will be organized with 1500-2000 requests, which depend on each other and should be launched in a strict queue. And if you remember that the entire UI part depends on the answer, it becomes absolutely scary.

    • Kostyu-oriented programming, or a creative approach to solving problems

    Another topic is ListView, this is a very local Qt problem, but still unpleasant.

    Any self-respecting ListView must have a header component, which inserts some element that is fundamentally different from the others as the first delegate. Yes, he does it, yes, everything draws beautifully, if it were not for one “but”: my delegate takes up the entire screen, and it needs to be flipped, but as soon as I try to flip left from the zero index to the left, he basically refuses this Hader show. What to do with it? Put a crutch. A piece of my model generation code for this ListView in the cpp part, describing as much as possible what is happening:

    foreach (QVariant quest, QQuestions)
        Questions.append(new Question(client, quest));
    kostilQuestions = Questions;
    if (Questions.size() > 0)

    The delegate then creates 2 independent items whose visibility depends on the index.
    When the index is zero, we see one, otherwise - the other.


    As a result, I received an application that “flies” both on Android and iOS, and on Sailfish, more precisely, a flexible application that adapts to these operating systems. And magic has nothing to do with it. I found a way to avoid conflict and make friends with all OS c Sailfish by substituting some files for Sailfish and all the others. This allowed in the application code to allocate user interface layers for each OS.

    We can assume that we have taken the first step - we made friends with the application Sailfish. But the work on this is not completed, we with Sailfish are entering a new level of our relationship - we are preparing the ISOP Areopad application for registering in the registry (as an application for Sailfish), which means that we will need to adapt it also for the registry.

    I hope it was interesting. To be continued.

    Also popular now: