Skip to content

Saturday, 30 August 2025

Every year the KDE Community conducts a large-scale field-test of KDE Itinerary, their fantastic travel companion app, disguised as annual community conference. This year’s Akademy takes place in the capital of Germany, Berlin. I have decided to try and exclusively use KDE Itinerary (full trip planner app) and KTrip (focused on public transport) for all my travel needs from and to the venue as well as its accompanying events.

KDE Itinerary travel companion app “Select Departure Stop” page with a grayed out list of recently searched for stops. “Current Location” is highlighted in a “Determining Location…” state
WIP: Finding your way home from dinner with Itinerary

Did you know that you can import various parts of the Akademy website into Itinerary? For example, if you go to the Social Event page and “share” it with Itinerary, it will add date, time, and location of the event to your timeline. This even works with many other websites, such as hotels. Of course, it’s preferred to import the actual reservation but if you don’t have one, you can just paste the hotel website URL into Itinerary, add your check-in and check-out dates, and you’re good to go.

While I won’t be needing it for Berlin, another feature I’ve wanted for a long time is a live currency converter. Itinerary has always displayed the exchange rate when travelling to a foreign country but it didn’t let you input an arbitrary amount and convert it for you. Now on every trip that involves travel to a country using a currency other than your home country, a handy currency converter is displayed.

KDE Itinerary app displaying details of a trip to Atlanta: No compatible power plugs. An interactive unit converter from USD to EUR is pointed at.
Anything you need to know about your trip, now with an interactive currency converter

I realized that we actually didn’t download the currency conversion table anymore. In KDE Frameworks 5 KUnitConversion did that implicitly when you used it but it’s a simple value-based synchronous API and doing an unsolicited blocking network request in there was obviously quite problematic – not just because KRunner is multi-threaded. In Frameworks 6, there’s instead a dedicated update job but you have to run it yourself when needed. On a desktop, KRunner’s unit converter likely already did that which is why this probably went unnoticed but on Android, the app certainly cannot rely on that.

In my opinion, the biggest issue for using Itinerary/KTrip as daily driver to navigate a foreign city, however, was the lack of a “Current Location” option when searching for a departure stop. Sure, when I know where I’m at I can search for the stop by name but what about finding your way back to the hotel from your dinner place? I therefore wrote a prototype to add a button to the stop picker page. It uses Qt Location to get the device’s location and feeds it into a journey request. It’s still very much work in progress and definitely not merged in time for Akademy, so in the meantime you’ll have to use a custom build.

In order to test my changes on an actual Android phone, I used Craft, KDE’s meta build system and package manager. It is super easy to set up for building libraries and applications for any major platform KDE software supports. For Android, it comes with a ready-to-use Docker image containing all the necessary Qt and Android libraries. I just had to configure it to use my local git checkout where I already made some changes and was able to produce a working APK within a couple of minutes. All of that without even touching Android Studio or worrying about getting the right NDK and Gradle version and what not. Great stuff!

I am very much looking forward to seeing you all in Berlin very soon!

Going to Akademy
6 – 11 September 2025
Technische Universität Berlin, Germany

A somewhat recurring problem I encounter in things I work on is the need to compute simplified geographic polygons, or more specifically, simplified hulls of geographic polygons. Here’s an overview on the currently used approach, maybe someone has pointers to better algorithms for this.

Coverage polygons

Geographic polygons are used in a few different places:

  • The Transport API Repository and consumers of it like KPublicTransport use them for describing areas covered by a public transport routing service, to automatically pick a suitable one at a given location.
  • The Emergency and Weather Aggregation Service uses them to describe areas affected by an emergency. Alerts that don’t carry explicit geometry but refer to an external dataset using a geographic code are particularly affected here, as those datasets (e.g. derived from OSM boundaries) are used for many different purpose and thus are often extremely detailed.

Meter-resolution geometry isn’t needed for any of those use-cases, hundreds of meters or even a kilometers are more than sufficient. And using a higher resolution does come at a cost, larger geometry needs to be stored and transferred, and rendering or doing intersection tests becomes significantly more expensive to compute.

Simplified coverage

Applying generic geometry simplification algorithms here isn’t ideal, as we would want a result that is still covering the original geometry, ie. a simplified hull. In the above use-cases covering more area is merely inefficient or maybe mildly annoying, while covering a smaller area can be catastrophic (e.g. someone potentially affected by an emergency not getting alerted).

A bounding box is the extreme case fulfilling that requirement and minimizing the resulting geometry, but we are obviously looking for a more reasonable trade-off between additionally covered area and geometry complexity.

Also, not all additionally covered area is equal here, covering extra area at land potentially impacts more people than covering extra area at sea. Or even more generally, additionally covered area hurts the more the more densely it is populated, with the sea just being the extreme (although not uncommon) case here. None of the below takes any of this into consideration though, but it’s one aspect where I’d expect some room for improving the result.

Douglas-Peucker

