Skip to content

Friday, 14 March 2025

Friday, 14 March 2025

KDE today announces the release of KDE Frameworks 6.12.0.

KDE Frameworks are 72 addon libraries to Qt which provide a wide variety of commonly needed functionality in mature, peer reviewed and well tested libraries with friendly licensing terms. For an introduction see the KDE Frameworks release announcement.

This release is part of a series of planned monthly releases making improvements available to developers in a quick and predictable manner.

New in this version

Baloo
  • [FileContentIndexer] Avoid race on updatedFiles modification. Commit.
  • Extractor: don't try to extract when index failed. Commit. Fixes bug #498236
Breeze Icons
  • Remove themed SmartGit icon. Commit.
  • Let the GNOME icon loader re-color our window-close icons. Commit. Fixes bug #500950
  • Add -symbolic symlinks for value-decrease/increase. Commit. Fixes bug #494086
  • Add MIME-type icons for kdenlive project files. Commit.
  • Fix fill-rule-even-odd.svg and fill-rule-nonzero.svg. Commit.
  • Borrow debug function from Qt documentation. Commit.
  • Simplify qrcAlias to not use as much memory. Commit.
  • Force folder creation. Commit.
  • Remove inkscape icons. Commit.
  • Safe half of memory for duplicate checking. Commit.
  • Add battery-profile-balanced symlink. Commit.
Extra CMake Modules
  • Consider BSL-1.0 as GPL-compatible. Commit.
  • Improve docs for ECM QML modules. Commit.
  • Drop old > 2 cmake version conditional branch. Commit.
  • Require cmake >= 3.16 for the tests too. Commit.
  • Add tests for KDE_INSTALL_APP_TEMPLATES. Commit.
  • Unless setting KDE_INSTALL_APP_TEMPLATES, kde_package_app_templates is skipped when cross-compiling. Commit.
  • Try to also satisfy Google Play's version code constraints. Commit.
  • Generate Gradle version include file as part of ecm_add_android_apk(). Commit.
KArchive
  • KF6 TODOs are now KF7 TODOs. Commit.
  • Kgzipfilter.cpp use nullptr instead of zero. Commit.
  • Use 'const QString' declarations for test filenames. Commit.
  • Move all test data files to data directory. Commit.
  • 7zip: Add default naming for files without a name. Commit. Fixes bug #496175
  • Add error checking for writing back temp files in KTar. Commit.
  • Handle errors in KTar::writeLonglink. Commit.
  • Remove stale TODO. Commit.
  • Refactor KXzFilter::init to use QScopeGuard. Commit.
KCalendarCore
  • Codespell fixes (minor). Commit.
  • Calfilter.cpp - CalFilter::filterIncidence() bail on null incidence. Commit.
  • Recurrence.cpp - shiftTimes() prevent crash on missing or invalid period. Commit. Fixes bug #499470
KCMUtils
  • ScrollView: don't move focus to empty toolbar. Commit.
  • Kcmultidialog: set AccessibleName for ScrollArea. Commit.
  • Kcmultidialog: only focus ScrollArea if scrollable. Commit.
  • Src/kcmultidialog.cpp - prevent a crash in KCMultiDialogPrivate::apply(). Commit.
  • Restore non-default highlight for widget kcms. Commit.
KCodecs
  • Move entities table into read-only data section. Commit.
  • Binary search instead of gperf. Commit.
KConfigWidgets
  • KRecentFilesAction: Don't call into QMimeDatabase to get what we already have. Commit.
KCoreAddons
  • Declare KFormat option flag operators. Commit.
  • Add missing break in switch statement. Commit.
KDeclarative
  • KeySequenceItem: Only steal shortcut if the user accepted. Commit.
KDE Daemon
  • Add Restart=on-failure to plasma-kded6 service configuration. Commit.
KFileMetaData
  • [dump] Always build utility, even when tests are disabled. Commit.
  • [XmlExtractor] Use non-deprecated QDomDocument::setContent overload. Commit.
  • [dump] Build/install utility even when tests are disabled. Commit.
  • Exiv2: Avoid calling enableBMFF for exiv2 >= 0.28.3. Commit.
  • Odf: port to new QDomDocument::setContent version. Commit.
  • [autotests] Remove leftover unused CMake variable. Commit.
  • [ExtractorPlugin] Declare private helpers as deprecated. Commit.
  • [ExtractorCollection] Warn if metadata is invalid. Commit.
  • [ExtractorCollection] Warn if an extractor has no metadata. Commit.
  • [ExtractorPlugin] Improve documentation. Commit. See bug #398101
  • [ExtractorPlugin] Define the interface ID in a single place. Commit.
KGuiAddons
  • Add KKeySequenceRecorder patterns. Commit.
KHolidays
KIconThemes
  • Do not remove all instances of "-symbolic" at once. Commit.
KImageformats
  • Use of heif_context_add_XMP_metadata instead. Commit.
  • Sct: qRound with param bigger than max int is undefined. Commit.
  • Sct: Use height instead of width when calculating dotsPerMeterY. Commit.
  • MicroExif: search for the TIFF signature. Commit.
  • MicroExif: API improvements and minor bugfixes. Commit.
  • Fix compilation error. Commit.
  • Added support for resolution and EXIF/XMP metadata to HEIF. Commit.
  • JXR: Added rotation (transformation) support. Commit.
  • JXR: added support to EXIF metadata. Commit.
  • AVIF: added support to XMP and EXIF metadata. Commit.
  • Added pixel limit detected by experimental tests. Commit.
  • Jxl: fix build with Qt before 6.8.0. Commit.
  • JP2: Disable ICC profile writing when saving an image with OpenJPEG V2.5.3 or lesser and improve the format detection on reading. Commit.
  • Heif: improve handling of grayscale ICC profiles. Commit.
  • Improve printing details when writetest fails. Commit.
  • Update HEIF writetest templates. Commit.
  • Added JXL to CMYK formats. Commit.
