Skip to content

Thursday, 6 February 2025

Model/View Drag and Drop in Qt - Part 1

This blog series is all about implementing drag-and-drop in the Qt model/view framework. In addition to complete code examples, you'll find checklists that you can go through to make sure that you did not forget anything in your own implementation, when something isn't working as expected.

At first, we are going to look at Drag and Drop within a single view, to change the order of the items. The view can be a list, a table or a tree, there are very little differences in what you have to do.

part1-table-step1

Moving a row in a tableview, step 1

part1-table-step2

Moving a row in a tableview, step 2

part1-table-step3

Moving a row in a tableview, step 3

The main question, however, is whether you are using QListView/QTableView/QTreeView on top of a custom item model, or QListWidget/QTableWidget/QTreeWidget with items in them. Let's explore each one in turn.

With Model/View separation

The code being discussed here is extracted from the example. That example features a flat model, while this example features a tree model. The checklist is the same for these two cases.

Setting up the view

☑ Call view->setDragDropMode(QAbstractItemView::InternalMove) to enable the mode where only moving within the same view is allowed

☑ When using QTableView, call view->setDragDropOverwriteMode(false) so that it inserts rows instead of replacing cells (the default is false for the other views anyway)

Adding drag-n-drop support to the model

part1-list

Reorderable ListView

part1-table

Reorderable TableView

For a model being used in QListView or QTableView, all you need is something like this:

class CountryModel : public QAbstractTableModel
{
    ~~~
    Qt::ItemFlags flags(const QModelIndex &index) const override
    {
        if (!index.isValid())
            return Qt::ItemIsDropEnabled; // allow dropping between items
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
    }

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

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

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

    bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override; // see below
};

The checklist for the changes you need to make in your model is therefore the following:

☑ Reimplement flags()
For a valid index, add Qt::ItemIsDragEnabled and 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). \

☑ Reimplement mimeTypes() and make up a name for the mimetype (usually starting with application/x-)

☑ Reimplement supportedDragActions() to return Qt::MoveAction

☑ Reimplement supportedDropActions() to return Qt::MoveAction

☑ Reimplement moveRows()

Note that this approach is only valid when using QListView or, assuming Qt >= 6.8.0, QTableView - see the following sections for details.

In a model that encapsulates a QVector called m_data, the implementation of moveRows can look like this:

bool CountryModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
{
    if (!beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild))
        return false; // invalid move, e.g. no-op (move row 2 to row 2 or to row 3)

    for (int i = 0; i < count; ++i) {
        m_data.move(sourceRow + i, destinationChild + (sourceRow > destinationChild ? 0 : -1));
    }

    endMoveRows();
    return true;
}

QTreeView does not call moveRows

part1-tree

Reorderable treeview

part1-treemodel

Reorderable treeview with a tree model

QTreeView does not (yet?) call moveRows in the model, so you need to:

☑ Reimplement mimeData() to encode row numbers for flat models, and node pointers for tree models

☑ Reimplement dropMimeData() to implement the move and return false (meaning: all done)

Note that this means a move is in fact an insertion and a deletion, so the selection isn't automatically updated to point to the moved row(s).

QTableView in Qt < 6.8.0

I implemented moving of rows in QTableView itself for Qt 6.8.0, so that moving rows in a table view is simpler to implement (one method instead of two), more efficient, and so that selection is updated. If you're not yet using Qt >= 6.8.0 then you'll have to reimplement mimeData() and dropMimeData() in your model, as per the previous section.

This concludes the section on how to implement a reorderable view using a separate model class.

Using item widgets

The alternative to model/view separation is the use of the item widgets (QListWidget, QTableWidget or QTreeWidget) which you populate directly by creating items.

part1-listwidget

Reorderable QListWidget

part1-tablewidget

Reorderable QTableWidget

part1-treewidget

Reorderable QTreeWidget

Here's what you need to do to allow users to reorder those items.

Example code can be found following this link.

Reorderable QListWidget

☑ Call listWidget->setDragDropMode(QAbstractItemView::InternalMove) to enable the mode where only moving within the same view is allowed

For a QListWidget, this is all you need. That was easy!

Reorderable QTableWidget

When using QTableWidget:

☑ Call tableWidget->setDragDropMode(QAbstractItemView::InternalMove)

