This is an interesting transitional period in the Qt world for desktop applications. We are in the phase where QML is becoming better and better for the use in a Desktop context, even for full fledged applications.
We noticed that there were some bits derived from the many years of experience in Plasma that can be very useful for every application developer out there, that fall pretty much in those categories:
- where to install and how to access QML files.
- integrating KDE pieces, such as the translation system
- how to write an application that is 100% QML and how to distribute it
- how to write an application that is a mix between C++ and QML
- how to write a KCM for systemsettings that is purely based on qml (and doesn’t even link to QWidgets)
Years ago, with the need of having plasmoids implemented with scripted language, we had also the need of having a simple way to distribute those plasmoids around. They are in the end just a bunch of files, that can beany kind of data: the actual source code of the scripts or any needed data assets such as graphics and sounds.
This brought the class Plasma::Package in libplasma, that’s the way to both install/unistall the plasmoid and access any data file or script file from plasmoids.
The problem then posed itself almost identical for things like scripting support in any generic Qt application, like any pack of addons, such as graphics or souds themes.
Same thing for applications based upon QML, that ends up being composed by two parts: purely C++ parts with the central logic and the QML files together any asset that may be needed.
One interesting feature is also that the same files (QML, assets or whatnot) can have versions specific for a particular device, for instance an application may have 99% of the same code between the normal desktop version and one optimized for touchscreen, intended at tablets. Just the few, interested QML files would be duplicated between the desktop and tablet versions.
Since Frameworks 5.6, there is a new tier 2 framework: KPackage, that offers what Plasma::Package offered in libplasma, but with less dependencies and usable by any Qt application that can use a tier 2 framework.
KDeclarative is the KF5 center for all things related to extending QML.
The framework provides several qml import plugins, such as imports specific of a particular KDE Framework.
It also offers two C++ libraries: libkdeclarative and libquickaddons.
libkdeclarative focuses on KDE related functionalities of the QML engine:
- KDeclarative: installs things in the QML engine: such as a KIO-based networkaccessmanager and the 18n() transpations functions.
- QmlObject: A class similar to QQuickView: in which you can just set the url of a QML file or a KPackage instance and it loads it, instances the QQmlEngine etc. The difference with QQuickView is that it’s not graphics based and is not a QWindow, you’ll just have the instantiated QObject *. Useful if your project is not graphic or if you already have a view, and you just want to instantiate a new thing for reparenting it into the view you have.
The other one is libquickaddons that focuses on utilities related to QtQuick, the actual graphical components.
- ManagedTextureNode: it’s a QSGSimpleTextureNode that will manage its own texture, making simpler to implement your own QQuickItem.
- ImageTexturesCache: helps to manage textures by creating images and reference counts them, use it if your QQuickItem starts from QImage.
- KQuickAddons::ConfigModule: the base to do KControlModules based on QML, without dependencies from QWidgets, more on that later :).
QML based applications: QML only
qmlpackagelauncher is a tiny command line tool provided by KDeclarative: it’s used to launch an application that is written in QML-only (no main application executable).
The application QML is intended to be distributed in a KPackage structure, with the QML engine initialized with KDeclarative, therefore having things like the i18n() functions available.
QML based applications: mix of QML and C++
The QmlObject class of KDeclarative can now load files from a KPackage, either by setting an existing KPackage instance to it or just setting the kpackage plugin name, making very simple to load a qml file from a plasmoid-like KPackage structure installed on the disk, such as in you main:
KDeclarative::QmlObject *qmlObj = new KDeclarative::QmlObject; qmlObj->loadPackage("org.kde.example");
For a full application is recomended to use the component ApplicationWindow from QtQuickControls, that’s its own QWindow, so it’s not even necessary to create a QQuickView or QQuickWindow, having the really needed C++ part really just those two lines.
QML based KControlModules
An important part for the ongoing redesign of the Plasma Desktop by the VDG also passes trough writing (and rewriting) modules for Systemsettings or KInfoCenter in QML, to make easy making those franly often outdated UIs beautiful.
One important thing for a mass-migration like that,
ConfigModule has the same API as the old base for kcontrol modules, KCModule, but is a pure QObject, making possible for a future QML-only Systemsettings version.
Start with your old KCModule subclass, keep all the logic in it, but start to scrape off all the QWidget based UI bits and give the class a nice property-based, QML friendly API to read and set the values that will eventually go into the config files.
The actual load and save from the config file, will be done just as in KCModule, by reimplementing ConfigModule::load() and ConfigModule::save().
The UI, QML based part will be provided by a KPackage, with the same name as the component name of the KaboutData of the ConfigModule instance. The QML part will be able to access the configModule instance as the “kcm” global object, just as “plasmoid” is accessible from within the QML code of plasmoids, as well as the ConfigModule QML attached property.