An common way to simplify polylines and polygons is the Douglas-Peucker algorithm. What this does is check whether for two points the maximum distance of any point in between to a line from the first to the last one is below a given threshold. If yes, all intermediate points can be discarded, otherwise this is recursively repeated separately for two parts split at the point with the maximum distance.

Animation of Douglas-Peucker algortihm applied to a polyline with 10 points.
Source: Wikipedia, CC-BY-SA 3.0

This is fairly easy to implement, and we have multiple copies of this around in different languages and for different polygon or polyline data structures, e.g. in Marble, KPublicTransport, KPublicAlerts, FOSS Public Alert Server and Transport API Repository.

For sufficiently small thresholds and relatively “smooth” geometries this works quite well, although on its own it doesn’t guarantee the result is a hull of the input.

Results however deteriorate when using a threshold in the same order of magnitude as there are features in the geometry, say a kilometer threshold on a geometry containing a highly detailed Fjord-like coastline.

A set of islands in Alaska with, with an overlay polygon perfectly covering their outlines.
2.6MB GeoJSON input with highly detailed complex coast lines.
The same islands, this time with a very jagged coverage polygon.
Douglas-Peucker result with a threshold of ~1km (0.5% of the overall area width).

And if you push this further, it can also result in self-intersecting polygons, which is something we generally want to avoid here.

Poylgon offsetting

To deal with the fact that Douglas-Peucker doesn’t produce a hull, we could offset or buffer the polygon. That is, enlarging it by moving all points to the “outside” by a given amount.

Implementing that is a bit more involved, so this is usually done by using the Clipper2 library, which seems to be somewhat of the reference implementation for some of the more complex polygon manipulation algorithms.

There’s a few small surprises in there, such as it working with integer coordinates and typos in its API (“childs”), but beyond that it’s reasonably easy to use both from C++ and Python (examples in Marble, KPublicTransport, FOSS Public Alert Server and Transport API Repository).

Simplifying by offsetting

These two steps can also be combined in another way to obtain a simplified hull:

  • Offset the polygon first, by a value large enough that unwanted details will get merged together. E.g. at half their width narrow concave areas such as Fjords disappear that way, islands will get “swallowed” by nearby land, etc.
  • Apply Douglas-Peucker, with a threshold below the offset size. The result will then still be a hull of the original geometry, and since the previous step removed small details that would interfere we get a “smoother” result.
  • Apply a negative offset, to shrink the polygon closer to its original size again. The maximum value to use for that is the value the polygon was initially offset with minus half the threshold used for Douglas-Peucker.

This has proven to be very effective with polygons with highly detailed relatively small concave features, such as land polygons with a Fjord-heavy coastline. And as a welcome side-effect it often also automatically fixes self-intersecting geometry in the input data.

The same islands again, this time with a smoother overlay polygon due to covering also many smaller water features.
Simplified hull, reduced to just 17kB.

It’s not quite as effective on the inverse though, ie. geometry with fine-grained convex features, such as the sea polygon in the above example.

Truncating numbers

There’s a technical simplification orthogonal to the above also worth mentioning when using GeoJSON or other textual formats such as CAP. Printed out naively floating point numbers easily end up with 12 or 13 decimals. That’s enough for a sub-millimeter resolution, which is pointless when working with kilometer-scale features.

It’s therefore also useful to implement adaptive rounding and truncation of the coordinates based on the size of the overall geometry, resulting in just four to six decimals usually in our use-cases, which is a two- to three-times reduction in (textual) size (example).

This only helps with storage and transfer volume of course, the computational complexity of processing the geometry doesn’t change by this.

Can this be done better?

As this isn’t really such an uncommon problem, are there better ways to do this? Ie. are there ways to achieve a higher-quality geometry at the same size or ways to further reduce the size without compromising quality? Are there other algorithms and approaches worth trying?

Welcome to a new issue of This Week in Plasma!

This week saw huge improvements to the Plasma clipboard, KRunner, and drawing tablet support — not to mention a bunch of UI improvements in Discover, and plenty more, too! So without further ado…

Notable New Features

Plasma’s clipboard now lets you mark entries as favorites, and they’ll be permanently saved so you can always access them easily! This is very useful when you find yourself pasting the same common text snippets all the time. The feature request was 22 years old; this may be a new record for oldest request ever implemented in KDE! (Kendrick Ha, link)

Starred /saved clipboard items

Plasma now lets you configure touch rings on your drawing tablet! (Joshua Goins, link)

Discover now lets you install hardware drivers that are offered in your operating system’s package repos! (Evan Maddock, link)

KRunner and KRunner-powered searches can now find global shortcuts! (Fushan Wen, link)

Global shortcuts/actions in KRunner

Notable UI Improvements

Plasma 6.5.0

KRunner and KRunner-powered searches now use fuzzy matching for applications. (Harald Sitter, link)

Fuzzy match in KRunner for “Thunderbirb”