KIO
  • KFileItem: fix stat() argument for URLs with local hostname. Commit.
  • KUrlNavigatorButton: Use icon name we got after stat. Commit.
  • KUrlNavigatorButton: Look up icon only when URL is set. Commit.
  • Add background to KUrlNavigator. Commit. See bug #475106
  • Add Fedora Packages search. Commit.
  • Add kde icons to web shortcuts. Commit.
  • Urifilters: Change the query url for wordreference.com. Commit.
  • Remove the spaces between words in the DuckDuckGo provider. Commit.
  • Shorten the Wikipedia search provider. Commit.
  • Kurlnavigator: restrict middle click pasting from selection clipboard. Commit. Fixes bug #486229
  • Filewidgets/kfilefiltercombo: std::copy_if instead of std::remove_if without std::erase. Commit.
  • KDirListerTest:testDeleteCurrentDir: there can be duplicated delete events. Commit.
  • Widgets/kabstractfileitemactionplugin: update header documentation. Commit.
  • Widgets/kabstractfileitemactionplugin: add a TODO KF7. Commit.
  • Fail loading admin.so outside of the KIO PLUGINDIR. Commit.
  • PreviewJob: Don't try to get thumbnail for empty files. Commit.
  • Update broken links in kde_apps urifilter. Commit. Fixes bug #498278
Kirigami
  • ScrollablePage: fix width and height binding loops. Commit. Fixes bug #459284
  • Columnview: Fill width column when only one column is present. Commit.
  • Platform: Use the old color set for disabled colors in PlatformTheme. Commit. Fixes bug #495694
  • Add a PageStack attached property. Commit.
  • Dialog: fix width and height binding loops. Commit. Fixes bug #494420
  • Controls, layouts: set Accessible.name for Mnemonics. Commit.
  • Mnemonicattached: add plainTextLabel property. Commit.
  • Primitives/Separator: mark as non-focusable for a11y. Commit.
KNotifications
KPTY
KStatusNotifieritem
  • Do not crash if KDE platform integration is loaded but SNI is unavailable. Commit. Fixes bug #350785
KTextEditor
  • Remove static_assert to avoid compiler warnings. Commit.
  • Add "gc" motion for vim to Toggle Comment. Commit. Fixes bug #490195
  • Fix boundary condition in argument hint navigation. Commit.
  • Fix line no info tooltip persists on right click. Commit.
  • Improve wording of Copy as HTML whatsthis. Commit.
  • Add "Copy as HTML" to context menu. Commit.
  • Don't reset revision on reload but increment it. Commit. Fixes bug #499311
  • Katedocument: Optimize mimeType. Commit.
  • Compute at least inside cursorToX with floats. Commit. Fixes bug #499669
  • Fix scrolling to search results in wrapped long lines. Commit. Fixes bug #448765
  • Renderer: simplify text ranges comparison function. Commit.
  • Add direct camel/subword movement actions. Commit.
KUnitConversion
  • Rename variable as KFUNITCONVERT_NO_DOWNLOAD. Commit.
KWallet
  • Remove superfluous spaces and quotes from debug output. Commit.
KWidgetsAddons
  • Allow limiting the selectable range of a KDatePicker. Commit.
  • KFontRequester: Force frame around sample label. Commit.
  • Correct DateKeywords option check in KDateComboBox::initDateWidget. Commit.
  • Set a QComboBox placeholder when KSelectAction is on a toolbar. Commit.
  • KActionMenu: Apply popupMode to existing widgets. Commit.
  • Add 1840d8fb to .git-blame-ignore-revs. Commit.
  • Run clang-format. Commit.
  • KCapacityBar: Allow to specify state in drawCapacityBar. Commit.
  • Fix popup menu position. Commit.
KWindowSystem
KXMLGUI
  • Delay accepting the bugreport dialog. Commit. Fixes bug #482240
  • Add KKeySequenceWidget::patterns property. Commit.
  • Add KKeySequenceWidget::recording property. Commit.
Network Manager Qt
  • Expose AccessPoint bandwidth property. Commit.
Purpose
  • Plugins: make name and actiondisplay more consistent. Commit.
Syntax Highlighting
  • Fix XML syntax for Hjson syntax highlighting. Commit.
  • Add syntax highlighting file for Hjson (syntax extension to JSON). Commit.
  • Don't ignore the result of QFile::open. Commit.
  • Adjust stan tests to new hl state. Commit.
  • Update Stan language for newer keywords. Commit.
  • Add example SPDX and alerts comments in test.gleam. Commit.
  • Replace inlined license by SPDX-License-Identifier in gleam.xml top comment. Commit.
  • Refactor alerts keywords to crash keywords and add import keyword list. Commit.
  • Increment gleam.xml version number. Commit.
  • Add example documentation comments. Commit.
  • Refactor comments and improve import highlighting. Commit.
Threadweaver
  • Increase required CMake version for example. Commit.

Thursday, 13 March 2025

One of the biggest behind-the-scenes changes in the upcoming Plasma 6.4 release is the split of kwin_x11 and kwin_wayland codebases. With this blog post, I would like to delve in what led us to making such a decision and what it means for the future of kwin_x11.

Background

KWin started as an X11 window manager almost two and a half decades ago. Over the course of the years, it transformed drastically. It gained support for compositing on X, and it became a Wayland compositor.

Sharing the same codebase was critical in the early days of kwin_wayland. We already had working window management abstractions, which had been tested for many years, so we could reuse them on Wayland instead of writing new from scratch. Also, if kwin_x11 gained a new feature, then kwin_wayland would likely gain it for free too.

As time went by, kwin_wayland outgrew kwin_x11. They still shared code but they became quite distinct projects with different mental models how things operate, e.g. how pixels get on the screen or how input works. It also didn’t help that many Plasma developers jumped the X11 ship and turned to the Wayland side as part of the “eating your own dog food” practice, which eventually led to the feature freeze in KWin/X11 back in 2018 due to the lack of sufficient testing and various breakages.

Some time around 2020, we started taking a more bold and aggressive approach to Wayland session development because we saw that Plasma Wayland was trailing behind other desktop environments and something had to be changed in order to catch up. Such a policy produced great results, and Plasma is now one of the leading Wayland desktop environments. Unfortunately, it also greatly contributed to the number of regressions in the X11 session.

