Saturday 3 August 2013

Alpha 2: Migrating an Import Library

Note: As my experience and understanding of migrating to Qt5 / Sailfish Alpha 2 increases, I will update this post if required.

Having installed the second Sailfish Alpha (which I will refer to as Alpha 2), and checked that the default "Hello Sailors" project runs on the Emulator, I jumped in feet first to try and get LandedSettings running using Qt5.

Almost at once I ran into a problem, one that should have been obvious from the start: LandedSettings depends on an import library AbstractUI, and of course this must be migrated first.

As abstractui is intended to abstract out the differences between Harmattan and Sailfish, and Sailfish is now on a higher Qt level than Harmattan this does raise the question whether this approach is still valid. But I prefer to defer that question to slightly later For the moment I want to get LandedSetttings up and running on the new Alpha, thus I need to get AbstractUI ported.

The irony of a tool that was intended to ease porting needing porting itself does not escape me.

Therefore I decided to make a throwaway demo import library native to Qt5, and a throwaway QML project to import it. I could then compare the throwaway library to AbstractUI, and identify what needs changing.

The first pleasant surprise is that there is now a project template for Libraries. I chose "New Project / Libraries / Qt Quick 2 Extension Plugin". In the first alpha this template was not available. if I remember correctly i actually created the project in the Qt Project SDK as a a Qt Quick 1 Extension Plugin, and adapted it for Sailfish to the point that I got it working.

Having tested that the throwaway was importable and installable (more on this in a follow-up post) it was time to start porting abstractui.

As the original Sailfish flavour of the abstractui library was not created in the Sailfish SDK (but now could be), I decided to start from fresh, creating a new project in the Saillfish QtCreator, and would then merge in the bits of code required from the old version of the library.

 



The Differences

1) The Project pro Files.

Alpha 1 pro file

#Sailfish OS version of the abstractui user interfacecomponents abstraction layer
TEMPLATE=lib
TARGET=abstractui
TARGET=$$qtLibraryTarget($$TARGET)
QT+=declarative
CONFIG+=qtplugin
#DEPLOYMENT_PATH=/opt/sdk/share/$$TARGET
 
SOURCES+=\
plugin.cpp
 
HEADERS+=\
auimdialogstatus.h\
auimpagestatus.h\
auimpageorientation.h\
plugin.h
 
