UI Extensions for Mobile (Orbit) vs. Maemo 6 UI Framework

Probably many of the readers of this blog have noticed that Nokia released a preview of UI Extensions for MObile aka Uiemo this week. In my opinion this is very interesting because Nokia has been developing two, very large, expensive UI frameworks and both of them are built on top of Qt. The development has been done at the same time also. Some time ago I wrote a blog article of “Maemo 6 and Concerns of the Community” where I referred couple of ongoing discussions in maemo.org. In that specific blog post I was guessing little bit how Orbit would probably work on top of Qt. I wasn’t so wrong after all:)

Now many of you readers will think that “Oh no… Now this guys is doing another Peek to XXX series of Uiemo”:) Don’t worry I won’t do that. I just don’t have time for doing such a large review at the moment. Instead I want to go through couple of things related on Uiemo. One interesting detail is that the following diagram from my previous post was not so far from the truth.

DirectUI vs. DirectUI

The only difference is that the underlying platform can be Symbian, Windows or Linux/Maemo. Yes, there is a support for Maemo also. Check Kypeli’s post from his blog where he built Uiemo for Maemo 5. Current version of Uiemo is not a cross platform though. It doesn’t support Mac (OS X) at the moment  which would be nice to have at some point.

So Nokia has released two different Qt based UI frameworks and they both run on Maemo also. I could say that this brings interesting thoughts into my mind. I also found couple of videos from youtube where Uiemo application is already running on N900. Watch one of the videos below:

Minor Peek into the Uiemo

So let’s go little bit deeper then. Here I will check the same metrics that I checked for Maemo 6 UI Framework. I ran sloccount for Uiemo and I noticed that it’s even bigger framework that Maemo 6 UI Framework was at the time when I reviewed it. There are over 150 000 lines of code.

SLOC Directory SLOC-by-Language (Sorted)
  • 86821   src_hbcore      cpp=86821
  • 38389   src_hbwidgets   cpp=38389
  • 9916    src_hbplugins   cpp=9916
  • 6295    src_hbinput     cpp=6295
  • 4446    src_hbservers   cpp=4446
  • 2282    src_hbtools     cpp=2282
  • 1569    src_hbfeedback  cpp=1569
  • 1088    top_dir         python=1088
  • 802     include         ansic=802
  • 161     bin             python=161
Totals grouped by language (dominant language first):
  • cpp:         149724 (98.65%)
  • python:        1249 (0.82%)
  • ansic:          802 (0.53%)

I also ran grep for searching the dynamic_casts and there were couple of them. Not as many as in Maemo 6 UI Framework, but I was bit surprised to see dynamic_cast to be used here also.

  • ./src/hbcore/gestures/hbswipegesturerecognizer.cpp:  1
  • ./src/hbcore/gui/hbtoolbar.cpp: 1
  • ./src/hbcore/gui/hbtoolbutton.cpp: 1
  • ./src/hbcore/indicatorplugins/hbindicatorpluginmanager.cpp:  1
  • ./src/hbplugins/feedback/feedbackeffectplugin/hbfeedbackeffectutils.cpp: 1
  • ./src/hbwidgets/sliders/hbslidertickmarks.cpp: 2
  • ./src/hbwidgets/sliders/hbslidertickmarkslabel.cpp: 3

After this I tested if Uiemo developers have normalized the signal and slot signatures when doing connections in order to reduce operations like removing white spaces and removing “const” keywords and “&” marks. I noticed that part of the code contained normalized signatures and other parts didn’t. If you don’t know what “normalized signal/slot signature” means check this first review article of Maemo 6 UI Framework. Compared to the Maemo 6 UI Framework, the Uiemo code seems to be more mature and somehow the code looks much cleaner in many ways. Maybe one reason for this is that they have been developing Uiemo longer than Maemo 6 UI Framework? I really don’t know.

Widget Hierarchy – HbWidgets and Primitives

The following diagram shows how the widgets are constructed in Uiemo. First couple words of widgets and primitives. If I have understood the design correctly, a widget in the Uiemo consists of a “Widget” and “widget primitives”.

