Saturday, July 9, 2011

Qt Components - The story of the ugly QWidgetling

Disclaimer: these are my own, personal thoughts, not necessarily matching those of my employer, neighbor, goldfish or innocent bystanders.

Paradigm shifts are always difficult, especially when linked to technology changes. Qt Components are here and seeing that there and at least three component sets (MeeGo Harmattan, Symbian, MeeGo UX) and counting, it is hard to see how components will help solve the cross-platform problem that has been plaguing mobile developers. Hard to see, if you think about Components as a QWidgetling, that is. In the vein of the story of the ugly duckling, I will try to explain how you can utilize Components and avoid the feeling of being given a square peg when you are looking at a round hole. To repeat, this is about figuring about just what QML with Components is, how it's supposed to be used. Disclaimer #2: Those who think QWidgets should have been the long term technology of choice, or hate QML with a passion, please skip this article. You're not going to like it, and I'm usually delete-button-happy, so save the angst and skip it. Sorry and thanks.

QWidgets

If I was trolling, I would say they were (mobile-wise) the cross-platform solution that never existed - it certainly *sounded* good that I, as a developer, work against an API and the UI framework works out everything, resolution, input method, hardware be damned. This, however, is a bit like listening to politicians - just vote for me and I will solve all problems. Well, not quite. As many have outlined, the paradigm shift from the "I wrap everything to native controls which
 kinda look/work the same" characteristic for the desktop spelt doom for the classic widget based approach. I have gotten nasty looks IRL for saying this, but Maemo5 did not prove QWidgets is the solution - it proved that it is NOT (yes, I be trollin', but only to make a point :). It was a great effort, and while the looks were certainly on par, your supposedly cross-platform code was a mess, full of #ifdefs, modules and classes specific to Maemo5. As I sometimes say, well, with enough ifdefs, you could switch between GTK and Qt, right ? At the same time, development was not made any easier - there were no specific UI tools for creating Maemo interfaces.

QML, and the long road to Components


Enter QML, a radically different approach. As people soon realized, QML is a base technology, it does not provide you with buttons or much higher level functionality you previously had with QWidgets. Also, at the same time, it was said Qt Components will solve this. All was well, it was just a little wait and we will have our new incarnation of QWidgets, right ? Well, not quite...
 
QtComponents have hatched...


... and it turns out they harbor a pretty ugly QWidgets replacement. People trying to make QML that runs equally well on Harmattan using the Harmattan components, Symbian using Symbian components already felt this is not good. Recently I got a contribution for QtInfo in the form of a cool Symbian components UI. I tried to kick it around a bit to make it work on Harmattan, with bleak results, with projects diverging already at the HelloWorld. Something was wrong. This duckling was really ugly. After a few days, however, it dawned on me...

A chainsaw cuts trees faster than an axe only if it's on

The reason I was suffering and losing time was because for years I have been taught to think (much in the vein of QWidgets) almost axiomatically that I want a single codebase and with enough tweaking (ifdefs) it would run equally well on platforms. That is no longer necessarily true (if you think I'm losing my mind, that's understandable, but read on). In terms of the title of this paragraph, I had Components (the chainsaw) and I was hitting the tree with it like I would with an axe, and it really is a horrible experience. However, there is a paradigm shift on the horizon. Turns out, Components solves the cross-platform challenge NOT by providing a singular API. It attacks the problem by making is super-easy to write throwaway code. WHAT ? (if you think I *completely* lost my mind, that's understandable, too, but read on).

Live fast, die young

One of the key appeals of the old widget approach was their enduring nature. If you wrote a desktop application 10 years ago with it, it would likely work okay today. However, this age of UI tranquility, taken for granted for so long, is in it's final days. As we've seen, today even the most conservative desktop OSs are undergoing UI paradigm shifts. Mobile is even faster, 4 years in mobile is an eternity. Writing an UI as if it was there to stay for decades is losing appeal quickly - the life expectancy of mobile UIs is dramatically shorter, which coincidentally also lowers the long-term maintenance burden, traditionally so important to developers.

Use the Force. Let go, Luke.

As Ben Kenobi said. And even though it seemed weird to the people in the rebel base for Luke Skywalker to use the Force instead of the targeting computer, it shows us what's happening here. Let go of the idea of monolithic, single UI codebases. Let. Go. Like the huge armor of European medieval knights on appearance of the guns - the armor no longer provided real protection, but made you slow and unmaneuverable. So, what should I do, I hear you asking ? EMBRACE DIVERSITY. Use the weapon/components best suited for the platform. Don't be afraid to improvise or include your own Elements, or borrow (barring license limitations) from Components of other platforms. Keep your UI (QML) layer as thin and nimble as possible, keep the logic on the C++ side, it will help you both in terms of portability and speed. Spawn as many UIs as you wish. Think about the UI as a throwaway component. Is it Harmattan ? Okay, I'll just drop in the QML from the examples, who cares if it runs on Symbian. Different resolution ? I'll just include a different QML optimized for that. I can see the disbelief in your eyes. How can this work ? The point is that spawning UIs with QML is *fast*. Really fast. Actually way, way, way faster than tweaking for a certain subset/common API or resolution independence. You will write (and maintain !) 5 different UIs *faster* than you would write a monolithic QWidgets UI that would work truly cross-platform. It is a radically different setup. Returning to my QtInfo porting example - it took me nearly a day to create a port from the Symbian-only version to a version that ran on both Harmattan and Symbian, but it meant a lot of compromises and visual artifacts, rotation and integration issues. However, when I realized the new paradigm I outlined above, I had a sexy Harmattan fully integrated native UI up and running in 30 minutes, just appended the QML to the package and now the application is cool on Symbian, Maemo, Harmattan, the Desktop, and I could add a tablet MeeGo UX in another 30 minutes.

There you go, with all the acknowledgement that this might be hard to swallow for many of you, trusty old QWidget veterans, hopefully I now explained just what kind of square peg Qt Components I see and you will hopefully stop trying to shove it in that round hole :) Now go and make Qt Components shine and create beautiful swans of Harmattan, Symbian, MeeGo, or whichever platform the Qt winds might blow on.