☑ Call tableWidget->setDragDropOverwriteMode(false) so that it inserts rows instead of replacing cells

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

Note: Before Qt 6.8.0, QTableWidget did not really support moving rows. It would instead move data into cells (like Excel). The example code shows a workaround, but since it calls code that inserts a row and deletes the old one, header data is lost in the process. My changes in Qt 6.8.0 implement support for moving rows in QTableWidget's internal model, so it's all fixed there. If you really need this feature in older versions of Qt, consider switching to QTableView.

Reorderable QTreeWidget

When using QTreeWidget:

☑ Call tableWidget->setDragDropMode(QAbstractItemView::InternalMove)

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

Conclusion about reorderable item widgets

Of course, you'll also need to iterate over the items at the end to grab the new order, like the example code does. As usual, item widgets lead to less code to write, but the runtime performance is worse than when using model/view separation. So, only use item widgets when the number of items is small (and you don't need proxy models).

Improvements to Qt

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

  • QTBUG-13873 / QTBUG-101475 - QTableView: implement moving rows by drag-n-drop
  • QTBUG-69807 - Implement QTableModel::moveRows
  • QTBUG-130045 - QTableView: fix dropping between items when precisely on the cell border
  • QTBUG-1656 - Implement full-row drop indicator when the selection behavior is SelectRows

Conclusion

I hope this checklist will be useful when you have to implement your own reordering of items in a model or an item-widget. Please post a comment if anything appears to be incorrect or missing.

In the next blog post of this series, you will learn how to move (or even copy) items from one view to another.

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

Glaxnimate 0.6.0 Beta has finally been released for testing!

It has been a while since the last release of Glaxnimate, but in the background we worked hard to make this first release under the KDE umbrella happen!

Please help us testing and report any issue you may encounter on https://bugs.kde.org/enter_bug.cgi?product=glaxnimate

Glaxnimate joins KDE

The Glaxnimate team is proud to announce Glaxnimate is now part of KDE. Glaxnimate benefits from the shared KDE build and distribution infrastructure, the collective knowledge of the community and libraries such as KDE Frameworks. This way the developers can spend more time on the code to fix bugs and develop new features for you!

Changes

Editing

  • The rotation handle now preserves rotation direction and multiple full rotations
  • Alt + click on keyframes cycles between built-in easing curves
  • Alt + click on bezier points cycles between tangent symmetry modes (Ctrl+click still works)
  • Changing a bezier point from corner to smooth will add tangents if they are missing
  • The import image dialog now allows importing multiple images at once

I/O

  • Added support for SVG text-anchor

User Interface

  • Middle mouse drag now pans the timeline
  • There is an icon on the timeline to quickly toggle keyframes
  • Buttons to jump to the next/previous keyframe in the timeline
  • Improved LottieFiles import dialog
  • Improved autosave recovery process
  • Script console now supports basic autocompletion

Scripting

  • Exposed method to add new compositions

Misc

  • Switched to an even/odd version numbering scheme
  • Integration with KDE Frameworks

Bug Fixes

  • Fixed keyframe context menu showing the wrong "after" transition
  • When drawing bezier points that don't have tangents are correctly marked as corner
  • The play button now resumes from the current frame rather than resetting to the start
  • Fixed saving custom templates
  • Toggling visibility / lock of a layer by clicking on its icon now adds an undo/redo action
  • Fixed LottieFiles import
  • Fixed dropping file as object
  • Fixed closing compositions from the tab bar
  • Fixed loading colors from older lotties
  • Shape modifiers marked as not visible are now correctly ignored
  • Fixed rendering of round corners modifier
  • Fixed "New Composition" action creating an invisible layer
  • Fixed repeater opacity not being applied correctly
  • Improved handling of repeater with stroke
  • Fixed SVG animation export
  • Fixed animated raster plugin I/O

How to get it

Note that this is a beta release. Most Linux distributions do not package unstable releases.

We recommend to test this release with one of the binaries we provide:

Packager Section

The source code tarball are available from the KDE servers:

URL: https://download.kde.org/unstable/glaxnimate/0.5.80

Source: glaxnimate-0.5.80.tar.xz

Signed by: 97B71AA02D63EA6C5C44C23B962AC48EF0501F0B Julius Künzel julius.kuenzel@kde.org

Monday, 3 February 2025