Another issue was that there were some features that we couldn’t make work as expected on Wayland so we had to drop them for everyone, which understandably made X11 users unhappy.

Goals

A few years ago, we started contemplating the idea of splitting the X11 and Wayland codebases because of the growing list of regressions affecting the X11 session, and architecture restrictions imposed on KWin/Wayland by the way KWin/X11 works.

That would allows us to keep KWin/X11 working as is without it breaking too often and freely change KWin/Wayland in ways that we think are best suited to make the Plasma Wayland session even better. Of course, it is not a silver bullet solution: we replace one problem with another problem (mainly related to maintenance and ensuring interface compatibility between two projects).

Details

After various discussions online and at Akademy and also seeing (impressive) Plasma Wayland usage statistics, we decided that it’s the right time to do such a split. The main kwin repository is going to host KWin/Wayland, while the kwin-x11 repository is going to host KWin/X11.

KWin/X11 and KWin/Wayland are co-installable so users can freely switch between the X11 and Wayland sessions back and forth and also make sure that updating to 6.4 is not a big hassle for distributions. You’ll be able to have only KWin/X11 or only KWin/Wayland on your computer, or both.

The codebase split doesn’t affect Xwayland support in KWin/Wayland. In other words, X11 applications will continue running on Plasma Wayland.

Extensions

Like any other Plasma component, KWin’s functionality can be extended using plugins. There’s good and bad news. The good news is that extensions written in JavaScript and QML (for example, fancy effects that are available at the KDE Store) will continue working both with kwin_x11 and kwin_wayland as expected, so extension developers don’t need to do anything about it. The bad news is that C++ extensions should be specifically targeted for kwin_x11 and kwin_wayland because neither provides API and ABI compatibility guarantees for its C++ API.

As Wayland progress moves forward, it is likely that the scripting API of KWin/Wayland will be further extended.

Future of KWin/X11

KWin/X11 will be still maintained for the foreseeable future. But that maintenance work will boil down to fixing build errors, adapting to new KDE Frameworks and Plasma APIs, and backporting window-related fixes from KWin/Wayland. There are no plans to drop KWin/X11 in the Plasma 6 lifecycle, although it’s highly possible that it will happen in Plasma 7.

KWin/X11 won’t receive new features anymore; until recently, it received new features that had been developed against KWin/Wayland passively (because both lived in the same repository). However, it might be actually a good thing because the X11 session doesn’t receive that much testing nowadays.

Wednesday, 12 March 2025

Qt Contributor’s Summit 2025 is taking place in Munich in May. Unfortunately, I won’t be able to make it this year, so let’s talk about some of my recent contributions to our favorite cross-platform UI toolkit.

KWrite (Text editor) window displaying a snippet of C++ code. Context menu over its right scroll bar containing the standard Qt options (Scroll here, Top, Bottom, Page Up/Down, Scroll Up/Down) and new KWrite-specific entries (Show scrollbar marks, show scorllbar mini-map)
KWrite with quick access to its scrollbar settings

A couple of years ago I added a context menu to the line number bar in KWrite and Kate. Rather than having to go to the menu to toggle automatic line breaks or bookmarks, those options were now accessible from the context menu. I’ve always wanted to do the same to the scrollbar and have a mini-map option there. However, it wasn’t possible to extend the default context menu and I didn’t want to re-implement all of its Up/Down/Pg Up/Pg Down/etc logic. I therefore added a QScrollBar::createStandardContextMenu method similar to what QLineEdit has. As the name implies, it builds the regular context menu and hands it to you, so you can add your own actions to it.

Speaking of menus, I uplifted SH_Menu_SelectionWrap that decides whether menu selection wraps around when using the arrow keys from QStyle to QStyleHints. This allows Qt Quick Controls Menu to behave the same as QMenu. This behavior is off by default on macOS, for instance, and our own Qt Quick Controls 2 Desktop Style currently handles keyboard input itself to implement wrapping.

I’ve talked about it before that I sometimes just fire up a profiler and look at application startup performance. That’s while working on KWrite I noticed that it was spending a good amount of time parsing the shared-mime-info database. It’s basically a huge XML file containing information about all file types there are and how to detect them, either by file extension or by magic bytes within. Now, why would it even load that database when opening a blank new document?

There’s several places where KWrite and the underlying KTextEditor Framework need to know the type of a viewed file: to load the correct syntax highlighter, display the correct file icon in the tab bar and recent documents list, and so on. When the file type isn’t already known it tries to guess from its contents. Qt caches the database of course but the first one to create a QMimeDatabase triggers a load. However, none of this really matters for an empty document so it now assumes an empty document be of type text/plain. The correct type is actually application/x-zerosize but that’s really not what you want here.

Global Shortcuts settings, shortcut “Switch to next keyboard layout”, default Meta+Alt+K and a custom shortcut “Keyboard” pointed at by the mouse cursor
Using the “Keyboard” key to switch keyboard layouts, eh?

My trusty ThinkPad has a “keyboard key” (Fn+F11) which under Windows supposedly opens some keyboard settings page. For the longest time, I thought it just wasn’t supported under Linux because I couldn’t create a global shortcut with it. Recently I noticed in KWin’s Debug Console that it did in fact recognize the key. Turns out Qt just didn’t have a corresponding Qt::Key. Starting from Qt 6.10 there will be a new Qt::Key_Keyboard value.

Qt Wayland Client

Since last time I talked about Qt Wayland, I have done a few more optimizations to its SHM (Shared Memory) backing store. It’s the canvas that Qt provides to software-rendered applications for drawing their user interface.

I finally merged support for scrolling the backing store. This lets an application, such as a text editor or terminal emulator, optimize scrolling through a view by merely moving the pixels and filling in only the small gap that’s now left. Unfortunately, this optimization cannot be provided when using fractional scaling because there’s no integer number of pixels we can just move up or down.

Furthermore, Qt Wayland no longer uses a backing store with alpha channel if the window didn’t request one. Most toplevel application windows are opaque after all. It doesn’t really matter from the compositor’s POV since a wl_surface can carry an “opaque region” that indicates what part of the window is actually opaque and Qt sets it accordingly. ARGB32 and RGB32 are the same in-memory size, too. Nevertheless, not using an alpha channel lets Qt skip certain operations, such as clearing the paint area before starting to draw.