16 comments:

  1. I believe the major part of what QML/Qt quick and Qt5 will introduce is what you described however it is NOT clearly stated by Qt/Nokia engineers. Maybe they are just afraid to be targeted :-)

    For the record, I am not against it because of my previous experience with cross-platform and ifdefs :-)

    ReplyDelete
  2. Thank you very much for posting this. QML truly brings a paradigm shift that is initially hard to grasp, but when working with QML you either accept it or have to learn it the hard way.

    When I started developing for Maemo5, MeeGo Netbook, MeeGo Tablet, and WeTab at the same time, I also tried to make the UI as generic as possible. However, this will only give you headache. You have to accept that a UI is throw-away code and code duplication in the UI is not essentially a bad thing as long as it doesn't affect program logic.

    What I miss as developer are guidelines for good practise in cross-platform QML development. As it is now every developer struggles her/his own fight with this.

    ReplyDelete
  3. Now this *might* be right (I'm going to think about it more), but this will be seen as another obstacle to Qt becoming a next-gen mobile platform. It certainly appears that this is just a rehash of the "we can't make QWidgets work on multiple form factors" argument (there, as you mention, it's the widely varying form factors, resolutions and capabilities that were the problem; but now those things are the broadly the same).

    The things which really differ between Harmattan, Maemo, Symbian and MeeGo are the styling (yawn) and the mechanisms for closing/switching apps. Is there really a need for the definition of an actionable Button being different and requiring a different "import"? No.

    Surely, the answer (if you weren't trying to retcon the poor decision decisions ;-)) is to give developers the choice. Make it easy to reuse the bits which are reusable but *encourage* the pattern of using different overall QML structures for different platforms (and provide an easy API, pattern and examples for that). IOW, have a common API and imports where it makes sense, and diverge where it doesn't.

    ReplyDelete
  4. @Jaffa As for the separate import - yes, that is annoying and I hope it goes away, though shortcuts in the form of "import Qt.labs.components.native 1.0" are already available and will be made more straightforward in the future releases.

    As for the cross-platform appeal... I would say it's more of an advantage than an obstacle in terms of porting. Making a component set (unconstrained by previous design/common API choices) for, say, WebOS/Android/iOS/younameit is a *lot* easier that making a really well integrated QWidgets implementation or common API QML.

    ReplyDelete
  5. @Attila, "Making a component set for, say, WebOS/Android/iOS/younameit is a *lot* easier that making a really well integrated QWidgets implementation or common API QML"

    Absolutely; but then I'm not the one whose (ex-)strategy depended on pitching Qt as the common factor for multiple platforns :-)

    ReplyDelete
  6. @Jaffa well, qt is multiplatform. You can use plain QML to develop perfectly portable apps for Meego and Symbian.
    qt-components is also multiplatform technically. At least it works on windows, mac, linux, embedded devices.
    The key here is UX. Good, consistent with OS UX can be platform specific only.

    ReplyDelete
  7. I wish QML all the best and hope it does wonders for Qt. But not at the cost of QWidgets ( which has already happened ). But as you already said that readers like me should not comment, so i wont troll much.

    ReplyDelete
  8. 1/ "Let go of the idea of monolithic, single UI codebases. Let. Go"
    Why ? It works in most case, avoid duplicate code, and permit easy port. What we have NOW, different component by device/plateform/vendor which didn't share the same api. This force us to do one UI for all. It s require far more time to target multi device.


    2/Let me give the feeling i have about QML and QWidget.

    QML is i think in it s current form not ready for primetime and all case use. Need many workarround for simple things (Text management miss features, problem with network request and 3G network (and stupid isp), ...)

    3/ "5 different UIs *faster* than you would write a monolithic QWidgets UI "
    Hum, sorry but this isn't the case yet. It s take me far more time to do ONE UI than doing it in QWidget. I'll repeat myself, but things are still too much low level.

    4/ The feeling i have is : "Hey guys, it s a pain to do qwidget adapt magically to all plateform, we should do something more low level and so it s less thing to do for us".
    Yep, i see now Qt as a low level plateform.

    Maybe later we will got component of a higher level compatible with all plateform qt is running on, but it s not the case yet.

    5/ I didn't like the syntax, but that is a personnal choice :)

    Anyway, this is the way to go, no choice for targetting harmattan device and for the futur, and i think the main rant is about that ... choice and changes.

    Let see what QtQuick 2.0 will bring.

    From someone who try to do cross plateform app working on desktop, harmattan, freemantle, and meego handset.

    ReplyDelete
  9. @Nishant
    QWidgets were already diverging intensely, see my point to Khertan below. It's too early to say just how successful the approach I outlined above will be, but QWidgets as a mobile solution were already failing/on the way out, as seen from the Maemo5 episode.

    @Khertan
    1. The point of the whole post was that it's not the COUNT of UIs that is important but how difficult it is to make them. You make one UI, true, and it a) looks miserably or b) is #ifdeffed to hell or c) uses widgets not available on other platforms.

    2. Of course it's not ready for all use cases, it's a different beast altogether. I could say the same about QWidgets. QWidgets suck at ListViews, for example, which happen to be fairly common in mobile applications.

    3. Because you are a newbie to QML and an expert in QWidgets. When you'll have as many QML hours under your belt as QWidget ones, it will be a different story :)

    ReplyDelete
  10. "When you'll have as many QML hours under your belt as QWidget ones, it will be a different story :) "

    I hope :) But things will be faster if common items component have common api :)

    Currently the main headache is finding what is available on one which plateform and what isn't.

    ReplyDelete
  11. @Khertan
    Well aware of that, a document/page/etc comparing (at least the various Nokia) components should be available shortly

    ReplyDelete
  12. @Attila,
    So at least we agree that QWidgets are the only option for complex applications of desktop (which want no eye candy). May be in future QML would have enough features/power to replace every qwidget (menus, toolbars, mainwindows etc).

    ReplyDelete
  13. @Nishant
    Absolutely, I tried to emphasize throughout the post that it applies to mobile context - and it's not like QWidgets on the desktop are going away (they are confirmed to be there in Qt5, even if in a separate module). It's not the merits of QWidgets that are a question, but their applicability to other than classic-desktop UX paradigms. Of course, Digia or somebody might decide if there is enough commercial interest to implement the desktop widget variant of components, and then we might want to revisit this, but that's another story...

    ReplyDelete
  14. Speaking as a Qt developer and having been involved in several of the component sets I agree with this post. If you want a true cross-platform app with a single code base, you should not use a component set that is specifically targeted at a particular platform such as meego or symbian. Pure generic QML gives you that. We are also looking into providing a component set with a generic theme for this purpose though.

    Attila Csipa:
    We are already working on desktop components with Qt Quick. http://labs.qt.nokia.com/2011/03/10/qml-components-for-desktop/
    http://labs.qt.nokia.com/2011/05/26/table-view-with-qt-quick/

    ReplyDelete
  15. This comment has been removed by a blog administrator.

    ReplyDelete
  16. Yes, but! :)

    Indeed creating another native UI in QML is relatively easy as long as you keep it UI only. Tgough it is probably similar to any other techs if you indeed separate UI cleanly.

    Interesting thing in QML is that together with JavaScript it is actually a very efficient language for creating main UI logic, I try extracting only heavy duty stuff such as video processing to C++.

    And then the headache comes when you try keeping your QML logic same across platforms, but QML UIs different in absence of #ifdef'ed imports. Well, hopefully conditional imports are coming.

    ReplyDelete