KStars v3.7.5 is released on 2025.02.03 for Windows, MacOS & Linux. It's a bi-monthly bug-fix release with a couple of exciting features. Here are the release notes organized by developer.

Jasem Mutlaq

  • Added dome slit visualization on sky map. Specify the Dome Measurement parameters in the INDI Dome driver to see a live dome slit overlay in the Sky Map.

  • Implemented generic DBus methods for KStars options
  • Added SchedulerSleeping event
  • Added mutex protection for multi-threaded resources
  • Enhanced scheduler loading and settings management
  • Improved filter manager operations
  • Fixed video subframing. Up to 50x improvement in subframed video feeds.
  • Fixed multiple profile editor issues
  • Added VSCode development setup support

Hy Murveit

  • Fixed DMS delta angle calculation
  • Added mandatory settle to PAA
  • Improved imaging planner stability


  • Fixed pierside placeholder directory usage
  • Added START_AT scheduler test
  • Fixed Abell planetary nebula lookup
  • Enhanced PAA adjustment estimation

Wolfgang Reissenberger

  • Implemented video sequence capture. Preliminary support for capturing Video files as regular sequences in the Capture module. Great news for EAA.

  • Fixed focus options
  • Improved remote directory handling
  • Fixed flats with wall position
  • Enhanced filter wheel integration

John Evans

  • Enabled focuser controls when camera disconnected
  • Improved focus measure framing
  • Fixed focus advisor code warnings
  • Updated aberration inspector functionality

Toni Schriber

  • Fixed overshooting cosine in CachingDms calculation
  • Implemented calibration reuse after rotation. Guide calibration data can now be re-used between sessions after rotation.

Ben Cooksley

  • Removed CMake trace/debug logs from CI runs

György Balló

  • Set window icon

Oliver Kellogg

  • Fixed typo in FITS Viewer configuration

Akarsh Simha

  • Fixed right-click popup menu on deep stars

Technical Highlights

  • Improved capture sequence stability: Set 5-minute timeout for transient operations (dome motion, mount parking/unparking, dust cap operations, focusing, filter wheel changes) to prevent indefinite sequence stalling.
  • Improved mount rotation processing
  • Enhanced scheduler loading mechanism
  • Added mutex protection for multi-threaded resources
  • Improved capture operation timeout handling

Sunday, 2 February 2025

A new Craft cache has just been published. The update is already available for KDE's CD, CI (Windows/Android) will follow in the next days.

Please note that this only applies to the Qt6 cache. The Qt5 cache is in LTS mode since April 2024 and does not recieve major updates anymore. We highly recommend to port your Qt5 app packaged by Craft to Qt6 as soon as possible!

Changes (highlights)

General

We added CI for flake8, isort and black with the help of tox (which makes it easy to run them locally too) to all Craft repositories. To be able to do so we did a lot of best pratice cleanup beforehand like eg. removing star imports.

Craft Core

  • Drop support for MSVC 2017
  • Introduced a CraftBool helper. This allows handy things like self.subinfo.options.dynamic.withMyLib.asOnOff instead of 'ON' if self.subinfo.options.dynamic.withMyLib else 'OFF'
  • Fix: let the Meson build system respect the buildStatic option
  • Handle --enable-static --enable-shared in AutoToolsPackageBase instead of in every single blueprint
  • Python packages (Linux and Windows MSVC; macOS is work in progress):
    • Build them ourself instead of using the pre-build binaries from pypi.org
    • Use proper staging
    • Allow to deploy/package them
  • Properly set Craft env when branch is switched (eg. with Craft Master in CI)

Blueprints

  • libjpeg-turbo 3.0.3
  • Multiple fixes for build of shared vs. static libs
  • libvpx 1.15.0
  • Add minGW 14.2 (not the default yet!)
  • 7z 24.09
  • KShimgen 0.6.1
  • linuxdeploy-plugin-qt 2.0.0-alpha-1-20250119
  • qtkeychain 0.15.0

About KDE Craft

KDE Craft is an open source meta-build system and package manager. It manages dependencies and builds libraries and applications from source on Windows, macOS, Linux, FreeBSD and Android.

Learn more on https://community.kde.org/Craft or join the Matrix room #kde-craft:kde.org

Saturday, 1 February 2025

The Linux App Summit is a project we KDE created, together with GNOME and some other parties. We wanted a physical space where to discuss our platform to different stakeholders.