While investigating a performance problem in animations under Wayland, I noticed that StackView’s new pushItem methods didn’t use any animation by default. As part of the effort to give QML tooling, such as qmlcachegen and qmllint, more context, many generic methods were supplemented by proper overloads. For example, StackView.push(var) takes either an Item, a Component, or a URL but you could call it with anything and that’s why it has to be invoked dynamically. StackView.pushItem on the other hand is declared three times with an explicit type which allows to generate more efficient code.

It didn’t make much sense that they would behave differently, of course. Indeed online documentation clearly said “If no operation is provided, PushTransition will be used.” We concluded it was a copy-paste mistake and I changed this for Qt 6.8.3, even though it’s technically a behavior change.

I’ll be jealous of your Weißwurstfrühstück in Munich and am looking forward to attending Qt Contributor’s Summit again in 2026!

Tuesday, 11 March 2025

The last maintenance release of the 24.12 cycle is out.

  • Fix audio playback breaks when switching between bin clips. Commit. See bug #500491.
  • Fix crash on single item deletion in group. Commit.
  • Fix crash pasting clips with a same track transition (like dissolve). Commit.

The post Kdenlive 24.12.3 released appeared first on Kdenlive.

Last week I decided to clean up a bit of digital cruft. That is, I moved a few of my websites onto a single VPS, saving quite a bit of monthly server hosting costs.

What I did was that I moved VPSes from Linode (Akamai) to DigitalOcean, but also migrated a full web hotel from One to DigitalOcean (converting email accounts to email forwards).

As this is something that I do very rarely, I decided to document the process here so that I don’t have to look everything up again next time around.

The grunt work was about migrating a number of L*MP services to a LEMP server. There are a couple of tasks involved here, mainly migration of databases and getting WordPress running in a subdirectory using Nginx. The rest of the exercise had to do with the moving of nameservers and waiting for DNS propagation to get certbot to provide certificates for the new location.

Migration of MySQL databases

The migration of a database between machines can be broken down into three stages:

  1. Dumping the old database
  2. Creating a new database and user
  3. Sourcing the database contents into the new database

I choose to do it in these three stages, as I’d like to keep the old database dump as an additional backup. The other option would be to transfer the database contents in a single step, merging steps 1 and 3 into one

Nevertheless, I use mysqldump to dump the database contents, and then bzip2 to reduce the size of the dump. This is efficient since and SQL dump is quite verbose.

mysqldump -u username -p --databases databasename | grep -vE \"^(USE|CREATE DATABASE)\" | bzip2 -c - > dumpname.sql.bz2

This is derived from the answer by Anuboiz over at stack overflow. The resulting file is then transferred to the new server using scp together with the actual website.

The next step is to create a new database and a new database user. Here, I assume MariaDB (using the mysql commands), as my main target is WordPress. For other database engines, e.g. Postgresql, please check the docs for exact grammar, but the SQL commands should be very similar.

sudo mysql
mysql> CREATE DATABASE databasename;
mysql> USE databasename;
mysql> CREATE USER 'username'@'localhost' identified by 'password';
mysql> GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES, RELOAD on databasename.* TO 'username'@'localhost' WITH GRANT OPTION;
mysql> EXIT

Check out this digital ocean tutorial for details on the above commands.

The next step is to read the database contents into the new database. For this, we need to unzip the sql dump, e.g. bunzip2 dumpname.sql.bz2, which will result in a file called dumpname.sql. Please notice that bunzip2 unzips the file and removes the original, zipped, file. If you want to keep the original, use the -k option.

Once you have the dumpname.sql file available, you can read it into the database with the newly created user using the source command as shown below.

mysql -u username -p
enter the password here
mysql> USE databasename;
mysql> SOURCE dumpname.sql;
mysql> EXIT

Now you should have a new database with the old database contents on the new server, with an associated database user. For WordPress sites, make sure that you reflect any changes in the associated wp-config.php file.

WordPress in a subdirectory using Nginx

The other piece of the puzzle that was new to me was to run WordPress from a subdirectory, e.g. example.com/blog/, rather than from the root level, e.g. example.com/.

Removing most of the nginx server configuration, the following parts does the magic:

server {
        root /var/www/thelins.se;
        index index.php index.html;

        server_name thelins.se www.thelins.se;

...

# For root
        location / {
                try_files $uri $uri/ /index.php?$args;
        }

# For subdirectory
        location /johan/blog/ {
                try_files $uri $uri/ /johan/blog/index.php$args;
        }

        location ~ \.php$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
                fastcgi_index index.php;
                include fastcgi.conf;
        }

...
}

The trick was to ensure that the subdirectory try_files statement refer to the correct index.php. Notice that this has to be done for each WordPress instance, if you happen to have multiple WordPress installations in various subdirectories on the same domain.

Conclusions

Its a bit of hassle to migrate a lot of web sites at once, but the monetary saving from moving the low traffic sites onto a single VPS, and the simplification of the management and monitoring by moving all VPSes to a single provider makes it worth it.

Tuesday, 11 March 2025. Today KDE releases a bugfix update to KDE Plasma 6, versioned 6.3.3.

Plasma 6.3 was released in February 2025 with many feature refinements and new modules to complete the desktop experience.

This release adds two weeks’ worth of new translations and fixes from KDE’s contributors. The bugfixes are typically small but important and include:

  • Breeze: Do not cascade header colors when using non-global color scheme. Commit.
  • Breeze: Kstyle/breezetoolsareamanger.cpp: menu bar colors from header. Commit.
  • Breeze: Fix Qt6 build regression with MinGW. Commit. Fixes bug #500106
View full changelog

Monday, 10 March 2025

Today I’m going to talk about something a bit different. Maybe very different!

After six years at Blue Systems GmbH, I’ve had the privilege of working daily with some of the finest and most ethical engineers I’ve ever known; lots of people whose names you probably recognize, because they’re some of the biggest contributors to Plasma and KWin, and regularly appear in This Week in Plasma.

