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.


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.