Planet KDE
Message-passing APIs (SIMPL)
In the KDE world, famously there was that weekend where DCOP (Desktop Communicating Objects Protocol) was created, setting the stage for things like KParts. GNOME picked the CORBA object model, and much later the Free Desktop world settled on DBus as a message-passing API. But even at the time, there were other message-passing APIs. At work-work I use one, called SIMPL, which is kind of shout-out to the late ’90s of DCOP.
Please note that my presentation of “history” is just what I remember now of events that were already “tales told ‘round the campfire” 15 years ago. Corrections welcome (by email).
At work-work SIMPL is just a given, and it’s got wrappers and abstractions so that there’s a decent C++ style API around it. At its heart it is a point-to-point message-passing API with no policy at all about the payload of messages. That is both a blessing – no policy means it can be used for whatever kind of messages you think is necessary – and a curse – no policy means that you end up writing a bunch of abstractions to represent the messages that you actually use.
Code at the wrapped-in-C++ level looks something like this (effectively obscuring the underlying transport):
auto reply = CoordinatorTask().Send(requests::GetCurrentUser()); if(reply.has_value()) { do_something(reply.value().username); ...There does not seem to be much online about SIMPL anymore. There is a LinuxDevices article from 2000 when SIMPL was under some active development as an Open Source project, there’s a LWN comment from 2015 that mentions it still, and there’s a Wikipedia article on it, as a historical note. Note that the Website link on wikipedia goes to something that is now a spam domain. I can’t quickly find sources anymore.
I do wonder at the chances of history that made desktop developers at the time entirely miss out on this existing message-passing mechanism – perhaps the SIMPL authors were too focused on industrial automation and not visible in the X11 desktop space, and not visible on SunOS and other platforms where a fair bit of KDE development happened at the time.
One thing that the SIMPL library developers emphasize repeatedly in documentation (there’s a book) is a philosophy of doing one thing and doing it well. So serialization and message payloads are not part of this – no policy. So security and access control are not part of his – no policy. Those concerns are things that can go into a different API layer on top of SIMPL.
Something else that the SIMPL authors emphasize is doing one thing and doing it well. That applies to the applications that use SIMPL, in particular. And that translates, in the depths of the library, to being able to register only one name for an application (for purposes of discovering what other applications there are, each application has a unique name in the system). It translates into a lack of thread safety, due to the use of global state. It translates into a contextless API, so all an application can do is call “give me the next incoming message”. There’s no concept of an event-loop, and no obvious mechanisms for integrating SIMPL message-handling into another event loop (like an X11 loop).
For me personally this means that I need to re-tool my brain during the trip between home and work, switching of Qt wrappers around DBus to work-work wrappers around SIMPL and the subtleties of each. In practice, that means mostly cursing QtDBus (because of the relative amount of time I put into both).
Qt Quick Effect Maker: What's new in Qt 6.8
As the Qt 6.8 Beta 3 was released last week, it is a good time to start talking about what's new in the Qt 6.8 release. This blog post introduces one of those things, the new effect nodes available in Qt Quick Effect Maker. Also included is an example application using all of these effects.
GSoC 2024: Progress Update
I’ve added ECM as a dependency and am now using some of its modules. While this introduces the downside of adding an extra dependency, ECM is fairly common across KDE apps, so it’s reasonable to assume that most users will already have it installed on their systems.
The project now uses the KDEInstallDirs6, KDECMakeSettings, and KDECompilerSettings ECM modules, making the default build settings consistent with the rest of KDE software.
I’ve also integrated ECMAddTests, which has greatly simplified the CMakeLists file related to testing.
PImplThe classes in the library have been refactored to use the PImpl idiom, as suggested by Albert. This improves ABI compatibility and aligns with KDE’s policies regarding binary compatibility issues with C++.
TestingThe testing framework used by the library has been switched from Google Test to Qt Test. Google Test adheres strictly to some Google policies that could potentially be troublesome in the future, such as quickly dropping support for older compilers. Additionally, Qt Test seems to integrate better with KDE’s CI. For instance, Google Test failed to compile on the Android pipeline, but migrating to Qt Test completely resolved this issue without requiring any workarounds.
MankalaTo put MankalaEngine to use, I am developing a GUI, Mankala, which will offer a selection of games from the Mancala family. I’ve already started learning Qt, and developing this will be my primary focus during the remaining weeks of GSoC.
I plan to continue working on this project after GSoC concludes and eventually integrate both Mankala and MankalaEngine into KDE.
New Craft cache 24.08 published
A new Craft cache has just been published. The update is already available for KDE's CD, CI will follow in the next hours or days.
Please note that this only applies to the Qt6 cache. The Qt5 cache is in LTS mode since April 2024 and does not recieve major updates anymore.
Changes (highlights)- Qt 6.7.2
- FFmpeg 7.0.1
- llvm 18.1.8
- boost 1.86.0
- OpenSSL 3.3.1 (for Android too, which was still on 1.1.1v until recently)
- CMake 3.30.0
- Ninja 1.12.1
- Removed qt-installer-framework (Windows)
KDE Craft is an open source meta-build system and package manager. It manages dependencies and builds libraries and applications from source on Windows, macOS, Linux, FreeBSD and Android.
Learn more on https://community.kde.org/Craft or join the Matrix room #kde-craft:kde.org
This week in KDE: System Settings modernization and Wayland color management
Many folks are on vacation right now, but KDE’s tireless contributors still worked hard to bring you a number of improvements anyway, among them some nice System Settings modernization work and improvements to Wayland color management. You’ll find them mentioned below, along with various other improvements!
Notably, we’re back to only 30 15-minute Plasma bugs — the lowest level since February of this year right before Plasma 6 was launched! Essentially, having regained the level of stability we had at the end of Plasma 5 in only 6 months, we’re super well positioned to drive this even further in the coming months. With Plasma 6 offering both stability and features, who says you can’t have it all?
Notable New FeaturesPlasma’s weather widget now shows “feels like” temperatures that take into account the heat index (Ismael Asensio, Plasma 6.2.0. Link 1 and link 2):
And yes, I see that the temperature labels in the forecast view are misaligned! We’ll get that fixed. Notable UI ImprovementsLanded a redesign of System Settings’ Keyboard page to match other similar modern pages and make things easier to find (Evgeniy Chesnokov, Plasma 6.2.0. Link):
Modernized the UI for System Settings’ Thunderbolt page, which also fixed a text readability bug (Ivan Tkachenko, Plasma 6.2.0. Link):
Modernized the UI for multiple pages in System Settings that still use QtWidgets, so that they look a bit more like their more modern QML counterparts (Thomas Duckworth, Plasma 6.2.0 and KDE Gear 24.12.0, link 1, link 2, link 3, link 4, and link 5):
Discover and its System Tray icon now always agree on whether there are any updates available (Harald Sitter, Plasma 6.2.0. Link)
Weather forecasts from the Environment Canada provider now fit in the System Tray popup at its default size, so you don’t have to enlarge it (Ismael Asensio, Plasma 6.2.0. Link)
When you drag an image or other file out of a web browser window and onto the desktop or Dolphin, the drop menu now contains only relevant actions, and with better text and icons (me: Nate Graham, Frameworks 6.6. Link 1 and link 2):
Notable Bug FixesWe accidentally broke SVG wallpaper support in Plasma 6.1.4 with the fixes to Centered placement mode, so now we’ve fixed it again. Sorry about that, everyone! (Marco Martin, Plasma 6.1.5. Link)
Fixed a tricky KWin bug that caused copied text to sometimes not be paste-able into XWayland-using apps (David Edmundson, Plasma 6.2.0. Link)
Worked around a Qt issue that was causing some windows on disconnected screens to sometimes not get moved over to one of the remaining screens as expected (Xaver Hugl, Plasma 6.2.0. Link)
Addressed a few more edge cases for the bug whereby Plasma’s “Show Alternatives” popup wouldn’t close in certain circumstances, so now it should always close when needed (Niccolò Venerandi, Plasma 6.2.0. Link)
Fixed an issue that caused some symbolic icons in Plasma panels to be colored improperly with mixed light/dark global themes (Nicolas Fella, Frameworks 6.6. Link)
Other bug information of note:
- 3 Very high priority Plasma bugs (same as last week). Current list of bugs
- 30 15-minute Plasma bugs (down from 31 last week). Current list of bugs
- 89 KDE bugs of all kinds fixed over the last week. Full list of bugs
Added support for rendering intents and black point compensation to KWin’s implementation of the Wayland color management protocol, and enabled it by default so apps that also implement support for it can make use of it immediately (Xaver Hugl, Plasma 6.2.0. Link 1, link 2, and link 3)
KWin has gained support for the alpha-modifier Wayland protocol (Xaver Hugl, Plasma 6.2.0. Link)
On Wayland, you can now copy to and paste from the system clipboard while in Overview and other KWin effects (Vlad Zahorodnii, Plasma 6.2.0. Link)
Qt 6.8 changed how screen scaling affects icons, so we adapted to those changes to prevent icon blurriness everywhere for people already using Qt 6.8 (Nicolas Fella and Kai Uwe Broulik, Frameworks 6.6. Link 1, and link 2)
Human Interface GuidelinesExpanded the Text and Labels page to include some more symbols that should use real unicode glyphs rather than handmade approximations (Emir SARI, link)
Fixed a number of small typos, punctuation, and grammar issues throughout the text (John Veness, link 1, link 2, link 3, link 4, link 5)
Tweaked a bunch of text labels in Okular to be HIG-compliant by using real ellipses and unicode symbols (Emir SARI, Okular 24.12.0. Link)
KWin’s “Screen Edge” effect has been renamed to “Highlight Screen Edges and Hot Corners” for HIG-compliance and user-comprehensibility (me: Nate Graham, Plasma 6.2.0. Link)
Tweaked the text of Plasma’s critical battery level notifications and System Settings’ unsaved changes dialog to be HIG-compliant and therefore less redundant and more user-friendly (me: Nate Graham, Plasma 6.2.0. Link 1 and link 2)
…And Everything ElseThis blog only covers the tip of the iceberg! If you’re hungry for more, check out https://planet.kde.org, where you can find more news from other KDE contributors.
How You Can HelpOtherwise, visit https://community.kde.org/Get_Involved to discover other ways to be part of a project that really matters. Each contributor makes a huge difference in KDE; you are not a number or a cog in a machine! You don’t have to already be a programmer, either. I wasn’t when I got started. Try it, you’ll like it! We don’t bite! Or consider donating instead! That helps too.
2024 OSPP KDE Project Late-Stage Summary
It's been more than three weeks since the midterm summary, and the project is now nearing completion.
Currently, all the original features of Blinken have been fully implemented in the QML version. The remaining tasks involve UI adjustments, testing, and fixing potential bugs.
Over the past few weeks, I’ve been working on the following:
Integrating Blinken's LogicThe game logic of Blinken is handled by the BlinkenGame class from the original Blinken. The original code design is quite good, with most of the game logic encapsulated in this one class. The separation between the logic and the UI rendering is well done, so all I needed to do was connect the signals from this class in QML.
As for the audio playback in Blinken, the original code used the Phonon library, which is also open-source but does not support Android. Therefore, I replaced it with the QtMultimedia library, which provides cross-platform audio playback functionality.
Android Build for KF6 ApplicationsSome features of Blinken rely on libraries provided by the KF6 framework, such as KF6I18n and KF6Config. When cross-compiling to the Android platform, it's necessary to use the aarch64-linux versions of these libraries. If these libraries are not available on your system, you will encounter the following errors during compilation:
ld.lld: error: /usr/lib64/libKF6XmlGui.so.6.4.0 is incompatible with aarch64linux ld.lld: error: /usr/lib64/libKF6ConfigWidgets.so.6.4.0 is incompatible with aarch64linux ……However, the package manager on my Fedora distribution does not provide these versions. Compiling and installing them one by one from source is too cumbersome. On the advice of the community, I used Craft to handle cross-compilation.
For reference, here is the Craft tutorial: Craft - KDE Community Wiki
Important note: If you encounter installation failures, make sure to clear all contents under craft-kde-android before trying again, as leftover files may cause the installation to fail.
When installing, choose the Arm64 target architecture. If there are remnants from a previous failed installation, it may prevent the option to select the ARM64 architecture.
If you encounter issues like "Permission denied," you’ll need to disable SELinux:
sudo apt-get install selinux-utils sudo setenforce 0Additionally, note that in the virtual machine invent-registry.kde.org/sysadmin/ci-images/android-qt67 provided by the community, the Java version is outdated, preventing the use of Gradle 8.6. You can either manually update the Java version in the docker or use an older version of Gradle.
To use Craft for building applications, you need to write a script called a Blueprint, which describes the libraries your application depends on. These scripts are relatively easy to write, and you can quickly get started by following the community documentation: Craft/Blueprints - KDE Community Wiki.
Using KF6 Framework LibrariesSome of the libraries originally used by Blinken are compatible with the Android platform, while others are not. By referring to the API Documentation, you can check which libraries are supported on Android. In Blinken, the following libraries are Android-compatible:
- CoreAddons
- GuiAddons
- I18n
- XmlGui
I needed to use these libraries in the QML version of Blinken.
The KF6 framework provides a convenient internationalization API, and the usage in QML is almost the same as in QWidget, which allowed me to directly reuse Blinken’s original multi-language support, saving a lot of time.
KConfig is used in Blinken to store high score information and settings. For the high scores, I needed to extract the HighScoreManager class from the original HighScoreDialog file, make some modifications, and then create a new high score interface in QML that connects the signals and slots of HighScoreManager. For the settings functionality, it’s as simple as registering a KConfig singleton in QML :
`qmlRegisterSingletonInstance<blinkenSettings>("org.kde.blinken", 1, 0, "BlinkenSettings", blinkenSettings::self());KF6XmlGui was used in the original Blinken to create the About Blinken Page, About KDE Page, and Handbook Page. Although this library is Android-compatible, it is based on QWidget, while the main interface of Blinken is built with QML. Bringing in QWidget just for these pages didn't seem like a good idea. Luckily, for the Android platform, kirigami-addons provides this functionality. By incorporating it, I also brought in Kirigami, which helps optimize the UI.
After adding new dependencies, it’s important to modify the .kde-ci.yml file to support CI/CD. For more information: Infrastructure/Continuous Integration System - KDE Community Wiki.
Web Review, Week 2024-33
Let’s go for my web review for the week 2024-33.
Why We Picked AGPL - ParadeDBTags: tech, foss, business
I wish more product companies would pick this license. Going for AGPL with a support and/or double license offering is a strong model in my opinion.
https://blog.paradedb.com/pages/agpl
Tags: tech, foss, economics
Interesting initiative. I’m looking forward to the results of this first pilot.
https://www.sovereigntechfund.de/programs/fellowship
Tags: tech, google, monopoly, law, economics
Of course it sounds complicated to break Google up… but that’s not the point. It’s about avoiding its monopolistic position, the fact that it’s complicated is just another symptom.
https://micro.webology.dev/2024/08/14/breaking-up-google.html
Tags: tech, google, browser, web, standard
Yes, please let’s increase the market share of non-Chromium based browsers.
https://endler.dev/2024/the-dying-web/
Tags: tech, security, hacking
Someone was about to get revenge, this gives an interesting exploration.
https://blog.smithsecurity.biz/hacking-the-scammers
Tags: tech, cpu, amd, security
Luckily this kind of very low level vulnerabilities are not too common and difficult to exploit. But when they get exploited all things break loose and you can’t trust your hardware anymore.
https://www.wired.com/story/amd-chip-sinkclose-flaw/
Tags: tech, security, memory
Interesting take, those bugs are more convenient to exploit. Logic bugs are too specific to easily exploit at scale.
https://pacibsp.github.io/2024/why-exploits-prefer-memory-corruption.html
Tags: tech, security, ssh
Clearly a new OpenSSH feature to keep an eye on. This should improved security of the server by default. That said, it needs to be a bit more in the wild before knowing how to best tune it.
https://utcc.utoronto.ca/~cks/space/blog/sysadmin/OpenSSHPerSourcePenaltiesThings
Tags: tech, windows, networking
This is indeed surprising behavior and specific to Windows. If you wonder why TCP connect is slow and you got IPv6 support active this might be why.
https://daniel.haxx.se/blog/2024/08/14/slow-tcp-connect-on-windows/
Tags: tech, python, performance
Interesting dive into some of the performance improvements introduced into recent CPython releases.
https://blog.codingconfessions.com/p/are-function-calls-still-slow-in-python
Tags: tech, python, type-systems
Here is an interesting use of Pydantic to properly model inputs.
https://blog.yossarian.net/2024/08/12/Approximating-sum-types-in-Python-with-Pydantic
Tags: tech, c++, reflection, type-systems, performance
Compile time reflection in C++ will indeed be a big deal.
https://lemire.me/blog/2024/08/13/reflection-based-json-in-c-at-gigabytes-per-second/
Tags: tech, time, databases, sqlite
Looks like a neat extension which can come in handy.
https://antonz.org/sqlean-time/
Tags: tech, databases, postgresql, tools
Looks like an interesting tool for creating anonymized pre-production environments.
Tags: tech, databases, postgresql
Need to duplicate data in Postgres? Several options are on the table.
https://ongres.com/blog/fastest_way_copy_data_between_postgres_tables/
Tags: tech, web, browser, frontend, html
A new HTML attribute to keep an eye on. I can expect people to abuse it with hard to debug problems in the frontend if you don’t know it is there.
https://csswizardry.com/2024/08/blocking-render-why-whould-you-do-that/
Tags: tech, garbage-collector, performance, safety, memory
Interesting, it confirms garbage collectors can be the source of unrecoverable performance degradation in request based systems.
https://brooker.co.za/blog/2024/08/14/gc-metastable.html
Tags: tech, distributed, failure, recovery
Retries are becoming common place to deal with transient errors. That said, they can be a problem with recovery of longer failures due to amplification. There are options on the table to solve this though.
https://medium.com/yandex/good-retry-bad-retry-an-incident-story-648072d3cee6
Tags: tech, design, complexity, performance
Or why anticipating too much is merely a gamble. You can be lucky, but how often will you be? Also I agree that in such cases the performance will be impacted longer term leading to a death by thousands of paper cuts.
https://www.sebastiansylvan.com/post/the-perils-of-future-coding/
Tags: tech, technical-debt, organization, leadership, funny
I’m not sure the incentives are right… it’s better to clean up as you go. Still some places would benefit from such an event from time to time and even if you clean up as you go missed opportunities happen.
https://zaidesanton.substack.com/p/organizing-the-best-cleanathon-your
Tags: tech, organization
Surprisingly, I bumped into this article as I’m wrapping up reading the Team Topologies book. This highlight fairly well some of the concerns I have with it and where it shines. I think it’s right to turn to the principles it’s built on rather than use the model it proposes as a blueprint.
https://martyoo.medium.com/stop-team-topologies-fd954ea26eca
Tags: business, organization, management, strategy
It’s bloody hard to build a strategy. This article is full of good wisdom to make one. This won’t make it really easier, but at least you won’t start in the wrong direction and will be able to know if what you produce is any good.
https://www.cultivatedmanagement.com/how-to-build-a-strategy/
Tags: tech, blender, 3d, funny
Funny short video, I guess it has also some tutorial value to know what you can do with Blender? (and no, you can’t break the fourth wall with it)
https://www.youtube.com/watch?v=gTi_-HGtsDY
Bye for now!
A Fresh Perspective on Things
Can you believe it’s already been almost half a year since Plasma 6.0 came out? Time really flies! The other day I went through some of my 50+ open merge requests on KDE’s GitLab and took another stab at them. Some are four years old at this point but it definitely helped to let them sit for a while and finish them with a fresh new perspective and clear mind.
Places panel tooltip indicating mount point, device name, and free space information Places panel tooltipWhat really grinds my gears is elided labels with no tooltip or other means to see the full text. The Places panel in Dolphin and the file dialogs is one prime example of this. While the default locations have concise names, particularly removable media can have rather long descriptions. Additionally, while you can roughly tell how full the device is by looking at the thin line underneath, there’s no way to know precisely. You either have to browse the device or access the properties dialog through the context menu. I also added the bookmark’s destination and mount points. In case of loop devices, such as ISO images, the path to its backing file is shown instead.
Finally able to see the full text!The main reason I haven’t merged this feature sooner is that under Wayland the tooltips didn’t follow the item as you moved the mouse. You see, Qt reuses that window and just updates its position and text for different controls. Under Wayland, however, windows cannot just position themselves on absolute coordinates. Popup windows, such as menus and tooltips, instead provide a semantic description of where they would like to be placed using an XDG Positioner (part of the XDG Shell protocol that contains many interfaces for desktop-like use cases).
It tells the compositor, among other things, where to anchor to (e.g. a button or menu item) and what to do if it ends up outside the visible area: slide the window to fit or flip it to the other side, and so on. While Qt already used XDG Positioner for the longest time, before Qt 6.8 it did not support the reposition request. Hence the tooltip was placed correctly the first time but subsequently never moved. Since I didn’t want the patch to bitrot any further, I merged it with a check for Qt Wayland >= 6.8, so please don’t be alarmed if you cannot enjoy the feature just set. I figured, we haven’t had tooltips in there for the longest time, hence not having them for another few months is better than a distracting user experience with an influx of bug reports.
Audible feedback when (un)plugging displaysPlasma 6.0 introducted support for the XDG sound theme spec which lets applications play sound effects using a semantic name. Among those are device-added and device-removed events which are played when plugging in and out a USB device. However, there’s more things you can plug into a computer. One logical candidate is output devices: is the cable even plugged in, the projector turned on, or did it just not configure the resolution correctly?
Display detected – naturally by default there’s no such popup!Originally, I planned to implement it as part of the devicenotifications daemon which monitors USB devices. However, once faced with the prospect of having to monitor multiple GPUs using libdrm (note that QScreen is only enabled outputs), I realized: who knows your output devices best? The compositor, of course! Therefore, I started adding output notifications to KWin. The key difference to its normal output management is that I want to be notified of an output device whenever it is present, regardless of whether it is enabled or configured. However, it turns out there’s a KDE-proprietary Wayland protocol for managing output devices for use by our display settings module. As a result I didn’t have to change KWin and could merge this functionality with the devicenotifications daemon after all!
Import VPN configuration on clickA feature both Nico and I worked on independently from each other was the ability to import a new VPN configuration by just clicking on the file. While mine was implemented as a small helper application in Plasma Network Management, Nico put the functionality into the settings module itself by launching it with a special command-line argument. The latter approach has the advantage that it doesn’t duplicate any code dealing with VPN import (it’s all plugin-based and more complicated than you think). Therefore I abandoned my merge request and will let Nico finish his instead.
Import VPN connection by merely opening it from the download finished notification or file manager.Currently it only supports OpenVPN and Cisco VPN configuration files as those are the only ones to actually have a registered MIME type in shared-mime-info and can therefore participate in file type associations. If you use any other VPN provider that Plasma supports, please get in touch so we can figure out a way to support them, too.
In just three weeks a bunch of KDE developers, designers, users, stakeholders, and many others, including myself, will meet up in Würzburg, Germany, for this year’s Akademy. Come join us, it’s always great fun and attendance is free!
Localizing spin box prefixes/suffixes
KDE Frameworks 6.5 brings a little new feature for localizing prefix and suffix texts in spin boxes. It’s also a good reminder of the level of detail we have to pay attention to when preparing our software for being translated.
The problemQt spin boxes can have inline prefix and suffix strings. That’s commonly used for units.
There’s multiple challenges when localizing this:
- Plurals: Depending on the selected quantity different plural forms for prefixes/suffixes might be needed (e.g. “1 cake” vs “3 cakes”). How many plural forms there are depends on the language and can be anywhere between none (e.g. Japanese) and six (e.g. Arabic). CLDR’s Language Plural Rules gives you an idea of the complexity.
- Word order: Not all languages place those texts in the same position. For a percent value for example English uses the % sign as a suffix, while Turkish uses it as a prefix.
So just setting a fixed string doesn’t cut it.
Existing solutionsNone of that is new, and for the plural handling we do have an existing solution in form of KPluralHandlingSpinBox in KF::TextWidgets. It takes a suffix in form of a KLocalizedString, which it reevaluates each time its value changes to show the correct plural form.
This works but has a number of downsides:
- It’s not solving the word order problem, and it’s only handing suffixes.
- It’s using inheritance and thus is harder to integrate with custom or otherwise more complex existing spin box code.
- The use of inheritance is also limiting it to QSpinBox, not helping with e.g. QDoubleSpinBox.
Starting with an idea by Emir Sarı and Lukas Sommer for a solution to the word ordering problem and a suggestion by me to generalize the same approach to cover plural handling as well we ended up with two new methods in KF::I18n.
KLocalization::setupSpinBoxFormatString is the one you’ll most commonly need. It allows to set a KLocalizedString format string on any spin box instance. That format string must contain the special placeholder %v, which represents the current spin box value.
Texts before the %v end up in the prefix and the part after it in the suffix, giving translations control over the word order. This can be used both with and without considering plural forms, as shown in the example below.
// with plural QSpinBox spinBox; KLocalization::setupSpinBoxFormatString(&spinBox, ki18np("Baking %v cake", "Baking %v cakes")); // without plural QDoubleSpinBox doubleSpinBox; KLocalization::setupSpinBoxFormatString(&doubleSpinBox, ki18n("%v%"));As this isn’t relying on inheritance it can be used on QSpinBox, QDoubleSpinBox or any subclass thereof. Being part of KF::I18n also means this is very likely available without needing additional dependencies. All of this should help with a much wider adoption than we ever had for KPluralHandlingSpinBox.
The second new method is KLocalization::retranslateSpinBoxFormatString, which explicitly triggers reevaluating the format string. That’s automatically called when the spin box value changes, but if you are for example supporting runtime language changes you might have the need for manually triggering this as well.
What’s left to doWe need to make use of this. It’s an easy way to contribute, and helps making our software better in other languages than English :)
There’s also the question how to address these issues in QML UIs. Qt’ QML spin box control doesn’t have support for inline prefixes/suffixes, but the problems don’t go away by placing the those texts on the outside.
Generate Python Bindings for C++ code using Shiboken
This will be a guide on how to generate Python bindings for your C++ library using Shiboken. Shiboken is a tool specifically created to build PySide, so it supports Qt code perfectly fine.
The steps described here require the in-progress merge request that adds the necessary code to Extra CMake Modules. I hope that it gets merged soon (I’ll update the post). I’ll use KUnitConversion as an example, because it’s a small library.
We’ll start adding the building instructions. This part is mostly boilerplate code as it’s the same for any library (except for the obvious thing of changing the library name):
1set(bindings_library "KUnitConversion") 2 3set(wrapped_header ${CMAKE_SOURCE_DIR}/python/bindings.h) 4set(typesystem_file ${CMAKE_SOURCE_DIR}/python/bindings.xml) 5 6set(generated_sources 7 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_module_wrapper.cpp 8 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_wrapper.cpp 9 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_converter_wrapper.cpp 10 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unit_wrapper.cpp 11 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unitcategory_wrapper.cpp 12 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_updatejob_wrapper.cpp 13 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_value_wrapper.cpp) 14 15set(qt_libs Qt6::Core) 16 17ecm_generate_python_bindings( 18 PACKAGE_NAME ${bindings_library} 19 VERSION ${KF_VERSION} 20 WRAPPED_HEADER ${wrapped_header} 21 TYPESYSTEM ${typesystem_file} 22 GENERATED_SOURCES ${generated_sources} 23 INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_INCLUDEDIR_KF}/KUnitConversion 24 QT_LIBS ${qt_libs} 25 QT_VERSION ${REQUIRED_QT_VERSION} 26 HOMEPAGE_URL "https://invent.kde.org/frameworks/kunitconversion" 27 ISSUES_URL "https://bugs.kde.org/describecomponents.cgi?product=frameworks-kunitconversion" 28) 29 30target_link_libraries(${bindings_library} PRIVATE KF6UnitConversion) 31install(TARGETS ${bindings_library} LIBRARY DESTINATION "${KDE_INSTALL_LIBDIR}/python-kf6")Let’s see what each part does.
1set(bindings_library "KUnitConversion") 2 3set(wrapped_header ${CMAKE_SOURCE_DIR}/python/bindings.h) 4set(typesystem_file ${CMAKE_SOURCE_DIR}/python/bindings.xml) 5 6set(generated_sources 7 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_module_wrapper.cpp 8 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_wrapper.cpp 9 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_converter_wrapper.cpp 10 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unit_wrapper.cpp 11 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unitcategory_wrapper.cpp 12 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_updatejob_wrapper.cpp 13 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_value_wrapper.cpp) 14 15set(qt_libs Qt6::Core)The first line just defines the name of the Python library we’ll build later. Then we set the header file that includes all the necessary headers of the library. We’ll see that file later. The generated sources list is a bit more complicated, as you need to guess the names of the files generated by Shiboken. Fortunately, you can probably guess the pattern from the example above: the first two files are always the same (the name of the library + _module_wrapper or _wrapper) and the rest is the list of classes defined in your XML file (more about it later). The qt_libs variable just contains a list of the Qt modules that our library requires. You should list all of them, even if one depends on another, because otherwise Shiboken won’t be able to find the include directories.
17ecm_generate_python_bindings( 18 PACKAGE_NAME ${bindings_library} 19 VERSION ${KF_VERSION} 20 WRAPPED_HEADER ${wrapped_header} 21 TYPESYSTEM ${typesystem_file} 22 GENERATED_SOURCES ${generated_sources} 23 INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_INCLUDEDIR_KF}/KUnitConversion 24 QT_LIBS ${qt_libs} 25 QT_VERSION ${REQUIRED_QT_VERSION} 26 HOMEPAGE_URL "https://invent.kde.org/frameworks/kunitconversion" 27 ISSUES_URL "https://bugs.kde.org/describecomponents.cgi?product=frameworks-kunitconversion" 28)This is the magic part. The ecm_generate_python_bindings function takes care of running Shiboken with all the required arguments, building the Python library and a wheel file to publish it on the Python Package Index (pypi.org). It has the following arguments:
- PACKAGE_NAME: Name of the Python library.
- VERSION: Version of the resulting library.
- WRAPPED_HEADER: The header file we talked about above.
- TYPESYSTEM: XML file with the type system information.
- GENERATED_SOURCES: The list of files that Shiboken will generate.
- INCLUDE_DIRS: A list with additional include directories that are required for the library. It’s typically the location where the header files included in the WRAPPER_HEADER are.
- QT_LIBS: The list of Qt libraries as explained above.
- QT_VERSION: The minimum required Qt version.
- HOMEPAGE_URL: A URL to the homepage of the project.
- ISSUES_URL: A URL where users can report bugs.
The last part links the C++ library with the Python bindings and installs it. Now let’s take a look at the header file:
1#pragma once 2 3// Make "signals:", "slots:" visible as access specifiers 4#define QT_ANNOTATE_ACCESS_SPECIFIER(a) __attribute__((annotate(#a))) 5 6#include <KUnitConversion/Converter> 7#include <KUnitConversion/Unit> 8#include <KUnitConversion/UnitCategory> 9#include <KUnitConversion/Value>Nothing exciting there, just the list of includes (and some Qt thing that I don’t understand).
The last file you need is the typesystem definition, where you tell Shiboken which things (classes, structs, enums, namespaces…) you want to include in your bindings and how it should interpret them. You can delete or rename functions, change the return type, modify the input parameters and many other things. You may want to take a look at the documentation because the list of posible options is very large.
1<?xml version="1.0"?> 2<typesystem package="KUnitConversion"> 3 <load-typesystem name="typesystem_core.xml" generate="no" /> 4 5 <namespace-type name="KUnitConversion"> 6 <enum-type name="CategoryId" /> 7 <object-type name="Converter" /> 8 <object-type name="Unit" /> 9 <object-type name="UnitCategory" /> 10 <enum-type name="UnitId" /> 11 <object-type name="UpdateJob" /> 12 <object-type name="Value" /> 13 </namespace-type> 14</typesystem>You need to load the typesystems of the Qt libraries that you are using so Shiboken can understand what your code is referring to. They come included with PySide.
That’s all you need to generate the Python bindings for your library. The last step is building the project as you usually do.
Mastering Cross-platform Desktop Apps
Creating applications for cross-platform compatibility is a modern best practice. It increases deployment flexibility and allows applications to reach a wider audience. However, doing it properly can involve some trial and error. At KDAB, we’ve built many multiplatform desktop applications. Here, we’ve compiled a few insights from that process to help you build better software.
The case for multiplatform applicationsIf you’re not yet sold on building multiplatform applications, here are three straightforward reasons why it makes sense for both you and your users.
- Bigger audience: The most obvious reason for creating a multiplatform application is to reach a bigger audience. Why narrow your potential market share from the start? Targeting all main platforms makes sure you don’t exclude potential users.
- Compiler diversity: Compiling your application across multiple platforms requires using different compilers. This pushes you towards writing standards-compliant code and enhances software quality by exposing compiler-specific warnings and errors.
- Environment consistency: Restricting your builds to a single OS tailors the application to the peculiarities of that environment. Maybe that’s okay in the short term, but if (or when) you move your software, it will create problems.
Setting up the CI build system to only build for the platform you’re actively developing and testing on might seem to save time. However, we recommend that your CI system always builds all platforms. This approach ensures that changes work across all operating systems, preventing developers on other platforms from having to fix your bugs, which is inefficient and error prone.
Why you shouldn’t ignore LinuxMany companies provide Windows and Mac variants of their applications but leave Linux out of the picture. We suggest including Linux for several reasons.
First, if you’re using tools that target both Windows and Mac, adding Linux isn’t too big of a stretch. Even if your main user base doesn’t include many Linux users, you’ve certainly got Linux lovers among your developers. Developers on your team will appreciate the ability to use your application on their favorite platform. Most importantly, the Linux ecosystem is rich with open-source tools for debugging, profiling, and optimizing applications, which can significantly enhance developer productivity and code robustness. Building on all three main platforms ensures you have the widest array of tools to find issues and improve your software.
Multiplatform toolsWhat tools make sense for creating the best multiplatform environment? Here are a few to consider:
- Analyzers, linters, and profilers: Regular use of linters and static analyzers such as Clang Static Analyzer, Clang-Tidy, Clazy, and SonarQube helps maintain code quality by detecting potential errors before they become problematic, while profilers and performance analyzers like Perf, Valgrind, VTune, and Hotspot help find and fix difficult bugs.
- Cross-platform development environments: IDEs such as VS Code, Qt Creator, and Eclipse offer extensive support for multiplatform development. These IDEs can launch multiplatform build environments like CMake, allowing both visual and command-line control over your software development process.
- Containerization and virtualization: Tools like Docker, Kubernetes, VirtualBox, or other VMs can simulate different operating environments on a single hardware platform. This is great for quickly spinning up developers and new development environments and makes for efficient cross-platform testing.
The primary benefit of multiplatform is the flexibility it provides. This flexibility doesn’t just let users choose their platform of choice. It also allows developers to access tools from across the development spectrum and run in environments where they’re most efficient. If this sounds interesting, check out our desktop best practice guide.
About KDAB
If you like this article and want to read similar material, consider subscribing via our RSS feed.
Subscribe to KDAB TV for similar informative short video content.
KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.
The post Mastering Cross-platform Desktop Apps appeared first on KDAB.
Plasma Dialer 24.08 is out
After a long wait, Plasma Dialer 24.08 is finally out. This released is based on Qt6 and contains 17 months of bug fixing as well as small improvements all other the place.
Packager Section
You can find the package on download.kde.org and it has been signed with my Carl's GPG key.