We have seen lots of progress since 2019. From a KDE perspective, we see our flatpaks and snaps. This adoption brings all sorts of users to our software that otherwise wouldn’t have been able to.

From the other side of the equation, linux distros have been evolving like ever. We have seen a myriad of distributions using technologies that we would have never dreamed of. And we can find them both on consumer and development devices. Even KDE Linux and GNOME OS are looking into tightening the other end of that software distribution loop.

Now, it’s time to take things even further.

This year we will have LAS 2025 in Tirana. Consider participating in LAS 2025! How you ask?

  • Join us! It’s free to attend and, dare I say, we are lovely people.
  • Send a talk! You can come and talk us about how you are helping linux apps be a reality or what kind of problems you found with your app and how you solved them. Here you can find some more ideas.
  • Sponsor! Does your organisation take part in the linux ecosystem? Take part in it!

You can follow LAS updates on the Attendees chat or here @LAS@floss.social on Mastodon.

Thursday, 30 January 2025

Wednesday, 29 January 2025

gcompris 25.0

Today we are releasing GCompris version 25.0.

As you can see, we are now basing the major version number on the release year. This makes sense as we are doing one major version per year. It is also a good occasion to do it now to celebrate the 25 years of GCompris.

This version adds translation for one more language: Sanskrit.

This new version contains 195 activities, including 5 new ones:

  • "Sketch" is an activity for drawing freely with multiple tools to let children explore their creativity.
  • "Calculate with ten's complement" is the continuation of the existing ten's complement activities. This one helps the children to swap the numbers to easily compute a sum.
  • "Vertical addition" is an activity to write an addition and solve it.
  • "Vertical subtraction", is similar to the addition activity but for subtraction with the borrowing by regrouping method.
  • "Vertical subtraction (compensation)", is similar to the subtraction one with the borrowing by compensation method.

It contains bug fixes and graphics improvements on multiple activities.

With the help of teachers, we rewrote a big part of the activities description to be clearer.

When we switch language in the menu, the new language is now applied directly, without having to restart GCompris.

On the technical side, it is also the first release using Qt6.

We have also set the graphical renderer to direct3d11 by default on Windows.

It is fully translated in the following languages:

  • Arabic
  • Bulgarian
  • Breton
  • Catalan
  • Catalan (Valencian)
  • Greek
  • Spanish
  • Basque
  • French
  • Galician
  • Croatian
  • Hungarian
  • Italian
  • Latvian
  • Malayalam
  • Dutch
  • Polish
  • Brazilian Portuguese
  • Romanian
  • Sanskrit
  • Slovenian
  • Swedish
  • Turkish
  • Ukrainian

It is also partially translated in the following languages:

  • Azerbaijani (90%)
  • Belarusian (86%)
  • Czech (98%)
  • German (88%)
  • UK English (99%)
  • Esperanto (99%)
  • Estonian (88%)
  • Finnish (91%)
  • Hebrew (96%)
  • Indonesian (93%)
  • Georgian (85%)
  • Lithuanian (92%)
  • Macedonian (83%)
  • Norwegian Nynorsk (94%)
  • Portuguese (89%)
  • Russian (92%)
  • Slovak (82%)
  • Albanian (98%)
  • Swahili (92%)
  • Chinese Traditional (88%)

You can find packages of this new version for GNU/Linux, Windows, Android and Raspberry Pi on the download page. This update will also be available soon in the Android Play store, the F-Droid repository and the Windows store.

Thank you all,
Timothée & Johnny

Tuesday, 28 January 2025

tldr; save the date for our QtCS25, May 7-8 in Munich.
Stay tuned for more information.

Sunday, 26 January 2025

Project Description

In SoK 2025, I will be working on adding Pallanguzhi, a traditional Indian Mancala variant, into the Mankala Engine. Collaborating with Srisharan V S, my focus includes two key goals:

  1. Developing a computerized opponent to enhance player engagement and ensure a seamless gameplay experience.
  2. Creating a Text-Based User Interface (TUI) for gameplay.

What I Did This Week

The first step in my journey was setting up the Mankala Engine repository. I forked the repository to my local system, successfully built it, and resolved some warnings during the build process. Afterward, I delved into the codebase, analyzing the existing algorithms and understanding how they work for other Mancala variants.