Starting earlier this month, about a dozen of Blue Systems’ current people — myself included — have moved over to a new company named Techpaladin Software that’s co-owned by me and someone else you probably know: David Edmundson!

No, this isn’t some kind of hostile takeover or internal corporate backstabbing. 🙂 Rather, it’s the result of a mutual decision made between the owner of Blue Systems, myself and David Edmundson, and Blue Systems’ other personnel who are moving over.

Practically nothing changes for KDE: Techpaladin will sponsor almost all of the same people Blue Systems did, and they will continue to enjoy the same wide latitude to improve KDE software for a living with a high level of personal and professional freedom. Techpaladin will be a KDE e.V. Patron, too. Keeping this transition as smooth as possible was a major goal here!

I’m incredibly grateful to Blue Systems for the personal and professional opportunities I’ve had over the past six years. Working on KDE for a living has been one of the greatest privileges I’ve ever been blessed with — undoubtedly the most satisfying years of my career, and I have Blue Systems to thank for it.

Wait what

Yeah for real! To be honest, in the beginning of this process, I was as surprised to learn about the opportunity as you may be while reading about it right now.

Now, I’ve been a business owner before, but admittedly only at a smaller scale, running a two-person 3D printer company from 2011 through 2014. In fact, some of you who were around for the early days of 3D printing and the RepRap project might remember a company bearing the similar name of “Techpaladin Printing“. That’s right, this was my company! Back then, we helped fellow community members people build MendelMax 3D printers (you can find an archived build guide of mine linked to on that page) from our parts and kits, starting with a humble order of 250 plastic Igus bushings — which at the time could only be purchased in commercial quantities, not at retail. It was my first serious exposure to FOSS (and FOSH!) principles in action, and also where I first fell in love with the movement.

Techpaladin is a much bigger business, of course — with a headcount of over a dozen spread across 7 countries and 2 continents, more complicated accounting, and a co-owner. There are a lot of moving parts; the setup process has been challenging for sure. But I think we’re up to the task!

So this is you throwing off the mask and revealing yourself as some kind of evil techbro corporate oligarch, right? I knew it!!!

And you should buy my new cryptocoin, too! 🫨

But seriously, setting up this enterprise has refocused my conviction that while organizing a business is real work that can be done well or poorly and should not be discounted, the true value in a company is generated by the workers — and those workers should be the overwhelming beneficiaries of that value. I’m still me, and my primary goal remains to propel KDE to world domination! Techpaladin is simply a new and powerful arrow in that quiver, particularly on the topic of helping people make careers out of KDE — a topic near and dear to my heart.

On a personal level, I fully intend to continue working on KDE software in my technical and organizational capacities, in addition to my new tasks managing the business. For example, you can see I’m still publishing This Week in Plasma, still doing technical work, still reviewing other people’s merge requests, and still triaging bug reports.

I’m sure I’ll make some dumb mistakes as I find my way on this journey, and be deservedly criticized for them. When that happens, I’ll try my best to learn from them and do better in the future. So thanks in advance for bearing with me!

What’s your business model?

Like Blue Systems, Techpaladin is a software consultancy, and clients can pay for work on KDE software. And we’re inheriting Blue Systems’ contract with Valve Inc. as our first client! So Techpaladin will continue to maintain and develop large amounts of KDE software relevant to the Steam Deck.

In that case, can you fix this awful bug I’m experiencing?

Why yes, as a matter of fact! If you’d like to sponsor a bug fix — or a new feature, or custom development work of any kind — do get in touch. Techpaladin draws from the same deep well of top Plasma talent that Blue Systems did.

Are you hiring?

Not at the moment. We just got started, but if things go well, we will be open to hiring! If and when that time comes, I’ll announce it publicly.

Wow, what a weird thing to happen

Isn’t it!? The world is a weird place, and if there’s anything I feel like it’s been trying to teach me over the past five months, it’s that you can’t really predict anything. I think all you can do is be flexible in the face of events, and try to make a positive difference within the sphere of what you do have influence over, so that’s what I’m aiming for here.

Thanks as always for your time, everybody, and let’s continue to propel KDE to ever greater heights together. Today I’m feeling even more optimistic that the absurd goal of getting KDE software onto every device on the planet is actually doable!

Model/View Drag and Drop in Qt - Part 2

In the previous blog, you learned all about moving items within a single view, to reorder them.

In part 2, we are still talking about moving items, and still about inserting them between existing items (never overwriting items) but this time the user can move items from one view to another. A typical use case is a list of available items on the left, and a list of selected items on the right (one concrete example would be to let the user customize which buttons should appear in a toolbar). This also often includes reordering items in the right-side list, the good news being that this comes for free (no extra code needed).

Blog_Drag&Drop_Qt_part2-step1

Moving a row between treeviews, step 1

Blog_Drag&Drop_Qt_part2-step2

Moving a row between treeviews, step 2

Blog_Drag&Drop_Qt_part2-step3

Moving a row between treeviews, step 3

With Model/View separation

Example code for flat models and example code for tree models.

Setting up the view on the drag side

To allow dragging items out of the view, make sure to do the following:

☑ Call view->setDragDropMode(QAbstractItemView::DragOnly) (or DragDrop if it should support both).

☑ Call view->setDragDropOverwriteMode(false) so that QTableView calls removeRows when moving rows, rather than just clearing their cells

☑ Call view->setDefaultDropAction(Qt::MoveAction) so it's a move and not a copy

Setting up the model on the drag side

To implement dragging items out of a model, you need to implement the following:

class CountryModel : public QAbstractTableModel
{
    ~~~
    Qt::ItemFlags flags(const QModelIndex &index) const override
    {
        if (!index.isValid())
            return {}; // depending on whether you want drops as well (next section)
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
    }

    // the default is "return supportedDropActions()", let's be explicit
    Qt::DropActions supportedDragActions() const override { return Qt::MoveAction; }

    QMimeData *mimeData(const QModelIndexList &indexes) const override; // see below

    bool removeRows(int position, int rows, const QModelIndex &parent) override; // see below
};

More precisely, the check-list is the following:

☑ Reimplement flags() to add Qt::ItemIsDragEnabled in the case of a valid index

☑ Reimplement supportedDragActions() to return Qt::MoveAction

☑ Reimplement mimeData() to serialize the complete data for the dragged items. If the views are always in the same process, you can get away with serializing only node pointers (if you have that, e.g. for tree models) and application PID (to refuse dropping onto another process). Otherwise you can encode the actual data, like this:

QMimeData *CountryModel::mimeData(const QModelIndexList &indexes) const
{
    QByteArray encodedData;
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
    for (const QModelIndex &index : indexes) {
        // This calls operator<<(QDataStream &stream, const CountryData &countryData), which you must implement
        stream << m_data.at(index.row());
    }

    QMimeData *mimeData = new QMimeData;
    mimeData->setData(s_mimeType, encodedData);
    return mimeData;
}

s_mimeType is the name of the type of data (make up a name, it usually starts with application/x-)

☑ Reimplement removeRows(), it will be called after a successful drop. For instance, if your data is in a vector called m_data, the implementation would look like this:

bool CountryModel::removeRows(int position, int rows, const QModelIndex &parent)
{
    beginRemoveRows(parent, position, position + rows - 1);
    for (int row = 0; row < rows; ++row)
        m_data.removeAt(position);
    endRemoveRows();
    return true;
}

Setting up the view on the drop side

☑ Call view->setDragDropMode(QAbstractItemView::DragDrop) (already done if both views should support dragging and dropping)

Setting up the model on the drop side

To implement dropping items into a model (between existing items), you need to implement the following:

class DropModel : public QAbstractTableModel
{
    ~~~
    Qt::ItemFlags flags(const QModelIndex &index) const override
    {
        if (!index.isValid())
            return Qt::ItemIsDropEnabled;
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable; // and optionally Qt::ItemIsDragEnabled (previous section)
    }

    // the default is "copy only", change it
    Qt::DropActions supportedDropActions() const override { return Qt::MoveAction; }

    QStringList mimeTypes() const override { return {QString::fromLatin1(s_mimeType)}; }

    bool dropMimeData(const QMimeData *mimeData, Qt::DropAction action, 
                      int row, int column, const QModelIndex &parent) override; // see below
};

☑ Reimplement supportedDropActions() to return Qt::MoveAction

☑ Reimplement flags()
For a valid index, make sure Qt::ItemIsDropEnabled is NOT set (except for tree models where we need to drop onto items in order to insert a first child).
For the invalid index, add Qt::ItemIsDropEnabled, to allow dropping between items.

☑ Reimplement mimeTypes() and return the name of the MIME type used by the mimeData() function on the drag side.

☑ Reimplement dropMimeData()
to deserialize the data and insert new rows.
In the special case of in-process tree models, clone the dragged nodes.
In both cases, once you're done, return true, so that the drag side then deletes the dragged rows by calling removeRows() on its model.

bool DropModel::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    ~~~  // safety checks, see full example code

    if (row == -1) // drop into empty area = append
        row = rowCount(parent);

    // decode data
    const QByteArray encodedData = mimeData->data(s_mimeType);
    QDataStream stream(encodedData);
    QVector<CountryData> newCountries;
    while (!stream.atEnd()) {
        CountryData countryData;
        stream >> countryData;
        newCountries.append(countryData);
    }

    // insert new countries
    beginInsertRows(parent, row, row + newCountries.count() - 1);
    for (const CountryData &countryData : newCountries)
        m_data.insert(row++, countryData);
    endInsertRows();

    return true; // let the view handle deletion on the source side by calling removeRows there
}

Using item widgets

Example code can be found following this link.

For all kinds of widgets

On the "drag" side:

☑ Call widget->setDragDropMode(QAbstractItemView::DragOnly) or DragDrop if it should support both

☑ Call widget->setDefaultDropAction(Qt::MoveAction) so the drag starts as a move right away

On the "drop" side:

☑ Call widget->setDragDropMode(QAbstractItemView::DropOnly) or DragDrop if it should support both

☑ Reimplement supportedDropActions() to return only Qt::MoveAction

Additional requirements for QTableWidget

When using QTableWidget, in addition to the common steps above you need to:

On the "drag" side:

☑ Call item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled); for each item, to disable dropping onto items.

☑ Call widget->setDragDropOverwriteMode(false) so that after a move the rows are removed rather than cleared

On the "drop" side:

☑ Call widget->setDragDropOverwriteMode(false) so that it inserts rows instead of replacing cells (the default is false for the other views anyway)

☑ Another problem is that the items created by a drop will automatically get the Qt::ItemIsDropEnabled flag, which you don't want. To solve this, use widget->setItemPrototype() with an item that has the right flags (see the example).

Additional requirements for QTreeWidget

When using QTreeWidget, you cannot disable dropping onto items (which creates a child of the item).

You could call item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled); on your own items, but when QTreeWidget creates new items upon a drop, you cannot prevent them from having the flag Qt::ItemIsDropEnabled set. The prototype solution used above for QTableWidget doesn't exist for QTreeWidget.

This means, if you want to let the user build and reorganize an actual tree, you can use QTreeWidget. But if you just want a flat multi-column list, then you should use QTreeView (see previous section on model/view separation).

Addendum: Move/copy items between views

If the user should be able to choose between copying and moving items, follow the previous section and make the following changes.

With Model/View separation

On the "drag" side:

☑ Call view->setDefaultDropAction(...) to choose whether the default should be move or copy. The user can press Shift to force a move, and Ctrl to force a copy.

☑ Reimplement supportedDragActions() in the model to return Qt::MoveAction | Qt::CopyAction

On the "drop" side:

☑ Reimplement supportedDropActions() in the model to return Qt::MoveAction | Qt::CopyAction

The good news is that there's nothing else to do.

Using item widgets

On the "drag" side:

☑ Call widget->setDefaultDropAction(...) to choose whether the default should be move or copy. The user can press Shift to force a move, and Ctrl to force a copy.

Until Qt 6.10 there was no setSupportedDragActions() method in the item widget classes (that was QTBUG-87465, I implemented it for 6.10). Fortunately the default behavior is to use what supportedDropActions() returns so if you just want move and copy in both, reimplementing supportedDropActions() is enough.