OTHER_FILES+=$$PWD/auiqmls/*.qml\
auiqmls/AUILabel.qml\
auiqmls/AUICheckBox.qml\
auiqmls/AUIPageWithMenu.qml\
auiqmls/AUIPageHeader.qml\
auiqmls/AUIBackgroundRectangle.qml\
auiqmls/AUIHighlightRectangle.qml\
auiqmls/AUIContextMenu.qml
 
OTHER_FILES+=rpm/abstractui.yaml\
rpm/abstractui.spec
 
TARGETPATH=/opt/sdk/bin
target.path=$$TARGETPATH
 
DEPLOYMENT_PATH=/opt/sdk/share/$$TARGET
qml.path=$$DEPLOYMENT_PATH
  
DEFINES+=DEPLOYMENT_PATH=\"\\\"\"$${DEPLOYMENT_PATH}/\"\\\"\"

Alpha 2 pro file

#SailfishOS version of the abstractui user interface components abstraction layer
TEMPLATE=lib
TARGET=abstractui
QT+=qmlquick
CONFIG+=qtplugin
 
TARGET=$$qtLibraryTarget($$TARGET)
uri=org.flyingsheep.abstractui
 
SOURCES+=\
plugin.cpp
 
HEADERS+=\
auimdialogstatus.h\
auimpagestatus.h\
auimpageorientation.h\
plugin.h
  
OTHER_FILES+=$$PWD/auiqmls/*.qml
 
!equals(_PRO_FILE_PWD_,$$OUT_PWD){
copy_qmldir.target=$$OUT_PWD/qmldir
copy_qmldir.depends=$$_PRO_FILE_PWD_/qmldir
copy_qmldir.commands=$(COPY_FILE)\"$$replace(copy_qmldir.depends,/,$$QMAKE_DIR_SEP)\"\"$$replace(copy_qmldir.target,/,$$QMAKE_DIR_SEP)\"
QMAKE_EXTRA_TARGETS+=copy_qmldir
PRE_TARGETDEPS+=$$copy_qmldir.target
}
 
qmldir.files=qmldir
unix{
installPath=$$[QT_INSTALL_QML]/$$replace(uri,\\.,/)
qmldir.path=$$installPath
target.path=$$installPath
INSTALLS+=targetqmldir
}
 
The most significant change is easy to overlook:

QT+=declarative
 
Is now:
 
QT+=qmlquick
 
This reflects the fact that QtDeclarative is replaced by QmlQuick in Qt5. According to this porting page (see bottom of the page), QtDeclarative is still available in Qt5, but lets make the move to QmlQuick now.

The bottom half of the file is dedicated to installation configuration. I will look at this closely later.

The plugin.h Files

Alpha 1 plugin.h file
 
#ifndef ABSTRACTUI_PLUGIN_H
#define ABSTRACTUI_PLUGIN_H
 
#include<QDeclarativeExtensionPlugin>
 
class AbstractuiPlugin: publicQDeclarativeExtensionPlugin
{
 
 Q_OBJECT
#ifQT_VERSION>=0x050000
 Q_PLUGIN_METADATA(IID"org.qt-project.Qt.QQmlExtensionInterface")
#endif
 
public:
 void registerTypes(constchar*uri);
};
 
#endif // ABSTRACTUI_PLUGIN_H

 

Alpha 2 plugin.h file
 
#ifndef ABSTRACTUI_PLUGIN_H
#define ABSTRACTUI_PLUGIN_H
 
#include<QQmlExtensionPlugin>
 
class AbstractuiPlugin: public QQmlExtensionPlugin
{
 
 Q_OBJECT
 Q_PLUGIN_METADATA(IID"org.qt-project.Qt.QQmlExtensionInterface")
 
public:
 void registerTypes(constchar*uri);
};
 
#endif // ABSTRACTUI_PLUGIN_H

 
Here again the changes reflect the fact that QtDeclarative is replaced by QmlQuick in Qt5.

 
The plugin.cpp Files

Alpha 1 plugin.cpp file

//SailfishOS "flavour" of user interface components abstraction layer
#include"plugin.h"
#include"auimpagestatus.h"
#include"auimdialogstatus.h"
#include"auimpageorientation.h"
 
#include<qdeclarative.h>
 
void AbstractuiPlugin::registerTypes(const char *uri)
{
 Q_ASSERT(uri==QLatin1String("org.flyingsheep.abstractui"));
   qmlRegisterUncreatableType<AUIMPageStatus>(uri,1,0,"AUIPageStatus","");
   qmlRegisterUncreatableType<AUIMDialogStatus>(uri,1,0,"AUIDialogStatus","");
   qmlRegisterUncreatableType<AUIMPageOrientation>(uri,1,0,"AUIPageOrientation","");
}
 
Q_EXPORT_PLUGIN2(abstractuiplugin,AbstractuiPlugin)

Alpha 2 plugin.cpp file

//SailfishOS "flavour" of user interface components abstraction layer
#include"plugin.h"
#include"auimpagestatus.h"
#include"auimdialogstatus.h"
#include"auimpageorientation.h"
 
#include<qqml.h>
 
void AbstractuiPlugin::registerTypes(const char *uri)
{
 Q_ASSERT(uri==QLatin1String("org.flyingsheep.abstractui"));
   qmlRegisterUncreatableType<AUIMPageStatus>(uri,1,0,"AUIPageStatus","");
   qmlRegisterUncreatableType<AUIMDialogStatus>(uri,1,0,"AUIDialogStatus","");
   qmlRegisterUncreatableType<AUIMPageOrientation>(uri,1,0,"AUIPageOrientation","");
}

Here the only difference is that the Q_EXPORT_PLUGIN2 macro is no longer required.

https://qt-project.org/doc/qt-5.1/qtdoc/qtquick-porting-qt5.html states: 

"
plugins no longer require the Q_EXPORT_PLUGIN2() macro. Instead, they should use the Q_PLUGIN_METADATA() macro within the plugin class declaration.
"
I will look into what this means at a later date, and update this post.

The *.qml Files
 
These now import QtQuick 2.0 rather than the QtQuick 1.0 of the first SDK. When I get to testing the library I will see if this has any knock on implications for the qml code, and update this post accordingly.
 
The qmldir File 

According to http://qt-project.org/doc/qt-5.0/qtqml/qtqml-modules-qmldir.html the qmldir should start with a "module identifier directive".

So the first line in the AbstractUI qmldir is now:

module org.flyingsheep.abstractui

This prevents warnings like:

 

Module 'Sailfish.Silica' does not contain a module identifier directive - it cannot be protected from external registrations.

 

 

(In this case, thrown by Sailfish.Silica, which is currently missing a module identifier directive.)


 
Next Steps

Having made these changes, my library now builds, and I have an libabstractui.so and a qmldir file.

The next step will be to install the library and then import it to LandedSettings. I will post on that soon ….

 

No comments:

Post a Comment