A widget is something that is constructed from a primitive or several primitives. For example HbPushButton contains the following primitives: frame item, text item, additional text item, icon item and text area item. These primitives are created via HbStyle object’s HbStyle::createPrimitive( HbStyle::P_PushButton_background,  parent ) method. Usually the widget e.g. HbPushButton is passed as a parent to the primitive.

The primitives are responsible of doing the actual drawing so primitives implement the paint(..) methods for widgets. This means that when a widget gets paint event, all the children of the widget i.e. the primitives will make the actual drawing.

HbPushButton structure.

Remember that the diagram above is not perfect. The idea is to give a rough picture how classes are connected together and for example what HbPushButton requires in order to make it work. Next I will explain how the basic structure works without going any details of HbPushButton implementation.

HbStyle

HbStyle class is reponsible of creating all the primitive types that HbWidget needs. As I said earlier, the primitive is resposible of doing the actual drawing. Each primitive type is defined in enum HbStyle::Primitive here and based on a first attribute value in HbStyle::createPrimitive(HbStyle::Primitive, QGraphicsItem*) method, the correct primitive object is created. HbStyle instance can be accessed via HbWidget::style() method.

As you probably now, in Qt the drawing must be done in certain order. For example the background must be drawn first and text must be drawn after the background. Otherwise the text stays under the background. This is where the Z-value of a primitive matters. In HbStyle::createPrimitive() method, most of the primitives are created so that HbStyle sets the Z-value for the primitive. Basically the Z-value means that items with smaller Z-value are below to the other items with higher Z-value. This also means that item on top, will receive events. If the Z-value is not set for a primitive, then primitives must be created in certain order to make them draw correctly (Please correct this if I’m wrong).

There are bunch of predefined primitives in Uiemo, but as a developer I started to think, right away, how extensible this system is? With this I mean, how easy it is to introduce new primitives to HbStyle class because each primitive type is hardcoded there. The answer is that you can extend Uiemo with custom primitives via plugins. I believe that, one of the main idea is that you can build your application using the Uiemo primitives only and not by introducing new primitive types. Of course nothing prevents you to re-implement paint(..) method in your own class which inherits HbWidget and do all the drawing and event handling by yourself.

HbStyle provides methods for extending Uiemo by using primitive plugins. Plugin system uses standard Qt plugin loader system. Each custom primitive must inherit and implement abstract HbStyleInterface class. Otherwise it’s just a Qt Interface loaded via QPluginLoader. If you use a custom primitive, your  widget should call HbStyle::registerPlugin(QString pluginName ) method. This means that the plugin is loaded when a widget or an application calls this method. The intersting thing is that this of course causes some slowness for application startup. Another interesting issue is that it seems that the “hardcoded” Uiemo primitives don’t implement HbStyleInterface class.

One big issue with this design is that I think HbStyle implementation doesn’t take advantage of OO paradigm. All hardcoded primitive types require that HbStyle knows exactly the primitive and style option interfaces that it is dealing. HbStyle must know each custom methods the primitive have and HbStyle must know the Z-order that primitive must have. In HbStyle::updatePrimitive(..) method, the HbStyle must know e.g. HbStyleOptionPushButton instead of the HbStyleOption class. In opinion, this should have been done in OO way i.e. knowing the common superclass for all primitives and for all style options. You can easily see this problem from the diagram above and I’m quite surprised of this design.

Addition: After some discussion in the comment section, I may have made some haisty conclusions so the design is probably better than I thought. Thanks for opening my eyes:)

HbStyleOption

HbStyleOption is a really “thin” class. It contains enum OptionType which defines types for each style option. This class is inherited by several widget specific style option classes e.g. by HbStyleOptionPushButton. For me this class basically acts as a model, which contains data that is used for visualizing the widget and in this case the widget is HbPushButton.

HbAbstractItem