On the "drop" side:

☑ Reimplement supportedDropActions() in the item widget class to return Qt::MoveAction | Qt::CopyAction

The good news is that there's nothing else to do.

Improvements to Qt

While writing and testing these code examples, I improved the following things in Qt:

  • QTBUG-1387 "Drag and drop multiple columns with item views. Dragging a row and dropping it in a column > 0 creates multiple rows.", fixed in 6.8.1
  • QTBUG-36831 "Drop indicator painted as single pixel when not shown" fixed in 6.8.1
  • QTBUG-87465 ItemWidgets: add supportedDragActions()/setSupportedDragActions(), implemented in 6.10

Conclusion

In the next blog post of this series, you will learn how to move (or copy) onto existing items, rather than between them.

The post Model/View Drag and Drop in Qt - Part 2 appeared first on KDAB.

Sunday, 9 March 2025

Back this month with another update on the progress for our new design system in Plasma.

This update includes:

– Icon selection and request to submit bugs

– Icon review and changes

– Plasma Sprint updates

If you would like to participate in an open design project like ours, learn more about it here: https://community.kde.org/Get_Involve&#8230; Learn more about our organization:

• Facebook: KDE Community

• Twitter: @kdecommunity

• Mastodon: @kde@floss.social

• LinkedIn: KDE • Reddit: r/kde

• Lemmy: KDE Community

• Instagram: @kdecommunity

• YouTube: KDE Community

• PeerTube: KDE Channel

#FigmaIcons #IconDesign #FigmaTutorial #LearnFigma #FigmaTips #UIUXDesign #GraphicDesign #VectorArt #FigmaDesign #IconCreation #FigmaForBeginners #FigmaWorkflow #DigitalDesign #FigmaCommunity #FigmaIconDesign #DesignWithFigma #UXDesignTips #FigmaTipsAndTricks #IllustrationDesign #IconDesignTutorial #penpot #opensource #opendesign

LSP Support in KDevelop, systemDGenie rewrite and big UI changes in Dolphin

Welcome to a new issue of "This Week in KDE Apps"! Every week we cover as much as possible of what's happening in the world of KDE apps. This time we will cover the past two weeks as I was traveling last weekend.

Last week we released KDE Gear 24.12.3, which concludes the 24.12 series of KDE Gear. 25.04.0 is right around the corner, with only a few days left before the beta and feature freeze. Aside from the numerous bug fixes and polishing going on, we also had some pretty big changes in Krita regarding advanced text editing options, KDevelop with support for the LSP protocol, some big UI changes in Dolphin, and a complete rewrite of systemDGenie.

General Changes

Balló György added improvements to many Kirigami projects for when they run with the software rendering backend. Projects that have been improved include Kirigami and Kirigami Addons, but also many apps like Tokodon, Kaidan, Angelfish and more.

Volker wrote a small report about the recent improvements to KDE Apps on Android. You can find it on his blog.

We fixed an issue in KIO SFTP support where symlinks would be truncated (Kishore Gopalakrishnan, 25.04.0. Link), and another in KIO SMB support where shared resources from other computers on multiple LANs and virtual LANs were not displayed when using WSDD (Harald Sitter, 24.12.3. Link).

Another thing that got fixed was an issue where the report bug button would not open the report URL (Carl Schwan, KF 1.12.0. Link).

Graphics and Multimedia Apps

Elisa Play local music and listen to online radio

Balló György fixed restoring the hidden Elisa instance on file opening (Balló György, 25.04.0. Link), and Jack Hill fixed the spacebar play/pause action, as it was not being triggered when specific buttons had the focus (Jack Hill, 25.04.0. Link).

Gwenview Image Viewer

Pedro Hernández added an option to display hidden files (Pedro Hernandez, 25.04.0. Link), and we changed how image size integers were displayed to make them clearer in all languages. Previously, we displayed 1,024x1,024. Now it is 1024x1024.

Kasts Podcast application

Bart De Vries properly implemented single instance behavior (Bart De Vries, 25.04.0. Link).

Okular View and annotate documents

Okular now supports, in addition to S/MIME based signatures, PGP/GPG based signatures. PGP signatures have the advantages that it is a lot easier to get a PGP key than a S/MIME key. Note that this feature is not yet enabled by default and for the moment only works between Okular users (Sune Vuorela, 25.04.0. Link).

Creative Apps

Kdenlive Video editor

Darby Johnston added support for OpenTimelineIO export and import using the C++ library. This allows importing and exporting projects files to/from other video-editing applications that implement this open standard (Darby Johnston supported by KDenlive fundraiser, 25.04.0. Link).

Krita Digital Painting, Creative Freedom

Wolthera van Hövell implemented basic support for the font-feature-settings CSS property in Krita. This allows tweaking the rendering of text based on OpenType font features (Wolthera van Hövell, Link). Wolthera wrote an excellent blog post on this topic, as well as covering the support of font variants mentioned two weeks ago. You can find the post on her blog.

Maciej Jesionowski added a global pen tilt direction offset, which can be helpful to make the brushes feel the same for right- and left-handed users (Maciej Jesionowski, Link).

The process of porting Krita to Qt6 is making good progress: the macOS version now compiles (Freya Lupen. Link), and the implementation of the tablet switching API for Windows is now using Qt APIs instead of a custom implementation (Dmitry Kazakov, Link).

In other news, Carl Schwan fixed the menubar visibility state being saved as non visible if the global menu option is turned on. This become an issue when turning off the global menu, as Krita's menubar wouldn't appear again (Carl Schwan, Link).

Personal Information Management Apps

KOrganizer KOrganizer is a calendar and scheduling application

Allen Winter improved the agent selection dialog. Now the Ok button is only enabled when an item is selected and the search text field has a placeholder (Allen Winter, 25.04.0. Link).

Merkuro Calendar Manage your tasks and events with speed and ease

Shubham Shinde added support for displaying holidays in the week view and the month view. Note that it is possible to disable this feature (Shubham Shinde, 25.04.0. Link 1, link 2 and link 3).

