Plasmoid with C++
the screenshot is at the end of this post
I’m developing a Plasmoid for Plasma Mobile. Called KClock-Plasmoid, as its name suggests, it’s a plasmoid for KClock. The goal is to display time, next alarm and stay at system top panel to indicate KClock is running in background.
KClock side
So the goal is pretty simple, and all I have to do is to find a way to share information from KClock to the plasmoid. However the solution isn’t that trivia. As it turned out, DBus is perferred for IPC(Inter-process communication). Before start working on plasmoid, I need to expose some of the class of KClock to DBus first. Since KClock is built upon Qt, I choose to using Q-DBus as it will save a lot of effort than using low level interface. Now the problem is - I don’t know how to use Q-DBus. As usual, I went to the Qt documentation and to my surprise, it spent most content to describe the concept of DBus and compared to Qt’s signal/slot machinism. Although useful as it is, lack of examples meaning I still didn’t know how I can use it in my code. Thankfully, KDE has its own tutorial about DBus and it provides multiple examples. You can find it here.
After thoroughly reading KDE’s tutorial, I begin implementing the DBus interface for KClock just as the tutorial told me. It worked, of course. But the build process is complicated and the source code isn’t so clear. I’m using a c++ header file to generate the XML file describing the DBus interface. And then generating the actually DBus adaptor according to the XML file. It works like this:
C++ header -> XML -> adaptor class -> bind the adaptor in the class I want to expose
I submitted the Merge request anyway and then Nicolas Fella pointed out, the simple user case as KClock shouldn’t follow a complex procedure. I could just use QDBusConnection class directly in the classes I want to expose instead. To be honest, I didn’t know a simple solution exists until then. After some hours of read documentation about QDBusConnection and help from Nicolas Fella, I successfully exposed the classes without the additional source C++ header file and excessive compiling steps.
Plasmoid side
Now we are finally start developing the plasmoid itself. If you don’t know what is a plasmoid, it’s like “widgets” you can find in mobile devices. In plasma, the system tray itself and the icons inside it are all plasmoid. You can add them to desktop too. Normally, the core of a plasmoid is QML file describing its UI and logic. No C++ is required. To get information about system and other apps, you either use Qt Quick’s JS engine or use Plasma’s Data Engine. But to my dismay, you can’t do DBus in Javascript or at least not in Qt’s implementation and Data Engine will be deprecated in Plasma 6. Leave me the only choice of building a plasmoid with C++ plugin. To make things even worse, few tutorials metion how to write a plasmoid with C++. Without a basic skeleton, I reach a dead end.
Well, as you may expected, the story didn’t end here. One of the tutorial did mention a neat tool called kapptemplate
and it provides templates for plasmoid. I installed this tool and generated a skeleton from the option “Plasma QML/C++”, dispite the example itself didn’t quite work, I now at least have a CMakeFile to start with. So, my understanding of how this works is Plasma will load the QML file with a default C++ plugin provids basic functionality, but if you install custom C++ plugin which the base class is Plasma::Applet
, Plasma launches the QML with your Plugin instead.
Now everything is set, I connected the corresponding signal/slot from DBus to my C++ class, set up a timer to update time display every minutes. The rest of development went smooth.
This is the end result.
Ship
Now the only downside of a plasmoid with C++ is it can’t be shipped with “get new stuff” since a plugin need to be installed to system which requires root permission. The best way to ship this would be via operate systems' package manger, I expect this plasmoid to be shipped as part of Plasma Mobile DE since it would be a useful applet aloneside KClock, the default clock app for Plasma Mobile.
If you have any suggestion of other plasmoid you think would be great on Plasma Mobile, welcome to reach me via mastodon or email.
The tutorials and docs I read during the developing:
I want to edit/expand some of the KDE tutorials below, but I’m lazy so I’m not sure.
- KDE DBus tutorial Complex but helping none the less.
- Plasmoid tutorial 0 Data Engine section is outdated and you may just skip it
- Plasmoid tutorial 1 covered a lot but not very detailed
- Plasmoid tutorial 2 written recently and promising, but just enough to get you start. Last edited on 6 January 2020, I hope it doesn’t stop there.
- The docs about plasmoid plugin itslef I haven’t read it thoroughly myself at the time this blog was written
- QDBusConnection maybe the most important thing