Note this article is work-in-profess, reflecting work that is work-in-progress, and will be updated / corrected as the migration moves forwards . . .
Last update is: 06 Nove 2013
It is the weekend, but as it is wet and cold outside, with new snow only a few hundred metres higher, there is no flying today. So I am back to programming, and more importantly porting my app Landed to the Sailfish Alpha 2.
As I explained in my last post, recently I have concentrated on the Harmattan version of Landed, making it easier to use, and adding more functionality. While it is not yet finished (will it ever be?). Landed is now fully functional, and thus another stab at porting to the Sailfish Alpha 2 makes sense.
This time, rather than porting all of Landed, I decided to cut out the section I had spent most time on recently into a throwaway demo, and port that. I know from my first attempt that porting all of Landed will take quite some effort: Porting part of it first follows the old software engineering concept of solving large problems by dividing into smaller problems.
The demo is called MigratePhoneContactsDemo. I will soon post the Harmattan code, and the ported Sailfish equivalent code to Github, and add links here.
This article charts the progress of the porting. As the porting is not yet finished at the time I start this article, I will revisit the article over the next few days and make updates as I find solutions, and as I walk into new problems. I will try and keep the article at a high level, and will add child posts if I need to go into detail on particular challenges.
To recap: Landed is an app for paraglider pilots. Upon landing the pilot can use it to send his GPS coordinates via SMS to a recovery team. It should be easy to use, with only a few button presses to generate the SMS, as the pilot may be tired, or worse have crashed or be hanging in a tree. Thus the SMS body comes from a stored template with a preselected contact.
Landed was originally written for the Nokia N9 running Meego Harmattan. Using an abstraction library AbstractUI I was able to use a common code base to target both Harmattan and the Sailfish Alpha 1 as both used very similar versions of Qt (4.7.4 vs 4.8.3). But now Sailfish Alpha 2 is Qt 5 based, which brings a whole bag of changes.
These changes are extensive enough that my original aim of supporting both Harmattan and Sailfish from a common code base may no longer be achievable (though I have not yet totally given up on this). Nevertheless, even if I have to live with two sets of code, the aim is still to keep these as similar as possible, with the differences limited to clearly identified parts of the code, and not spread everywhere.
At the time that I have started this article my demo now starts on the Sailfish Alpha 2. Some of it even works, though not everything does; and even if it runs, it looks pretty ropey.
My porting methodology was this: create a new Sailfish project, copy in the Harmattan code, compile, analyse the errors and correct as required. The changes I have found can be categorised as follows:
a) .pro file
As a standard Sailfish .pro file is quite a bit different from the standard Harmattan .pro file, rather than trying to migrate the file, I chose to create a new Sailfish project from the Sailfish SDK Qt Creator. This gives me a new .pro file (as well as a new standard .cpp file). This also allows me to ditch a lot of Symbian related content that was lurking in the Harmattan .pro file.
b) main.cpp file
The Harmattan and Sailfish default main.cpp files are also quite different in detail - especially the Qt Modules included, which reflects the restructuring and renaming of Qt Modules from Qt 4.x to 5.x.
So my starting point is a new main.cpp file from a new Sailfish project, and then port in selected content from the Harmattan version.
Landed makes uses of several c++ plugins which expose functionality to the QML side of the project (e.g. for SMS and Torch functionality). However the MigratePhoneContactsDemo scope was chosen not to need these, but I do still set some ContextProperties via calls to setContextProperty().
As importing plugins and context properties requires changes to the sailfishapplication.cpp file as well as in the main.cpp file to work properly, I will post a separate post on this topic later and link from here.
c) General project structure
One of the most obvious differences between a Harmattan and a Sailfish project is the structure of the project, and especially where the QML files are buried. Once again, our new default project gives us the expected structure and default content.
Some of the differences are:
qmlapplicationviewer folder is now sailfishapplication. This contains files used by the .pro file. Normally you should not need to touch these (unless like me you have c++ plugins in your project
qtc_packaging is replaced by an rpm folder. If our project has dependencies on other packages that should be preinstalled on the target device, then we may need to make changes to the files within the rpm folder, but that is a story for another day.
d) qml location
By default a Harmattan project has a folder called qml containing a subfolder with the project name, which in turn contains all the qml files, including the main.qml referenced in the main.cpp file.
The default Sailfish structure is different. The main.qml lives in the project root. Other qml files live in one of two folders, pages or cover. I like this approach, and extend it by adding further folders alongside pages. For this demo I have added a folder otherqml. If you add such custom folders, you will need to reference these in the .pro file, and import them as required in .qml files.
e) Imports of QtQuick
The Sailfish Alpha 2, or rather Qt 5.x introduces QtQuick 2.0, whereas the Alpha 1 and Harmattan used QtQuick 1.x. Now while it would be possible to install QtQuick 1.x to the Emulator and continue to use that, somehow that seems to avoiding the point of porting! Instead i have replaced all the imports
import QtQuick 1.1
import QtQuick 2.0
The full Landed makes extensive use of QtMobility for SMS messaging, Torch, GPS Location, Sensors, Contacts, Haptic Feedback, and Multimedia functionality. Unfortunately with QT 5.x, the QtMobility module has been extensively rearranged, with some sub modules becoming modules in their own right, and others having an uncertain future. As migrating all of these in one blow was always going to be a challenge, I deliberately chose the scope of this demo to only include Contacts, Feedback and Multimedia.
The easy part is changing the imports in the .qml files thus
import QtMultimediaKit 1.1
import QtMobility.feedback 1.1
import QtMobility.contacts 1.1
are replaced by:
import QtMultimedia 5.0
import QtFeedback 5.0
import QtContacts 5.0
Not all of these are installed as standard to the Sailfish Alpha 2 SDK or Emulator, and thus may need installing to one or both. As an example Qt Contacts 5.0 was not installed to my Emulator, so I had to ssh in, and run
zypper in qt5-qtdeclarative-pim-contacts
From frequent queries to the Sailfish Developers's mailing list installing "missing" modules is a tricky area, so I will add a post on this topic later.
Note also that some QtMobility functionality has been split into different packages, rather than being moved en-bloc as in the examples above. GPS functionality which used to be in Location is now split between Qt5Location and Qt5Positioning.
g) "Missing" Sailfish Components
This is one of the most tricky areas: There a quite a few Harmattan components that have no Sailfish equivalents. Some examples are:
Now in the bad old days of the Alpha 1 the solution was to install the Harmattan components to the Sailfish SDK and Emulator, and use these when required. With my AbstractUI I was able to hide this from the core application, wrapping a Sailfish equivalent where available, and a Harmattan where required. But as the Harmattan components are based on Qt Quick 1.x installing these won't be quite so easy on the Sailfish Alpha 2.
This leaves 4 options
1) Abandon the missing component, find a better UI metaphor that is available in both Harmattan and Sailfish.
My original implementation used a Sheet element. The ContactsSelection page displayed a list of favourite contacts from an SQLite DB, plus a "Phone Contacts" button. Pressing the button opened a Sheet Control which hosted tabs with a Dialer for dialling custom numbers, and a list of the phone's contacts.
I was never entirely happy with this design, and now I found that Sailfish did not support the Sheet Control. So after a rethink I decided that it would be cleaner to dispense with the sheet control entirely: Instead the ContactsSelectionPage would host 3 tabs. The first tab would contain the original list of favourite contacts, the second the diaper, and the third the phone's contacts.
This solution was both cleaner on both platforms, and allowed me to junk a control not available on Sailfish, so I retrofitted this to the Harmattan original. Unfortunately tabs are also not available in Sailfish - by design - but that is a story for another time
2I Port the missing component from Harmattan to Sailfish.
As the Harmattan components are available as plaintext qml, It should be (from a technical point of view) possible to port individual components to the Sailfish Alpha 2 / Qt 5 7 Qt Quick 2.0. However this will have licensing implications, and may result in different parts of your application being under different licences. I will take some time to review the licences of the Harmattan components and update this post accordingly.
3) Write your own equivalent component and use on both platforms.
This is probably the cleanest solution, providing you do not get overly inspired by the source code of the original Harmattan equivalents.
4) Request equivalents from Jolla.
I am not sure how successful this will be, but if enough of us bombard the mailing list with "we need component X …" who knows what will happen ….
h) Equivalent Components, but missing properties / functions
i) Sailfish functionality not available in Harmattan
j) Sailfish look and feel - different handling
k) theme vs Theme