Kleopatra Certificate manager and cryptography app

Tobias Fella fixed decrypting files with very long paths on Windows (Tobias Fella, 25.04.0. Link).

Akonadi Background service for KDE PIM apps

Milian Wolff optimized some code in Qt related to timezones to improve the performance of some serialization in Akonadi. (Milian Wolff, Qt 6.8. Link)

KDE Itinerary Digital travel assistant

Volker Krause unified the formatting of temperature ranges and dynamic depending on the home country. Similarly, imperial speed units are shown for countries that use them (Volker Krause, 25.04.0. Link 1 and link 2).

Again Itinerary has increased the number of ticket types it supports and now handles multi-page 12go PDF tickets and Ghotel reservation emails.

Social Apps

NeoChat Chat on Matrix

Joshua Goins moved the "Explore rooms" button from the hamburger to the space drawer (Joshua Goins, 25.04.0. Link), added a dialog explaining what to do next when tapping "Verify this device" (Joshua Goins, 25.04.0. Link), and made joining remote rooms more reliable (Joshua Goins, 25.04.0. Link). Joshua also fixed a bug where emoji autocompletion would destroy the current message draft (Joshua Goins, 25.04.0. Link).

Meanwhile, James Graham improved the handling of switching link previews on and off (James Graham, 25.04.0. Link).

Developer Apps

Kate Advanced text editor

Niels Thykier added built-in support for the debputy language server. This is used when writing Debian package (Niels Thykier, 25.04.0. Link).

Meanwhile, Joshua Goins improved the titles of terminal tabs and assigning an icon to them (Joshua Goins, 25.04.0. Link). Joshua also improved the UI of the compiler explorer integration. This includes polishing some strings, adding tooltips and fixing some padding issues (Joshua Goins, 25.04.0. Link).

KDevelop Featureful, plugin-extensible IDE for C/C++ and other programming languages

KDevelop now support the Language Server Protocol (LSP) in addition to the native support for C++, PHP and Python. This reuses Kate's plugin, so, at the moment, it is only available when Kate is also installed (Igor Kushnir and Sven Brauch, 25.04.0. Link).

Konsole Use the command line interface

Jonathan Marten fixed a crash when double clicking on a terminal scroll bar (Jonathan Marten, 25.04.0. Link).

System Apps

Ark Archiving Tool

Natsumi Higa fixed the extraction of timestamps from 7-Zip archives, which now includes nanoseconds (Natsumi Higa, 25.04.0. Link).

Dolphin Manage your files

Dolphin is having its looks tweaked and has a new icon with an actual picture of a dolphin inside it! (Darshan Phaldesai, 25.04.0. Link).

In the same vein, Akseli Lahtinen added a background to the navigation bar of Dolphin and Gwenview (Akseli Lahtinen, KF 6.12.0. Link).

And Nate Graham added a nicer split icon to the toolbar (Nate Graham, 25.04.0. Link).

In other Dolphin news, Akseli Lahtinen fixed a crash when opening a new tab with search (Akseli Lahtinen, 24.12.3. Link).

systemdGenie System service manager

systemDGenie was completely rewritten using QML. The new version also relies a lot less on blocking DBus calls (Carl Schwan, 1.0.0. Link).

KWalletManager Wallet Management Tool

Xuetian Weng sorted a security issue and passwords copied from the KWallet Manager are no longer visible in the clipboard history of Plasma (Xuetian Weng, 25.04.0. Link).

Education Apps

Kiten Japanese Reference and Study Tool

Balló György fixed the font size of the result view. The font size was stored as point size, but passed as pixel size, causing that the actual font size is smaller than it should be (Balló György, 25.04.0. Link). Balló also fixed the background color of some views when switching to a dark theme (Balló György, 25.04.0. Link).

KHangMan Hangman Game

Max Brazhnikov Added support for non-latin alphabets (Max Brazhnikov, 25.04.0. Link).

KStars Desktop Planetarium

Hy Murveit added an altitude graph to the scheduler table (Hy Murveit, Link)

Utilities

Alligator RSS feed reader

Mark Penner made the text elide in the RSS entry list so that the buttons are always visible (Mark Penner, 25.04.0. Link), and Balló György set the default format to import and export feeds as OPML (Balló György, 25.04.0. Link).

KDE Connect Seamless connection of your devices

José Rebelo added the possibility of filtering out notifications from the Android work profile (José Rebelo, Link).

KDiskFree View Disk Usage

Kai Uwe Broulik added an option to explore in Filelight (Kai Uwe Broulik, 25.12.0. Link), and icons to the context menu entries (Kai Uwe Broulik, 25.12.0. Link).

KGet Download manager

Balló György fixed the windows activation when the current window is in the system tray (Balló György, 25.04.0. Link).

KRDC Connect with RDP or VNC to another computer

Fabio Bas added a setting for desktop scale and device scale (Fabio Bas, 25.04.0. Link), while Fabian Lesniakd disabled Kerberos support completely, since it turned out that having a broken support for it was worse than no support at all (Fabian Lesniak, 25.04.0. Link).

OptiImage Image optimizer to reduce the size of images

Balló György fixed the name of the generated optimized images, and now the suffix is appended before the file extension (Balló György, Link).

…And Everything Else

This blog only covers the tip of the iceberg! If you’re hungry for more, check out Nate's blog about Plasma and be sure not to miss his This Week in Plasma series, where every Saturday he covers all the work being put into KDE's Plasma desktop environment.

For a complete overview of what's going on, visit KDE's Planet, where you can find all KDE news unfiltered directly from our contributors.

Get Involved

The KDE organization has become important in the world, and your time and contributions have helped us get there. As we grow, we're going to need your support for KDE to become sustainable.

You can help KDE by becoming an active community member and getting involved. 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. There are many things you can do: you can help hunt and confirm bugs, even maybe solve them; contribute designs for wallpapers, web pages, icons and app interfaces; translate messages and menu items into your own language; promote KDE in your local community; and a ton more things.

You can also help us by donating. Any monetary contribution, however small, 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 your application mentioned here, please ping us in invent or in Matrix.