Improved the way Discover presents error messages to be a bit more user-friendly and compliant with KDE’s Human Interface Guidelines. (Oliver Beard and Nate Graham, link 1 and link 2)

Discover now lets you write a review for apps that don’t have any reviews yet. (Nate Graham, link)

On operating systems using RPM-OSTree (like Fedora Kinoite), there’s no longer an awkward red icon used in the sidebar and other places you’d expect black or white icons. (Justin Zobel, link)

KDE Gear 25.12.0

Opening a disk in KDE Partition Manager from its entry in Plasma’s Disks & Devices widget no longer mounts the disk, which is annoying since you’ll then have to unmount it in the app before you can do anything with it. (Joshua Goins, link 1 and link 2)

Notable Bug Fixes

Plasma 6.4.5

Fixed a critical issue that could cause the text of a sticky note on a panel to be permanently lost if that panel was cloned and then later deleted. This work also changes handling for deleted notes’ underlying data files: now they’re moved to the trash, rather than being deleted immediately. Should be a lot safer now! (Niccolò Venerandi, link 1 and link 2)

Fixed a very common KWin crash when changing display settings that was accidentally introduced recently. (David Edmundson, link)

Made a few strings in job progress notifications translatable. (Victor Ryzhykh, link)

Fixed an issue that could allow buttons with long text to overflow from System Monitor’s process killer dialog when the window was very very small. (Nate Graham, Link)

Fixed an issue in the time zone chooser map that would cause it to not zoom to the right location when changing the time zone using one of the comboboxes. (Kai Uwe Broulik, link)

The warnings shown by System Settings’ Fonts page in response to various conditions will now be shown when you adjust all the fonts at once, not only when you adjust one at a time. (Nate Graham, link)

Plasma 6.5.0

Fixed a case where Plasma could crash while you were configuring the weather widget. (Bogdan Onofriichuk, link)

Fixed an issue that could cause System Settings to crash while quitting when certain pages were open. (David Redondo, link)

Plasma is now better at remembering if you wanted Bluetooth on or off on login. (Nicolas Fella, link)

Panels in Auto-Hide, Dodge Windows, and Windows Go Below modes will now respect the opacity setting. (Niccolò Venerandi, link)

Frameworks 6.18

Fixed an issue that caused Plasma to crash when dragging files from Dolphin to the desktop or vice versa when the system was set up with certain types of mounts. (David Edmundson, link)

Other bug information of note:

Notable in Performance & Technical

Plasma 6.5.0

Implemented support for “overlay planes” on single-output setups, which have the potential to significantly reduce GPU and power usage for compatible apps displaying full-screen content. Note that NVIDIA GPUs are currently opted out because of unresolved driver issues. (Xaver Hugl, link)

Implemented support for drag-and-drop to and from popups created by Firefox extensions, and presumably other popups implemented with the same xdg_popup system, too. (Vlad Zahorodnii, link)

Fixed an issue that would cause V-Sync to be inappropriately disabled in certain games using the SDL library. (Xaver Hugl, link)

Undetermined release date

The annotating feature in Spectacle has been extracted into a re-usable library so that it can also be used in other apps in the future! Such integration is still in progress (as is working out a release schedule for the git repo that the library lives in now), but you’ll hear about it once it’s ready! (Noah Davis and Carl Schwan, link)

How You Can Help

KDE has become important in the world, and your time and contributions have helped us get there. As we grow, we need your support to keep KDE sustainable.

You can help KDE by becoming an active community member and getting involved somehow. Each contributor makes a huge difference in KDE — you are not a number or a cog in a machine! You don’t have to be a programmer, either; many other opportunities exist, too.

You can also help us by making a donation! A monetary contribution of any size will help us cover operational costs, salaries, travel expenses for contributors, and in general just keep KDE bringing Free Software to the world.

To get a new Plasma feature or a bugfix mentioned here, feel free to push a commit to the relevant merge request on invent.kde.org.

Friday, 29 August 2025

When travelling, I tend to rely on public Wi-Fi hotspots a lot, for example on trains, while waiting at the station, in cafe’s and so on.

Accepting the same terms and conditions every time gets annoying pretty quickly, so a few years ago I decided to automate this. The project that came out of that is freewifid.

It continously scans for Wi-Fi networks it knows, and sends you a notification when it found one it can automatically connect to. You can then allow it to connect to that network automatically in the future.

A freewifid notification asking whether to connect to a known network

Adding support for new captive portals

Adding support for a new kind of captive portal is pretty easy. You just need to implement a small rust trait that includes a function that sends the specific request for the captive portal. Often this is very simple and looks like this:

pub struct LtgLinkProvider {}

impl LtgLinkProvider {
    pub fn new() -> LtgLinkProvider { LtgLinkProvider {} }
}

impl CaptivePortal for LtgLinkProvider {
    fn can_handle(&self, ssid: &str) -> bool {
        ["Link WIFI"].contains(&ssid)
    }

