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.
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.
- 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
- 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.
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 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 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 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.
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 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.
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.