Qt and QML are really great for writing nice and beautiful UIs and applications that can be easily deployed across different platforms and operating systems. Though, I had to discover that the slogan “Code once, deploy everywhere” is not entirely true when it comes to developing in QML for Maemo Fremantle and MeeGo / Harmattan.
The first issue is that there seems to be no usable implementation of the QML components that ship with MeeGo / Harmattan for Maemo Fremantle. I posted some of my own implementations of QML dialogs and text input for Maemo Fremantle before.
The second issue is how to share common code which, depending on the platform (Fremantle or Harmattan), uses either the above mentioned custom implementations or the stock MeeGo components. There is a proposed feature for conditional imports in QML. Nonetheless, even such a feature in an upcoming version does not solve the issues for older versions as on Fremantle.
In this post I’ll sketch how I tried to solve this issue during the development of MeePasswords in order to share as much common code as possible. Please note that I am aware that there is the qt-components package for Fremantle. Though, this package is only available in extras-devel and there seem to be some issues in using it as it is at the moment.
To illustrate the idea of sharing common code while having the flexibility of either using custom implementations or stock libraries I’ll use a simple example. This example will use a simple button which comes as part of the MeeGo 1.2 / Harmattan API but is not available for Maemo Fremantle. For Fremantle the custom implementation available on the Qt Wiki will be used.
So let’s assume we have the following QML code for Harmattan (lets say in a file called “MyCode.qml”):
import QtQuick 1.1 import com.meego 1.0 Rectangle { id: myRectangle anchors.fill: parent Button { id: myButton anchors.centerIn: parent width: parent.width * 0.5 text: "Foo Button" } }
When we now want to port this code to Fremantle the first issue is related to the import statements. The “import QtQuick 1.1” can be “fixed” in two ways: either you change that import to read “import QtQuick 1.0” and use the qtquickcompat package or you simpley go the whole way back and use “import Qt 4.7”. Though, you should be aware that “import Qt 4.7” is officially deprecated (whatever that means for future Qt versions). So this way we get at least the “Rectangle” QML element.
The second issue is worse. On Fremantle there is, to the best of my knowledge, no such package that provides “import com.meego 1.0” (and is available in extras-testing or even extras). So how do we get the Button QML component? For Fremantle we can use the custom implementation of a button which only relies on the Qt 4.7 namespace (which basically equals the QtQuick 1.0 namespace).
Assuming we download that custom button and place it in a file “Button.qml”. This yields in two new issues. First, we only want to use this Button for Fremantle and not for Harmattan. This could be solved by conditionally adding the Button.qml to the Fremantle version, e.g., by using conditions based on QMake scopes in the project file. Still there is a second issue: the “import com.meego 1.0” statement will cause an error on Fremantle and hence block any further execution of our code.
So we essentially want to achieve two things: include the file “Button.qml” only in the Fremantle version and get rid of the “import com.meego 1.0” statement in our shared code.
The way I approached this issue in MeePasswords is as follows. First I split up the directory structure of my project to have directories for common, shared code, and for platform specific code:
- common/
- fremantle/
- harmattan/
Then I introduced an indirection for the Button element, named e.g. “CommonButton”. A CommonButton essentially is a button that, depending on the platform, either uses the custom button code or the button provided by the MeeGo API.
So for Fremantle the “CommonButton.qml” looks as follows (note that you could as well copy the code for the custom button directly to the “CustomButton.qml” instead of having it in “Button.qml” and using that indirection):
Button { id: commonButton }
For Harmattan the “CommonButton.qml” uses the Button that comes with the MeeGo API:
import com.meego 1.0 Button { id: commonButton }
The “CommonButton.qml” files are stored in the corresponding directories for the specific platform: fremantle/ and harmattan/ respectively.
In common/ the “MyCode.qml” looks as follows (Note that I simply used the Qt 4.7 namespace here. See also above.):
import Qt 4.7 Rectangle { id: myRectangle anchors.fill: parent CommonButton { id: myButton anchors.centerIn: parent width: parent.width * 0.5 text: "Foo Button" } }
Finally, I put everything together using Qt resources (in MeePasswords I wanted to encapsulate the QML files in the binary). Though, also when deployed in separate QML files the logic behind this is similar.
“common.qrc”:
<RCC> <qresource prefix="/"> <file>common/MyCode.qml</file> <!--<span class="hiddenSpellError" pre=""-->qresource> </RCC>
“fremantle.qrc”:
<RCC> <qresource prefix="/"> <file alias="common/Button.qml">fremantle/Button.qml</file> <file alias="common/CommonButton.qml">fremantle/CommonButton.qml</file> </qresource> </RCC>
“harmattan.qrc”:
<RCC> <qresource prefix="/"> <file alias="common/CommonButton.qml">harmattan/CommonButton.qml</file> </qresource> </RCC>
Note the “alias” attributes which put the CommonButton.qml files in the common/ directory such that CommonButton can be used in MyCode.qml without the need for an import statement.
With this approach it is possible to share common code between Fremantle and Harmattan at the cost of adding some simple *.qml files and aliasing in Qt resources (Assuming you already use Qt resources and scope based conditionals in your project file for deployment the additional overhead for this solution really is minimal.) While the example presented here is very simple and the benefit of the approach presented here might not be worth the effort in such simple cases even slightly more complex scenarios will be worth the additional, minimal overhead.
Pingback: QML TreeView « ruedigergad
a qt-components that works is on his way to extras-devel (Wait a week or so). Still yo will get thqr QtQuick 1.0 vs QtQuick 1.1 problems but IMO is somthing that could be managed at a git level.
If you want to see videos about it see http://www.kirumedia.com/maemo5.
The main problem now is the lack of a good theme, becouse blanco theme is propietary.
To now more about this take a look to meego forums.
Salu2