    fn login(&self, http_client: &ureq::Agent) -> anyhow::Result<()> {
        // Store any cookies the landing page might send
        common::follow_automatic_redirect(http_client)?;

        http_client
            .post("http://192.168.1.100:8880/guest/s/default/login")
            .send_form([
                ("checkbox", "on"),
                ("landing_url", crate::GENERIC_CHECK_URL),
                ("accept", "PRISIJUNGTI"),
            ])?;

        Ok(())
    }
}

For finding out what needs to be sent, you can use your favoute browser’s inspection tools.

For testing, Plasma’s feature for assigning a random MAC-address comes very handy.

Integration with Plasma

It could be interesting to write a KCM for freewifid, so you can graphically remove networks again. Support for ignoring public networks in the presence of a given SSID is also already implemented, but currently needs to be enabled by editing the config file. Writing a KCM is not high on my list of priorities right now, but if this sounds like something you’d like to do, I’d happily help with with the freewifid interfacing parts.

Project

The project is hosted on Codeberg. I’ll happily accept merge requests for additional captive portals there.

There are some prebuilt release binaries, but I’m not too certain they’ll work on every distribution. With a rust compiler installed, the project is very simple to build (cargo build). A systemd unit is provided in the repository, which you can use to run freewifid as a user unit.

Freewifid also supports running as a system service non-interactively for use in embedded projects.

Let’s go for my web review for the week 2025-35.


Open Source is one person

Tags: tech, foss, community, maintenance

This stays true, most projects are maintained by a single person and that’s a problem. Where is the support from all the businesses benefiting from FOSS?

https://opensourcesecurity.io/2025/08-oss-one-person/


The World Runs 20 Billion Instances of Curl. Where’s the Support?

Tags: tech, foss, maintenance, politics

The situation is still complicated for maintainers… And companies benefiting from their free labor don’t get it. This leads to really stupid situations.

https://thenewstack.io/the-world-runs-20-billion-instances-of-curl-wheres-the-support/


Give Your Spouse the Gift of a Couple’s Email Domain

Tags: tech, email, productivity

This is a funny but interesting productivity tip.

https://mtlynch.io/couples-email-domain/


Google says a typical AI text prompt only uses 5 drops of water — experts say that’s misleading

Tags: tech, ai, machine-learning, gpt, ecology, research

We can expect more misleading papers to be published by the big LLM providers. Don’t fall in the trap, wait for actually peer reviewed papers from academia. Unsurprisingly the results aren’t as good there.

https://www.theverge.com/report/763080/google-ai-gemini-water-energy-emissions-study


No, Google Did Not Unilaterally Decide to Kill XSLT

Tags: tech, google, web, xml, xslt, html

Here is another point of view on the XSLT situation in the WHATWG. Clearly the process needs to be made clearer. I’m not necessarily convinced by everything which is brought forth in this piece, still nice to have different point of views on it.

https://meyerweb.com/eric/thoughts/2025/08/22/no-google-did-not-unilaterally-decide-to-kill-xslt/


Google will block sideloading of unverified Android apps starting next year

Tags: tech, google, android, security, vendor-lockin

Unsurprisingly this ecosystem keeps being more and more closed.

https://arstechnica.com/gadgets/2025/08/google-will-block-sideloading-of-unverified-android-apps-starting-next-year/


Citrix forgot to tell you CVE-2025–6543 has been used as a zero day since May 2025

Tags: tech, networking, security

Clearly Citrix is drowning as a product… How can people still trust the provider after such an episode?

https://doublepulsar.com/citrix-forgot-to-tell-you-cve-2025-6543-has-been-used-as-a-zero-day-since-may-2025-d76574e2dd2c


I Hacked Monster Energy

Tags: tech, security

Alright… That’s really bad security practices. Don’t do this at home.

https://bobdahacker.com/blog/monster-energy


ghrc.io Appears to be Malicious

Tags: tech, security, containers, supply-chain

Mind your typos… It seems clear a bad actor is hiding behind that one.

https://bmitch.net/blog/2025-08-22-ghrc-appears-malicious/


Xz format inadequate for general use

Tags: tech, compression, safety

Probably biased, but this raises questions about xz.

https://www.nongnu.org/lzip/xz_inadequate.html


The vulnerability might be in the proof-of-concept

Tags: tech, security

Not every vulnerability reports are born equal… This can be a waste of time when the vulnerability is on the reporter end.

https://sethmlarson.dev/the-vulnerability-is-in-the-proof-of-concept


Pulse: A responsive monitoring application for Proxmox VE

Tags: tech, virtualization, monitoring

Looks like a nice tool to monitor your Proxmox install.

https://github.com/rcourtman/Pulse


Materialized views are obviously useful

Tags: tech, databases, caching, complexity, architecture

Indeed, if you can guarantee your materialized views to always be up to date, you might be able to get rid of some caching… and thus some complexity can be avoided.

https://sophiebits.com/2025/08/22/materialized-views-are-obviously-useful


shared_ptr: the (not always) atomic reference counted smart pointer