Research on Implementing a Computerized Opponent

To create a robust computerized opponent for Pallanguzhi, I began researching potential algorithms that could best fit the game mechanics. Here are the three techniques I explored.

1. Reinforcement Learning

Reinforcement Learning (RL) is an exciting approach where an agent learns optimal strategies by interacting with the environment and improving over time. For Pallanguzhi, RL could enable the computerized opponent to adapt and improve its gameplay dynamically. However, as I am new to RL, implementing and training models for this variant will take some time and effort. Despite its challenges, RL remains a promising option for advanced gameplay enhancement.

2. Monte Carlo Tree Search (MCTS)

MCTS is a powerful algorithm widely used for decision-making in games. It works by simulating potential moves to build a decision tree and then selecting the best move based on statistical evaluation. For Pallanguzhi, MCTS could efficiently explore the vast game state space and make informed decisions. By carefully tuning the number of simulations and exploration parameters, this algorithm can provide a balanced and competitive computerized opponent.

3. Alpha-Beta Pruning with Iterative Deepening

Alpha-Beta Pruning with Iterative Deepening is a highly effective technique for optimizing decision trees by eliminating unnecessary branches. This method is already implemented in the Mancala Engine for other variants and has proven its efficiency. Leveraging this existing implementation for Pallanguzhi will allow us to quickly develop a working version of the game with a competent computerized opponent.

Conclusion for Now

The immediate plan is to integrate the Pallanguzhi variant into the existing Alpha-Beta Pruning implementation. This ensures we have a functional version of the game ready for any further work. Once the TUI implementation is complete, I plan to revisit Reinforcement Learning for Pallanguzhi. Working with RL models and training them is a learning-intensive process, and I am excited to gain experience in this area. Even if RL proves too challenging, we will still have a polished Pallanguzhi variant running on the existing algorithm.

What’s Next

Next week, I will work on adding the longer version of Pallanguzhi, which consists of multiple rounds, while Srisharan V S focuses on completing the shorter version. Together, we aim to make significant progress toward integrating and refining this traditional game within the Mankala Engine.

Stay tuned for updates!

Saturday, 25 January 2025

What I am working on?

My project focuses on enhancing the GUI and adding Player vs. Player (PvP) multiplayer functionality to a Mancala game.

Mancala is a popular board game played worldwide. The proposed plan is to use Kirigami for improving the GUI and making the application cross-platform. Multiplayer functionality will be integrated using XMPP. The game will operate over a communication channel established by XMPP over UDP. The updated game board will be reflected graphically using data binding. The XMPP server being used is Prosody.

Work done so far

Setting up the prosody locally

Setting up Prosody is fairly straightforward. I installed it from Fedora’s official repository using the command:


sudo dnf install prosody

Alternatively, Prosody can be built and installed from its source code available on GitHub.

Configuring prosody

Prosody’s configuration is contained in a single file: prosody.cfg.lua. On Linux distributions, this file is typically located at /etc/prosody/prosody.cfg.lua..

For now the clients are connected over same LAN using the virtual host @mancala.local as the domain id.

The image above illustrates how to edit your virtual host configuration.

The next step is to configure a chat room, which is done similarly to the virtual host configuration.

Both configurations require an SSL certificate to secure the communication channel.

After completing these steps, we restart and check the status of Prosody using the following commands:

sudo systemctl restart prosody
sudo systemctl status prosody

If everything is configured correctly, the state will be “active.” You can verify this by checking the log file using: sudo tail -f /var/log/prosody/prosody.log we can check the log file. If configured successfully, the output will resemble this:

Adding users and communicating via a XMPP client

The plan is to allow users to either use their existing Jabber ID or create a new one through our server. For testing purposes, I manually added users to the server using the following command:

sudo prosodyctl adduser <username@domain_name>

After executing the command, you will be prompted to set a password for the user.

For communication, I used the Pidgin client.

As shown in the image above, I have added two users, user11 and user12.

To test communication, I sent a message from user11 to user12 by addressing it to user12@mancala.local. Below are the results:

Since I used the Pidgin client on the same device, both user tabs appear in the interface. The screenshots confirm that I successfully established a user-to-user communication channel over LAN.

What’s next

For the next week, I plan to:

  • Implement in-band registration.
  • Enable communication over the internet.
  • Develop the logic for the game invitation system.