HbAbstractItem is marked as deprecated class in the documentaion and they say that new base class for all widgets is HbWidgetBase class. But what this class does, is that it provides cast functions for casting QGraphicsItem to HbAbstractItem or specified types in a similar manner than Qt does casting e.g. qgraphicsitem_cast or qobject_cast. I think that providing these casting functions is a good idea because otherwise you would need to use static_cast which is not so safe way to do caseting. HbAbstractItem also defines so called user type for all HbWidgets.

HbWidgetBase

As stated in HbAbstractItem documentation, HbWidgetBase acts as a base for all HbWidgets and for all the primitives e.g. HbFrameItem. This class doesn’t do much – couple of methods for setting and getting attributes  and fonts for a widget, it listens state changes via QGraphicsWidget::itemChange() callback. Many of the inheriting classes re-implement this method in order to update their primitives.

HbWidget

HbWidget is a class that is inherited by all the “concrete” widget such as HbPushButton, HbLabel, HbTextEdit etc. HbWidget class provides access to the HbStyle instance in order to create, update and recreate the primitives. It is possible to set a custom style for each widget. It also handles focus in / out events and if I have understood the code right, then it’s possible to define a needed feedback (haptic) effect for that widget i.e. does the device vibrate when tapping a button and so on.

HbWidget is responsible of making the widget to update its state e.g. when pressing a button and the widget gets QGraphicsItem::mousePressEvent(..) callback call, then it usually must make one or more primitives to repaint the content of the widget. At this point the widget can also trigger feedback e.g. by calling: HbWidgetFeedback::triggered(this, Hb::InstantPressed).

Rest of the Uiemo Framework

Like in Maemo 6 UI Framework, Uiemo provides own HbApplication class. This class inherits from QApplication and  HbApplication instance is needed for initializing the HbInputs framework. The HbInputs framework handles input methods when a certain UI element becomes focused. I guess this means that when you tap e.g. text edit field, then a virtual keyboard opens.

There is also HbMainWindow class which creates a specialized version of QGraphicsView and that is used as an application window. By default it also constructs HbGraphicsScene, which can handle monitor the focus of the items in the scene in order to make HbInputs framework to work properly. The rationale behind this is that the Qt’s input method works only for QWidget based implementation, not QGraphicsWidget based widgets.

Each HbMainWindow can have view or views. This is where HbView comes to the picture. HbView is a QGraphicsWidget, which have a title, n icon, a menu and a tool bar. A view can contain the widgets and you can have one or several views. If you change a view, the HbMainWindow will update the title and a toolbar.

The Uiemo framework is huge and what I have presented here is just a tip of an iceberg. So if you think that you would like to learn more about Uiemo, just clone the repository from gitorious, generate doxygentation, open top level pro file to Qt Creator and start study.

Conclusion

Uiemo seems to be more mature that Maemo 6 UI Framework, but I haven’t seen any updates of Maemo 6 UI Framework lately and I have no idea which one of these two frameworks have been started earlier. I guess it doesn’t make much sense to compare them. There are quite much similarities, but also differences. In Maemo 6 UI Framework there is the  MVC model, which I criticized a lot in my review. In Uiemo there is similar kind of design but “components” are only named differently: a Controller is HbWidget or one of its subclasses, a View is a primitive or several primitives and a Model is HbStyleOption and its subclasses. Like in Maemo 6, in Uiemo, it is possible to override this structure by inheriting the HbWidget and define everything in one class, if you want.

I’m not sure, why MVC model seems to be hardcoded to each Nokia frameworks, but it’s there and it’s not probably going away. I’m bit worried about the amount of hardcoding primitives and options in the HbStyle class and not taking advantage of OO paradigm as I stated earlier. It was also interesting to notice that for custom primitives there is a HbStyleInterface, but the Uiemo primitives are not using that. So why do they have two different approach for implementing a primitive? It would be nice to know.

As I wrote in the beginning of this article, it is very interesting that why do they have a support for Maemo also? Is this just for proofing that it can run on Maemo also or do they really try to make it to work on each platform. In my opinion, it should be a cross platform, but then it would be nice to have Mac support also.