Tags: tech, c++, multithreading, memory, atomics, optimization

This is an interesting and deeply buried optimization for the GNU C++ STL implementation. I didn’t expect anything like this.

https://snf.github.io/2019/02/13/shared-ptr-optimization/


io_uring, kTLS and Rust for zero syscall HTTPS server

Tags: tech, linux, kernel, system, performance, networking

We really have nice facilities in the kernel to squeeze some extra performance nowadays.

https://blog.habets.se/2025/04/io-uring-ktls-and-rust-for-zero-syscall-https-server.html


Trying to get error backtraces in rust libraries right

Tags: tech, rust, safety, failure

Clearly the error handling landscape still evolves in Rust and that’s a good thing. The current solutions are too fragmented at the moment.

https://www.iroh.computer/blog/error-handling-in-iroh


Rust for Everyone!

Tags: tech, programming, debugging, learning, rust

Interesting talk. The tools presented can indeed go a long way helping people figure out what’s wrong with a piece of code or learning some of the harder parts of a language.

https://www.youtube.com/watch?v=R0dP-QR5wQo


Go is still not good

Tags: tech, go, criticism

Keep in mind this is a rant, so it likely goes over the top a bit. That said, I first hand encountered some of the constructs mentioned here… I find that surprising in such a recent language indeed.

https://blog.habets.se/2025/07/Go-is-still-not-good.html


You no longer need JavaScript

Tags: tech, web, frontend, html, css

Long but thorough collection of all the nice improvements CSS brought the past few years.

https://lyra.horse/blog/2025/08/you-dont-need-js/


Shader Academy

Tags: tech, graphics, shader, learning

Looks like a neat way to learn shader programming.

https://shaderacademy.com/explore


How to Slow Down a Program? And Why it Can Be Useful

Tags: tech, performance, multithreading

This can be useful indeed to explore concurrency issues. It requires some work though.

https://stefan-marr.de/2025/08/how-to-slow-down-a-program/


Inside Windows 3

Tags: tech, windows, history, architecture, system, complexity

Ever wondered about how Windows 3 was architectured? This is an interesting read. It was really complex though, you can really tell it’s in the middle of several transitions.

https://www.xtof.info/inside-windows3.html


Everything I know about good API design

Tags: tech, web, api, design

Lots of good points in there. Very much focused on web services APIs, that being said the first part also applies to libraries APIs in my opinion.

https://www.seangoedecke.com/good-api-design/


Why I Read Technical Books

Tags: tech, book, learning

I think this is pretty accurate… I have mostly the same reasons.

https://ratfactor.com/b/technical-books


Developer’s block

Tags: tech, programming, motivation

Feeling blocked? Maybe try a few of those things on your project.

https://underlap.org/developers-block/


College students are bombarded by misinformation, so this professor taught them fact-checking 101

Tags: tech, social-media, fake-news, politics, teaching

The approach is good, the results are encouraging as well. Not much effort and a very visible change. We need more such initiatives.

https://theconversation.com/college-students-are-bombarded-by-misinformation-so-this-professor-taught-them-fact-checking-101-heres-what-happened-262409


The Relativity of Wrong by Isaac Asimov

Tags: philosophy, physics, science

A very good essay which reminds us we can’t really reason in terms of absolute right or wrong.

https://hermiene.net/essays-trans/relativity_of_wrong.html?ref=DenseDiscovery-353



Bye for now!

Thursday, 28 August 2025

After I took a longer break from KDE development, I’ve been back in action for a few months now. It’s really nice to be back among friends, hacking on what I like most: Plasma. My focus has been on Plasma Mobile with some work naturally bleeding over into other areas.

Plasma on more Devices

I’d like to share some bits and pieces that I’ve worked on in the past months. Most of my efforts have revolved around making Plasma Mobile suitable for a wider range of devices and use-cases. The purpose of this work is that I want to make Plasma Mobile a more viable base for all kinds of products, not just mobile phones. We have a really mature software stack and great tools and applications which make it relatively easy for companies to create amazing products without having to hire large teams and many years to get the product ready for their market. This is I think a very interesting and worthwhile niche for Plasma to get into and I’m sure that Valve is not the only company that understands this.

Convergence Improvements

Convergence, or rather being able to support and switch between formfactors and usage patterns has always been a pet-peeve of mine and still is.
One area was improving using the available screen real estate use landscape displays (Plasma Mobile has quite naturally been rather “portrait-focused”, though a few smaller patches go a long way.)

Configurable number of columns in the Quicksettings drawer

I also improve usability with different pixel densities in the mobile shell by making the size of the top panel configurable. Also, when plugging in a second monitor, Plasma Mobile now switches from “all apps are maximized” to normal window management. (I’m currently working on KWin supporting more fine-grained window management. Currently, we just maximize all windows which has problems especially with modal dialogs.)

One changeset I worked on earlier this year makes it possible to ship multiple user interfaces for settings modules (“kcms”). An example is the “remote desktop” kcm which now shows a mobile-focused UI in Plasma Mobile. What happens here is that we load a main_phone.qml file in Plasma Mobile (where “phone” is picked from a list of form factors set in the environment of the session, so basically the “main” QML file gets picked based on the device. This mechanism allows us to share components quite easily, reducing the delta between different device UIs.

Mobile and Desktop RDP settings

This actually builds on top of work that I’ve done ten years ago which added support for form factors to our plugin metadata system.
I’ve also made the “Display & Monitor” kcm usable on mobile, this is a pretty important thing to have working when you want to be able to plug in an external monitor into your device. I have a mobile version of the keyboard KCM in the pipeline, too, but this will need a bit more work before it’s ready for prime-time.

More Features

There’s a new page in the mobile Wi-fi settings module, showing connection details and tranfer speeds. The code for this was amazingly simple since I could lift most of the functionality from the desktop panel widget. A shared code-base across devices really speeds up development.

Connection details for the mobile wifi settings

Adding useful features here and there, such as having the list of available bluetooth devices now filtered by default and only showing devices which actually make sense to pair (with an option to “Show all devices” in good Plasma manner). This feature isn’t mobile-specific, so desktop and laptop users will benefit.

Welcome to Okular Mobile

Not all my work goes into infrastructural and “shell” bits. The mobile okular version has now kind of caught up with the desktop version since it got a nice welcome screen when opened. This allows the user to easily open a document either from the “Documents” directory on disk (this is actually configurable) or one of the recent files viewed.

Okular Mobile Welcome Screen

Going to Akademy ’25

After having missed our yearly world conference for a number of years, this year I will be at Akademy again. I’m really looking forward to seeing everybody in person again!

I’m going to Akademy!

See you in Berlin!

We are happy to announce the release of Qt Creator 17.0.1!

Hello again everyone!

I’m Derek Lin also known as kenoi, a second-year Math student at the University of Waterloo.

Through Google Summer of Code 2025 (GSoC), mentored by Harald Sitter, Tobias Fella, and Nicolas Fella, I have been developing Karton, a virtual machine manager for KDE.

As the program wraps up, I thought it would be a good idea to put together what I’ve been able to accomplish as well as my plans going forward.

A final look at Karton after the GSoC period.

Research and Initial Work

The main motivation behind Karton is to provide KDE users with a more Qt-native alternative to GTK-based virtual machine managers, as well as an easy-to-use experience.

I had first expressed interest in working on Karton in early Feburary where I made the initial full rewrite (see MR #4), using libvirt and a new UI, wrapping virt-install and virt-viewer CLIs. During this time, I had been doing research, writing a proposal, and trying out different virtual machine managers like GNOME Boxes, virtmanager, and UTM.

You can read more about it in my project introduction blog!

A screenshot of my rewrite in March 8, 2025.

VM Installation

One of my goals for the project was to develop a custom libvirt domain XML generator using Qt libraries and the libosinfo GLib API. I started working on the feature in advance in April and was able to have it ready for review before the official GSoC coding period.

I created a dialogue menu to accept a VM name, installation media, storage, allocated RAM, and CPUs. libosinfo will attempt to identify the ISO file and return a OS short-ID (ex: fedora40, ubuntu24.04, etc), otherwise users will need to select one from the displayed list.

Through the OS ID, libosinfo can provide certain specifications needed in the libvirt domain XML. Karton then fills in the rest, generating a UUID, a MAC address to configure a virtual network, and sets up display, audio, and storage devices. The XML file is assembled through QDomDocument and passed into a libvirt call that verifies it before adding the VM.

VM information (id, name, state, paths, etc) in Karton is parsed explicitly from the saved libvirt XML file found in the libvirt QEMU folder, ~/.config/libvirt/qemu/{domain_name}.xml.

All in all, this addition (see MR #8) completely removed the virt-install dependency although barebones.

A screenshot of the VM installation dialog.

The easy VM installation process of GNOME Boxes had been an inspiration for me and I’d like to improve it in the future by adding a media installer and better error handling later on.

Official Coding Begins!

A few weeks into the official coding period, I had been addressing feedback and polishing my VM installer merge request. This introduced much cleaner class interface separation in regards to storing individual VM data.

SPICE Client and Viewer

My use of virt-viewer previously for interacting with virtual machines was meant as a temporary addition, as it is a separate application and is poorly integrated into Qt/Kirigami and lacks needed customizability.

Previously, clicking the view button would open a virtviewer window.

As such, the bulk of my time was spent working with SPICE directly, using the spice-client-glib library, in order to create a custom Qt SPICE client and viewer (see MR #15). This needed to manage the state of connection to VM displays and render them to KDE (Kirigami) windows. Other features such as input forwarding, audio receiving also needed to be implemented.

I had configured all Karton-created VMs to be set to autoport for graphics which dynamically assigns a port at runtime. Consequently, I needed to use a CLI tool, virsh domdisplay, to fetch the SPICE URI to establish the initial connection.

The viewer display works through a frame buffer. The approach I took was rendering the pixel array I received to a QImage which could be drawn onto a QQuickItem to be displayed on the window. To know when to update, it listens to the SPICE primary display callback.

You can read more about it in my Qt SPICE client blog. As noted, this approach is quite inefficient as it needs to create a new QImage for every frame. I plan on improving this in the future.

Screenshots of my struggles getting the display to work properly.

I had to manage receiving and forwarding Qt input. Sending QMouseEvents, mouse button clicks, were straightforward and can be mapped directly to SPICE protocol mouse messages when activated. Keystrokes are taken in as QKeyEvents and the received scancodes, in evdev, are converted to PC XT for SPICE through a map generated by QEMU. Implementing scroll and drag followed similarly.

I also needed manage receiving audio streams from the SPICE playback callback, writing to a QAudioSink. One thing I found nice is how my approach supported multiple SPICE connections quite nicely. For example, opening multiple VMs will create separate audio sources for each so users can modify volume levels accordingly.

Later on, I added display frame resizing when the user resizes the Karton window as well as a fullscreen button. I noticed that doing so still causes resolution to appear quite bad, so proper resizing done through the guest machine will have to be implemented in the future.

Now, we can watch Pepper and Carrot somewhat! (no hardware accelleration yet)

UI

My final major MR was to rework my UI to make better use of screen space (see MR #25). I moved the existing VM ListView into a sidebar displaying only name, state, and OS ID. The right side would then have the detailed information of the selected VM. One my inspirations was MacOS UTM’s screenshot of the last active frame.

When a user closes the Karton viewer window, the last frame is saved to $HOME/.local/state/KDE/Karton/previews. Implementing cool features like these are much easier now that we have our own viewer! I also added some effects for opacity and hover animation to make it look nice.

Finally, I worked on media disc ejection (see MR #26). This uses a libvirt call to simulate the installation media being removed from the VM, so users can boot into their virtual hard drive after installing.

Demo Usage

As a final test of the project, I decided to create, configure and use a Fedora KDE VM using Karton. After setting specifications, I installed it to the virtual disk, ejected the installation media, and properly booted into it. Then, I tried playing some games. Overall, it worked pretty well!

List of MRs

Major Additions:

Subtle Additions:

Difficulties

My biggest regret was having a study term over this period. I had to really manage my time well, balancing studying, searching for job positions, and contributing. There was a week where I had 2 midterms, 2 interviews, and a final project, and I found myself pulling some late nighters writing code at the school library. Though it’s been an exhausting school term, I am still super glad to have been able to contribute to a really cool project and get something work!

I was also new to both C++ and Qt development. Funny enough, I had been taking, and struggling on, my first course in C++ while working on Karton. I also spent a lot of time reading documentation to familiarize myself with a lot of the different APIs (libspice, libvirt, and libosinfo).

Left: Karton freezes my computer because I had too many running VMs.

Right: 434.1 GiB of virtual disks; my reminder to implement disk management.

What’s Next?

There is still so much to do! Currently, I am on vacation and I will be attending Akademy in Berlin in September so I won’t be able to work much until then. In the fall, I will be finally off school for a 4 month internship (yay!!). I’m hoping I will have more time to contribute again.

There’s still a lot left especially with regards to the viewer.

Here’s a bit of an unorganized list:

  • Optimize VM display frame buffer with SPICE gl-scanout
  • Improved scaling and text rendering in viewer
  • File transfer and clipboard passthrough with SPICE
  • Full VM snapshotting through libvirt (full duplication)
  • Browse and installation tool for commonly installed ISOs through QEMU
  • Error handling in installation process
  • Configuration and allow modifying of existing VMs in the application
  • Others on the issue tracker

Release?

In its current state, Karton is not feature complete, and not ready for officially packaging and releasing. In addition to the missing features listed before, there have been a lot of new and moving parts throughout this coding period, and I’d like to have the chance to thoroughly test the code to prevent any major issues.

However, I do encourage you to try it out (at your own risk!) by cloning the repo. Let me know what you think and when you find any issues!

In other news, there are some discussions of packaging Karton as a Flatpak eventually and I will be requesting to add it to the KDE namespace in the coming months, so stay tuned!

Conclusion

Overall, it has been an amazing experience completing GSoC under KDE and I really recommend it for anyone who is looking to contribute to open-source. I’m quite satisfied with what I’ve been able to accomplish in this short period of time and hoping to continue to working and learning with the community.

Working through MRs has given me a lot of valuable and relevant industry experience going forward. A big thank you to my mentor, Harald Sitter, who has been reviewing and providing feedback along the way!

As mentioned earlier, Karton still definitely has a lot to work on and I plan continuing my work after GSoC as well. If you’d like to read more about my work on the project in the future, please check out my personal blog and the development matrix, karton:kde.org.

Thanks for reading!

Socials

Website: https://kenoi.dev/

Mastodon: https://mastodon.social/@kenoi

GitLab: https://invent.kde.org/kenoi

GitHub: https://github.com/kenoi1

Matrix: @kenoi:matrix.org

Discord: kenyoy

Catching Up

These last few weeks have been pretty hectic due to me moving countries and such, so I have not had the time to write a blog post detailing my weekly progress, because of this I have decided to compress it all into a singular blog post talking about all the changes I have been working on and what I plan on doing in the future.


The NewMailNotifier Agent

In the last blog post I wrote I talked about the progress that had been made in the newmailnotifier agent, and that in the following weeks I would finish implementing the changes and testing its funcionality. Well, it ended up taking quite a bit longer as I found that several other files had to also be moved to KMail from KDE-PIM Runtime, and these ones were being used in the runtime repo. The files I have found so far and that I have been looking into are:

  • newmailnotificationhistorybrowsertext.cpp
  • newmailnotificationhistorybrowsertext.h
  • newmailnotificationhistorybrowsertextwidget.cpp
  • newmailnotificationhistorybrowsertextwidget.h
  • newmailnotificationhistorydialog.cpp
  • newmailnotificationhistorydialog.h
  • newmailnotificationhistorywidget.cpp
  • newmailnotificationhistorywidget.h
  • newmailnotifieropenfolderjob.cpp
  • newmailnotifieropenfolderjob.h
  • newmailnotifiershowmessagejob.cpp
  • newmailnotifiershowmessagejob.h

The Troublesome Migration Agent

The MR for the singleshot capability in the Akonadi repo was given the green light and just recently got merged. On the other hand, the MR with the changes for the agent received feedback and several improvements were requested.

Most importantly, Carl brought to my attention how recent MR’s by Nicolas Fella removed the job tracker from the migration agent, thus making it unnecessary to add it as a temporary folder. Both the requested changes and the removal of the folder have been carried out, while doing so I even realized that in my singleshot MR I was missing the addition of the new finished()signal in the agentbase header file, which I have now also added.

After doing this though, I once again focused on the problem that persisted, the singleshot capability not working properly. The migration agent would initialize without issue when running the Akonadi server but would then not shut down after completing its tasks. I knew that the isPluginOpen() method worked in sending the finished signal, as when I opened and closed the plugin the agent would shut down correctly.

With the help of my mentor Claudio, we found that the migrations were in fact not even running, the agent would start but the jobs would fail to run, because of this the logic implemented to signal the finilization of a job never had the chance to run, and thus isPluginOpen()remained untouched.

Furthermore, the way I had designed the plugin letting the agent know that it was open had proven to be insufficient, as the migrations (once we get them to run as intended) would emit the jobFinished() signal after concluding, thus triggering the isPluginOpen() method with the default value of false and shutting down the agent, even if the plugin was still open.

The times the singleshot capability did work (when opening and closing the plugin), we also found that the status would show as “Broken” and the statusMessage as “Unable to start”, which may need changing, but most troubling was that the opening of the plugin would not restart the agent, therefore only showing an empty config window. I need to find a way to either restart from the agent itself or notify Akonadi so that it restarts it when the plugin runs.


Current Status and What’s Next

The GSOC concludes next week and these last few weeks have not seen any MR requests from my part, so my plan is to continue with the refactoring beyond the end of the programme, working on completing the NewMailNotifier and Migration agents, as well as dealing with a few of the agents in KMail, namely MailFilter, MailMerge and the UnifiedMailBox.

As of now, the identified issues to solve regarding the Migration agent are:

  • The agent not knowing if the plugin is open or closed when emitting the finished() signal.
  • The migrations not running.
  • The status and statusMessage showing as “Broken” and “Unable to start”, respectively.
  • The agent not being able to restart itself.

In the case of the NewMailNotifier:

  • Complete the transfer of the UI related logic to KMail
  • Test the D-Bus connection and the modified slotShowNotificationHistory()

While there’s still work ahead, I feel that these weeks have been invaluable in terms of learning, debugging, and understanding the bigger picture of how the different Akonadi agents fit together. The experience has been both challenging and rewarding, and I’m looking forward to tackling the remaining issues with a clearer path forward.

Although GSoC is officially ending, this is just a milestone rather than a finish line, and I’m excited to continue contributing to Merkuro and the KDE ecosystem as a whole.

Wednesday, 27 August 2025

Qt for MCUs 2.8.3 LTS (Long Term Support) has been released and is available for download.  This patch release provides bug fixes and other improvements while maintaining source compatibility with Qt for MCUs 2.8 (see Qt for MCUs 2.8 LTS released). This release does not add any new functionality.

For more information about fixed bugs, please check the Qt for MCUs 2.8.3 change log..

As with other Qt products, Qt for MCUs 2.8.3 LTS can be added to an existing installation by using the maintenance tool or via a clean installation using Qt Online Installer.

The standard support period for the Qt for MCUs 2.8 LTS ends in December 2025.