I don’t have much to criticize Uiemo, only couple of things that I already mentioned. I tested  building it for linux and it worked out of box. According the attached youtube video it seems to work “ok” on N900, even though it looked bit sticky. I’m not sure if those guys ran the application with or without the Hildon Desktop, which might have a significant effect on perfomance. Compared to Maemo 6 UI Framework, you don’t need to extend Qt / qmake in order to be able to use Uiemo. Which is good.

I know, that Uiemo will probably raise similar kind of discussion as you can read from the Maemo.org’s thread about “Maemo 6 loosing source compatibility“. Let’s hope that community will be active on this one also and I mean in good, not in bad.

…and an Idea

While writing this article, I had an idea. What if there would be a (Qt) community driven open source project which has a goal to provide a set of QGraphicsWidget/Item based widgets that could be integrated to the Qt at some point. I know that there is already a project called “next generation widgets” but I think that if the community could provide something like this, it would be really cool. Another thing that came to my mind was that if these very same widgets could be used in QML also, it would extend the Qt’s Declarative UI for half free, but this is just so called “brain farting” (in the middle of night) and I haven’t given too much toughs for the details. But that’s all folks, I hope you liked this article.

Tags: , , , , ,

11 Responses to “UI Extensions for Mobile (Orbit) vs. Maemo 6 UI Framework”

  1. michael says:

    What’s your opinion about the memory allocator classes in Orbit? I think they look a bit un-c++-ish (the unsafe type casts from void pointers, for example) …

    • zchydem says:

      @michael you are right! I just had a lunch with chakie and we discussed with this problem and funny thing was that he faced this problem in 64 bits environment yesterday. There int has 64 bits and void pointer has 32 bits. When doing casting from void to int you will get an error. Definetly a critical issue when it comes to portability.

      This is very good point to raise and maybe you can send an email to developer.feedback@nokia.com?

  2. mbm says:

    The widgets-ng code is available here: http://qt.gitorious.org/qt-labs/widgets-ng
    We want this project to be done completely in the open, together with the rest of the open source community. So feel free to join us. :)

  3. mbm says:

    @dubik I see no problem with having choice. :) There is also an advantage in being the second mover. It gives the opportunity to learn from previous efforts.

    • dubik says:

      Don’t get me wrong, I really want to see what you guys can do with itemsview-ng. It wasn’t very active for past few months and I thought you guys gave up. Glad to hear that you didn’t :)
      I also like choice :)

  4. zchydem says:

    @dubik & @mbm If I understand the codebase correctly widgets should be in: widgets-ng/src/gui/graphicswidgets/ ? There’re not so many widgets around yet, as dubik said, but it’s good to have challenges:)

  5. tackat says:

    > You can easily see this problem from the diagram above
    > and I’m quite surprised of this design.

    Well, it mimics about almost exactly the design of QStyle, QStyleOption:

    http://doc.trolltech.com/qq/qq13-styles.html

    The only difference is that it takes QStyle to the next level by making the “primitives” / “controls” / “complex controls” QGraphicsItems and by making them accessible via the scene graph.

    The great thing about the QStyle “MVC” pattern in Qt is that usually you don’t notice it as a programmer. And it doesn’t get in your way.

    In Uiemo as well as in Maemo you don’t need to use the MVC pattern either in order to become productive. Both frameworks are exploring the capabilities of QGraphicsView and are helping (together with KDE’s Plasma) to make QGraphicsView even better. All of these projects have certainly QML and QWidgets-NG on their radar. And QML as well as QWidgets-NG are taking the lessons learned from these three projects. This is great because this will help the Qt universe to flourish further in the future.

    • zchydem says:

      @tackat You are right about the design and how it resembles the design of QStyle and QStyleOption!

      I may have done some haisty conclusions there and I agree that this is a great opportunity to learn from these projects. You’re also right that you can develop widgets without knowing the existence of primitives and how they work. I also mentioned in the article, that that you can inherit the HbWidget and do all the things there, just like it works with QWidgets. (If I understood it correctly)

      I’m still learning Qt, it’s a project that will never end. Thank you for your comments and patience:)

Leave a Reply

You must be logged in to post a comment.