Skip to content

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!

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.

Monday, 25 August 2025

Intro

In my final week of GSoC with KDE's Krita this summer, I am excited to share this week's progress and reflect on my journey so far. From the initial setup to building the Selection Action Bar, this project has been a meaningful learning experience and a stepping stone toward connecting with Krita's community and open source development.

Final Report

Progress

This week I finalized the Selection Action Bar with my mentor Emmet and made adjustments based on my merge request feedback.

Some key areas of feedback and fixes included:

  • Localization of user-facing strings
  • Removing unused parameters
  • Refactoring naming conventions and standardized styling

These improvements taught me that writing good code is not just about features, but also about clarity, consistency, and collaboration.

Alongside updating my feature merge request, I also worked on documentation to explain how the Selection Action Bar works and how users can use it.

Reflection

Looking back over the past 12 weeks, I realize how much this project has shaped both my technical and personal growth as a developer.

Technical Growth When I started, navigating Krita's large C++/Qt codebase felt overwhelming. Through persistence, code reviews, and mentorship, I've grown confident in reading unfamiliar code, handling ambiguity, and contributing in a way that fits the standards of a large open source project. Following Krita's style guidelines showed me how important naming conventions and standardized code styling are for long-term maintainability.

Personal Growth One of the most important lessons I learned is that open source development isn't about rushing to get the next feature in. It's about patience, clarity, and iteration. Code reviews taught me to embrace feedback, ask better questions, and view them as opportunities for growth rather than blockers.

Community Lessons The most valuable part of this experience was connecting with the Krita and KDE community. I experienced first-hand how collaborative and thoughtful the process of open source development is. Every suggestion, from small style tweaks to broader design decisions, carried the goal of improving the project for everyone. That sense of shared ownership and responsibility is something I want to carry with me in all my future contributions.

Conclusion

These final weeks have been very rewarding. I have grown from starting out by simply reading Krita's large codebase to implementing a feature that enhances users' workflow.

While this marks the end of GSoC for me, it is not the end of my open source journey. My plan moving forward is to:

  • Continue refining the Selection Action Bar based on user feedback
  • Add customization options to the Selection Action Bar
  • Stay involved through ownership of feature creation, bug fixes, community participation, and feature proposals with the Krita and KDE community

Finally, I would like to thank my mentor Emmet, the Krita Developers Dmitry, Halla, Tiar, Wolthera, everyone I interacted with in Krita Chat, and the Krita community for their guidance, patience, and encouragement throughout this project.

I also want to thank Google Summer of Code for making this journey possible and giving me the chance to grow as a developer while contributing to open source.

Contact

To anyone reading this, please feel free to reach out to me. I'm always open to suggestions and thoughts on how to improve as a developer and as a person.
Email: ross.erosales@gmail.com
Matrix: @rossr:matrix.org

Sunday, 24 August 2025


Implementation of Python virtual environment runtime switching

A long‑running backend that evaluates Python code must solve one problem well: switching the active interpreter or virtual environment at runtime without restarting the host process. A reliable solution depends on five pillars: unambiguous input semantics, reproducible version discovery, version‑aware initialization, disciplined management of process environment and sys.path, and transactional switching that can roll back safely on failure. 


The switching workflow begins with a single resolver that accepts either an interpreter executable path or a virtual environment directory. If the input is a file whose basename looks like a Python executable, the resolver treats it as such, and when the path sits under bin or Scripts it walks one directory up to infer the venv root. If the input is a directory, the resolver confirms a venv by checking for pyvenv.cfg or conda‑meta. Inputs that do not meet either criterion are interpreted as requests to use the system Python. One subtle but important detail is to avoid canonicalizing paths during this phase. Symlinked venvs frequently point into system trees; resolving them prematurely would collapse a virtual environment back into “system Python,” undermining the caller’s intent.

Pic 1. Project structure created by venv/virtualenv
Pic 2. Project structure in {virtual_env_path}/bin
Pic 3. Project structure created by conda


Once a target has been identified, the backend determines the interpreter’s major.minor version and applies a session‑level version policy. Virtual environments often publish their version and preferred executable in pyvenv.cfg; the backend reads version, executable and base‑executable if present, falling back to executing the interpreter with a small snippet to print its major and minor components when necessary. For system Python, a small set of common candidates are probed until one responds. At first login, the backend records the initialized major.minor pair and considers subsequent switches compatible only if they match that normalized value. This deliberately conservative choice prevents ABI mismatches inside a single process.

Pic 5.  Content in pyvenv.cfg

Initialization deliberately follows two distinct paths because Python’s embedding APIs changed significantly in 3.8. For older runtimes, the legacy sequence sets the program name and Python home using Py_SetProgramName and Py_SetPythonHome and then calls Py_Initialize. To keep the embedded interpreter’s view of the world coherent, the backend then runs a short configuration script that clears and rebuilds sys.path, sets sys.prefix and sys.exec_prefix, and establishes VIRTUAL_ENV in os.environ. This legacy path also relies on process‑level environment manipulation, which is described below. For modern runtimes, the backend uses the PyConfig API. It constructs an isolated configuration, sets program_name, home, executable and base_executable explicitly, marks module_search_paths_set, and appends each desired search path through PyWideStringList_Append before calling Py_InitializeFromConfig. This approach minimizes dependence on ambient process environment and makes the search space explicit and predictable. It is worth emphasizing that even when switching to the system interpreter on Py≥3.8, module search paths should be set explicitly rather than relying on implicit heuristics.


The legacy initialization path leans on controlled modification of the host process environment. Before entering a venv, the backend saves the current PATH and PYTHONHOME, prepends the venv’s bin or Scripts directory to PATH, unsets PYTHONHOME and clears PYTHONPATH, and sets VIRTUAL_ENV. On restore, PATH and PYTHONHOME are put back, VIRTUAL_ENV and PYTHONPATH are cleared, and a guard bit records that the environment is no longer modified. A frequent source of instability in ad‑hoc implementations is PATH inflation during rapid switching. The fix is straightforward: always rebuild PATH from the original value captured before the first switch rather than stacking new prefixes on top of already mutated values.


Search path construction is handled in two places. On the C++ side, we can expand the venv’s library layout into a concrete list of directories—lib/pythonX.Y/site‑packages, lib/pythonX.Y, and lib64 variants—and, if desired, appends a fallback set of system paths. On the Python side, a short configuration fragment clears sys.path and appends the new list in order, then sets sys.prefix and sys.exec_prefix to the venv root and publishes VIRTUAL_ENV in the environment. Projects that require strict isolation can omit the system fallback entirely or tie the decision to pyvenv.cfg’s include‑system‑site‑packages.


Switching itself is transactional. Before attempting a change, the backend captures a compact description of the current state—the venv directory and detected version. It then finalizes the current interpreter, applies the new target and logs in. If initialization fails for any reason, the backend finalizes again and restores the previous state, re‑logging in and restoring the prior version record on success. This simple but strict “switch‑or‑rollback” contract prevents half‑initialized sessions and ensures the host remains usable regardless of individual switch failures.


Operational visibility matters both for diagnostics and for UI integration. The backend publishes getters for the current venv directory, the detected Python version, and the chosen interpreter path. It can also discover virtual environments by scanning starting directories for pyvenv.cfg and recognizable layout patterns, returning a list of environment paths with associated versions. For consumption by other components, structured formats such as JSON simplify parsing and future evolution; even when initial implementations return human‑readable strings, migrating to a structured schema pays off quickly.


Several pitfalls recur in real deployments. Symlinked venvs must be treated carefully to avoid collapsing into system paths during resolution. PATH must be rebuilt from an original baseline to avoid unbounded growth during rapid switching. On Py≥3.8, the system interpreter should be initialized with explicit module search paths rather than relying on implicit platform logic. On Windows, hard‑coded “C:/Python” roots are fragile; build paths from CMake‑injected PYTHON_STDLIB/PYTHON_SITELIB or query sysconfig from a known interpreter. Finally, enforcing a stable major.minor within a process, while conservative, prevents obscure ABI issues that are otherwise difficult to reproduce.


A typical backend sequence for switching to a new venv reads cleanly: accept a target path, resolve it to either a venv or the system interpreter, finalize the current interpreter, set the new Python home and program name or PyConfig fields as appropriate, initialize, publish paths, and report success. If any step fails, finalize immediately and restore the previous environment. Switching to the system interpreter follows the same template, with the additional recommendation to populate module_search_paths explicitly for Py≥3.8. Querying the active environment simply returns the cached directory, version, and executable path.


A robust runtime venv switcher is primarily a matter of careful engineering rather than novel algorithms. By unifying input semantics, discovering versions reliably, choosing the correct embedding API for the runtime, treating the host environment and sys.path as controlled resources, and insisting on transactional switching with rollback, the backend achieves predictable, production‑grade behavior without sacrificing flexibility.


Implementation of Python interpreter hot switching in Cantor backend architecture

In Cantor’s backend architecture, the Python interpreter is embedded in a long‑running service process, and the frontend communicates with it via a lightweight protocol over standard input and output. The essence of runtime virtual‑environment switching is not to replace this service process but to terminate the current interpreter and reinitialize a new interpreter context within the same process, thereby avoiding any rebuild of the frontend‑backend communication channel. This approach requires a stable message protocol, controllable interpreter lifecycle management, consistent cross‑platform path and environment injection, and compatibility constraints combined with transactional rollback at the version level to ensure safety and observability during switching.

The message protocol adopts a framed “command–response” model with explicit separators and covers environment switching, environment query, and environment discovery. When a switch is initiated, the frontend issues the switching command and immediately follows with an environment‑information query to validate the state and synchronize the UI. Upon receiving the command, the service process first resolves the target environment, accepting either a virtual‑environment root directory or an interpreter executable, normalizing both into an environment root and interpreter path, while avoiding misclassification of system directories as virtual environments. Environment detection adheres to cross‑platform structural conventions: pyvenv.cfg and bin/python[3] on Unix‑like systems, Scripts/python.exe and conda‑meta on Windows.

The interpreter “hot‑switch” follows an explicit lifecycle sequence: finalize the current interpreter, then initialize a new one. For Python 3.8 and later, the PyConfig isolated‑initialization path is used with explicit settings for the executable, base_executable, home, and module_search_paths to minimize external interference; for earlier versions, traditional APIs are used in conjunction with environment variable and sys.path injection. To ensure semantic equivalence with terminal‑based environment activation, sys.prefix and sys.exec_prefix are rebuilt, module search paths are reconstructed, and key variables such as VIRTUAL_ENV, PATH, PYTHONHOME, and PYTHONPATH are injected when entering the new environment and cleaned when reverting to the system environment.

The compatibility policy enforces equality on the major.minor version. After the first successful initialization, the initialized interpreter version is recorded; subsequent switches are permitted only to environments with the same major.minor, mitigating uncertainty introduced by cross‑version ABI or interpreter‑state differences. The switching operation is transactional: prior to finalization, the current environment and version are cached; if initializing the new environment fails, the system automatically rolls back to the previous environment and restores version information, ensuring the server remains available under exceptional conditions. Observability is provided by returning key details—environment root, interpreter path, and version—through the query command, enabling UI presentation and traceability at interpreter granularity; diagnostic outputs are produced on critical paths such as version mismatch, initialization failure, and environment restoration to facilitate investigation of cross‑platform and resolution issues.

The Settings page’s interpreter selector uses a “lazy‑load plus runtime cache” strategy. On first entry, it recursively scans the user directory and conventional locations, deduplicating and classifying environments based on structural markers and version probing; immediately after rendering, it asynchronously requests the backend’s current environment, and if no response arrives within a bounded timeframe, it falls back to locally detecting the active interpreter to ensure sensible defaults in both the drop‑down and input field. To avoid UI jitter, switching is triggered by an explicit confirm/apply action; once applied, an environment‑change signal is emitted, the session layer issues a combined “switch plus query” command to complete the closed loop, and the results are fed back to the UI. Both success and failure are reported in a uniform response format; on failure, the Settings page raises a one‑time warning for the dialog session and automatically realigns to the last known‑good environment to preserve a stable user experience.

In typical usage, providing an absolute interpreter path is recommended for its determinism and cross‑platform clarity; supplying a virtual‑environment root is also supported, and the system will resolve the corresponding interpreter automatically. Returning to the system interpreter can be achieved via an empty path or a dedicated “system interpreter” option in the UI; the backend will clear injected variables and restore system path semantics. When switching across minor versions is required, a more robust practice is to manage backend instances at the major.minor granularity—or to separate them explicitly in the UI—to reduce the frequency of rollbacks and perceived interruptions.

The end‑to‑end interaction sequence and the Settings page “discover–compare–align–apply” workflow are illustrated by the two diagrams above. The former depicts message exchange and lifecycle management across the Settings page, session layer, service process, and embedded interpreter; the latter details environment enumeration, validation, backend alignment, and user confirmation. Together they constitute an engineering‑grade runtime virtual‑environment switching loop that balances stability, cross‑platform consistency, and observability, meeting both interaction and maintainability requirements.


Pic 6. End-to-end timing of runtime switching


Pic 7.  Set up the "Discover-Compare-Align-Apply" workflow on the page



How to switch Python virtual environment through cantor

1. When you open Cantor, if you do not select a virtual environment in the General Tab of Configure Cantor, the Python in the current system will be opened by default. You can get the environment linked to the current Python interpreter by entering "sys.path"

2. 
Open the General Tab of Configure Cantor. You can use the top two options to choose to manually import through the folder (the default is to perform a 5-level recursive search) or manually select the Python interpreter to import the virtual environment.

3. Select the virtual environment you want to switch to and click "Apply" to switch to the new environment


4. Enter "sys.path" again to verify


5. If you select the wrong virtual environment version, the system will prompt an error
                                          

6. If the environment switch fails, the program will fall back to the last successfully switched environment, which is "venv1" in this test



 

Project Structure of Virtual Environments Created with virtualenv or venv

When we create a Python virtual environment, the system automatically generates a complete directory structure to isolate project dependencies. As shown in the image, the venv1 virtual environment contains several core directories, each serving specific functions.

Core Directory Overview

The virtual environment's root directory contains four main directories: bin, include, lib, and lib64, along with an important configuration file pyvenv.cfg. This structure design mimics the layout of system-level Python installations, ensuring environment integrity and independence.

bin Directory: Executable File Hub

The bin directory is the execution center of the virtual environment, containing all executable files and scripts. The most important among these are various activation scripts, such as activate.csh, activate.fish, and activate.ps1, which correspond to different shell environments. When you execute source bin/activate, you're actually running these scripts to modify environment variables.

Additionally, this directory contains symbolic links to the Python interpreter, such as python, python3, and python3.12, all pointing to the same Python interpreter instance. Package management tools pip, pip3, and pip3.12 are also located here, ensuring that packages installed in the virtual environment don't affect the system-level Python environment.

include Directory: Header File Repository

The include directory primarily stores Python header files, particularly the C API header files in the python3.12 subdirectory. These files are crucial when compiling Python packages containing C extensions, such as numpy, scipy, and other scientific computing libraries. The virtual environment provides copies of these header files to ensure compilation process consistency.

lib Directory: Core Library Repository

The lib directory is the core of the virtual environment, containing the actual files of Python standard library and third-party packages. The site-packages folder in the python3.12 subdirectory is where all packages installed via pip are stored. This directory's isolation ensures that dependencies between different projects don't conflict with each other.

lib64 Directory: Architecture Compatibility Support

lib64 is typically a symbolic link pointing to lib. This design is primarily to support the library file lookup mechanism for 64-bit systems. In some Linux distributions, the system searches both lib and lib64 directories, and the symbolic link ensures compatibility.

pyvenv.cfg: Environment Configuration Core

The pyvenv.cfg file is the configuration core of the virtual environment, recording the environment's basic information, including the Python interpreter path, version information, and whether system site-packages are included. This file determines the virtual environment's behavior mode.

Python Interpreter's System Environment

According to the image, this is a Python 3.12.3 Linux environment, showing the Python interpreter's module search paths through sys.path.

First is the /usr/lib/python312.zip path, which represents Python's standard library compressed package. This is an optimization strategy where Python packages core standard library modules into a zip file to improve loading speed and save disk space. When importing standard library modules like os, sys, and json, the Python interpreter first searches in this compressed file.

The next /usr/lib/python3.12 directory is the main installation location for Python's standard library. This contains all standard library modules written in pure Python, as well as some configuration files and auxiliary scripts. This directory's structure reflects Python's module organization approach, containing complete implementations of packages such as collections, concurrent, and email.

The /usr/lib/python3.12/lib-dynload directory specifically stores dynamically loaded extension modules, which are typically modules written in C or C++ and compiled into shared libraries. These extension modules provide Python with the ability to interact with the underlying system, including file system operations, network communication, mathematical calculations, and other performance-critical functions.

In package management, the /usr/local/lib/python3.12/dist-packages directory plays an important role. This is the storage location for system-level installed third-party packages, typically installed through system package managers or pip packages installed with administrator privileges.

Finally, the /usr/lib/python3/dist-packages directory is another storage location for third-party packages, usually containing Python packages installed through Linux distribution package management systems. This design allows system package managers and Python package managers to coexist harmoniously, avoiding dependency conflicts.

This directory structure design reflects several important principles of the Python ecosystem. First is modular and layered management, where different types of modules are clearly separated into different directories. Second is the priority mechanism, where Python searches these directories in the order of sys.path, ensuring correct module loading behavior. Finally is package management flexibility, supporting multiple installation methods and management strategies.

System Environment Changes After Switching to Virtual Environment


When we activate a virtual environment, the Python interpreter's module search paths undergo fundamental changes. The comparison in the image clearly shows the differences in sys.path before and after virtual environment activation, revealing the sophisticated design of the virtual environment isolation mechanism.

When the virtual environment is not activated, sys.path follows the standard system-level path structure, with the Python interpreter searching for modules according to established priority order. However, once the source bin/activate command is executed to activate the virtual environment, the system cleverly inserts virtual environment-specific paths at the beginning of the sys.path list.

The most significant change is the addition of /home/zjh/test_venv/venv1/lib/python3.12/site-packages to the first position of the search path. This seemingly simple adjustment is actually the core of the virtual environment isolation mechanism. Python's module search follows the "first found, first used" principle, so when the virtual environment's site-packages directory is at the front of the search path, any packages installed in the virtual environment will be loaded preferentially.

This path priority reordering creates an elegant hierarchical overlay system. If you install a specific version of a package in the virtual environment, such as Django 4.2, while the system-level environment has Django 3.2 installed, then with the virtual environment activated, the Python interpreter will prioritize using Django 4.2 from the virtual environment. This mechanism ensures dependency precision and predictability.

It's worth noting that the virtual environment doesn't completely isolate system-level Python paths but adopts a more pragmatic approach. System-level paths, such as /usr/lib/python312.zip and /usr/lib/python3.12, remain in the search path, but with reduced priority. This means projects in the virtual environment can still access the Python standard library and system-level installed packages, but will prioritize versions from the virtual environment.

This design philosophy reflects the inclusiveness and practicality of the Python ecosystem. The standard library, as Python's core component, should remain accessible in all environments, while third-party packages achieve project-level isolation through virtual environments. Developers don't need to worry about reinstalling standard library modules like os and sys in virtual environments, while being able to precisely control project's third-party dependencies.

From a technical implementation perspective, this path management strategy brings another important advantage: high efficiency of environment switching. Activating and deactivating virtual environments is essentially just dynamic modification of sys.path, without requiring copying or moving large amounts of files. This allows developers to quickly switch between different project environments without significant performance overhead.

Runtime Virtual Environment Switching Comparison for Different Python Versions

Based on the significant architectural changes in Python 3.8, virtual environment switching shows distinct watershed characteristics in technical implementation:

Fundamental Restructuring of Initialization API

The PyConfig system introduced in Python 3.8 completely changed the interpreter initialization paradigm. Before 3.8, virtual environment switching relied on relatively simple but crude global variable setting methods, configured through functions like Py_SetProgramName and Py_SetPythonHome. While this approach was intuitive, it lacked fine-grained control capabilities and was prone to configuration conflicts and inconsistent states.

The post-3.8 PyConfig system provides a structured configuration management approach, allowing developers to precisely control every initialization parameter of the interpreter. The new system implements type-safe configuration setting through functions like PyConfig_SetBytesString, significantly reducing the possibility of configuration errors. However, this fine-grained control also brings significant complexity increases, requiring developers to understand and manage more configuration options.

Evolution of Path Management Mechanisms

Pre-3.8 versions mainly relied on environment variables and runtime Python code to manage module search paths. The advantage of this approach is high flexibility, allowing dynamic modification of sys.path through Python code execution. The disadvantage is the difficulty in controlling the timing of path settings, easily leading to path priority confusion issues.

Post-3.8 versions allow precise setting of module search paths during the initialization phase, through mechanisms like config.module_search_paths_set and PyWideStringList_Append, achieving more strict path control. While this approach improves the determinism of path management, it also increases implementation complexity, particularly in string encoding conversion and memory management.

Enhanced Configuration Isolation

Early versions' configurations were mainly managed through global variables and environment variables, with relatively weak configuration isolation between different virtual environments. Environment variable modifications could affect the entire process's behavior, easily causing unexpected side effects. The post-3.8 PyConfig system implements better configuration isolation, with each interpreter instance having independent configuration state. This design reduces mutual influence between different virtual environments, but also requires developers to more carefully manage configuration object lifecycles.

Friday, 22 August 2025

Integrate KTextEditor into Cantor(2)

Over the past few months, I’ve been working on an important refactor in Cantor: migrating the editor for command entries from our in-house QTextDocument implementation to the powerful KTextEditor framework. In my previous update, I described how Phase 1 laid the foundation—command cells were migrated to use KTextEditor::View, enabling basic syntax highlighting and a modern editing experience.

Today, I’m excited to share that Phase 2 is now complete! With this milestone, the migration of command entries to KTextEditor is fully in place, ensuring that all existing functionality works smoothly without regressions. This achievement provides a solid foundation for future enhancements while keeping Cantor stable and reliable for everyday use.

What’s New in Phase 2

With Phase 2 now complete, command entries are fully integrated into KTextEditor. Along the way, we introduced three major upgrades to Cantor’s core architecture, paving the way for a more consistent, powerful, and future-ready user experience.

🔹 Unified Highlighting Framework

All syntax highlighting in Cantor is now powered by KSyntaxHighlighting, the same robust engine behind Kate and KWrite. This change ensures that every backend (such as Python, Maxima, R, Octave, etc.) benefits from a consistent, accurate, and highly reliable highlighting system.

Previously, each backend shipped with its own ad-hoc rules that were difficult to maintain and often inconsistent in style. With the new centralized approach, Cantor handles highlighting uniformly, not only providing a smoother user experience but also laying the groundwork for future support of custom themes and user-defined keywords.


🔹 Unified Completion Infrastructure

Code completion has likewise been consolidated into a common framework coordinated through KTextEditor. In the past, each backend had its own incomplete and sometimes inconsistent completion logic. Now, all completion requests are handled in a unified, predictable manner, with backend-specific intelligent suggestions seamlessly integrated.

The result is less duplicated code, easier maintenance, and—most importantly—a more cohesive user experience. Whether you are writing Python scripts or Maxima formulas, code completion now behaves consistently, making Cantor feel smarter and more reliable.


🔹 Reduced Code Redundancy

By adopting KTextEditor as the core for command entry editing, we eliminated a significant amount of custom code that had been written in Cantor over the years to handle code completion and highlighting for the different supported languages.

This streamlining improves maintainability, reduces potential bug risks, and makes Cantor’s codebase more approachable for new contributors. Developers no longer need to reimplement low-level editor features, allowing them to focus on advancing high-level functionality. In short: less boilerplate, more room for innovation.


Functional demonstration: new and old comparison, take a look!

Thanks to the new KSyntaxHighlighting backend, we can now temporarily change the theme of command entries, demonstrating future possibilities.

Please note that this is currently a preview feature; global “sheet themes” (applying themes uniformly to the entire sheet,) are our next steps.

  • Breeze Dark

  • Github Dark

  • Breeze Light

By integrating KTextEditor, Cantor now provides a unified and reliable code completion experience for all backends (such as Python, R, and Maxima).

Cantor also supports consistent multi-cell handling, with themes and syntax highlighting applied uniformly.

Why This Matters

This migration is not just a technical change under the hood—it directly impacts how Cantor evolves:

  • Stability first: by ensuring no regressions during the migration, users can continue to rely on Cantor for daily work without disruption.
  • Consistency across backends: highlighting and completion now feel the same, no matter which computational engine you choose.
  • Future-proof foundation: less redundant code and more reliance on KDE Frameworks means Cantor can keep pace with new features in KTextEditor and the broader KDE ecosystem.

What’s Next

With command entries now fully migrated, the door is open for exciting new improvements:

  • Theming support: enabling custom color schemes and styles, giving users the ability to tailor Cantor’s appearance to their preferences.
  • Vi mode integration: bringing modal editing from Kate into Cantor.
  • Spell checking: powered by Sonnet, useful for Markdown and explanatory text inside worksheets.
  • Smarter backend completions: richer suggestions, function signatures, and inline documentation.
  • Performance work: optimizing for very large worksheets and heavy computations.

Theming support (planned)

For now, Cantor will keep the Default theme, which uses the desktop palette. This preserves the familiar look and behavior.

Next, we plan to introduce a Worksheet Theme setting. Users will be able to:

  • Stay with Default (desktop palette, as before), or
  • Choose a theme from KTextEditor/KSyntaxHighlighting, just like in Kate.

The selected theme will apply consistently across the worksheet—including command entries and results—for a unified appearance. Instead of relying on hardcoded colors or the system palette, Cantor will use the color roles provided by KTextEditor and KSyntaxHighlighting.

This approach avoids performance overhead from repeatedly reading theme files, ensures instant updates when switching themes, and lays the foundation for richer customization in the future—such as clearer distinctions between prompts, results, and errors, all within a consistent global style.


Wednesday, 20 August 2025

AI Coding with Qt: Qt AI Assistant for Qt Creator

The integration of artificial intelligence into software development environments has rapidly evolved, and Qt Creator is no exception. With the introduction of the Qt AI Assistant by Qt Company, developers working with Qt Creator now have access to AI models through the IDE. This post provides an introduction to the Qt Creator plugin.

This is part 1 of an ongoing series about AI coding with Qt.

What is Qt AI Assistant?

Qt AI Assistant is a commercial plugin for Qt Creator to bring current AI models to the IDE. Features provided by the plugin include

  • Code completion for multiple languages (QML, C++, Python, Bash, etc.)
  • Contextual chat with your codebase, enabling explanations, code generation and code review
  • Automated test case generation, particularly tailored for QML and Qt-specific workflows
  • Model choice based on languages (QML vs other languages) and task (chat vs code completion)

This is a step up from the existing GitHub Copilot support in Qt Creator that was focused on code completion only.

Completing Qt AI Assistant is a publicly available set of models by Qt Group. The models are based on CodeLlama and are fine-tuned for usage with Qt 6 QML. They are not included with the plugin but need to be set up manually using Ollama.

Setting Up Qt AI Assistant

The setup process for Qt AI Assistant is more involved than some other AI coding tools. The plugin is currently available as part of the commercial Qt distribution. Installation requires enabling the appropriate extension repository within Qt Creator and activating the plugin. Once installed, configuration is necessary to connect the plugin to a large language model (LLM) provider.

Supported LLMs include OpenAI (ChatGPT), Anthropic (Claude), Google (Gemini), and self-hosted models via Ollama. For OpenAI integration, developers must use the OpenAI developer platform to generate an API key, which is different from having an account for ChatGPT. This API key is then entered into the plugin’s settings within Qt Creator. Other models require similar setup using URLs and credentials, depending on the provider or the self-hosting method.

More information is in this video linked at the bottom of this blog post.

Features in Practice

Code Completion and Chat

The plugin distinguishes between code completion suggestions as you type and prompt-based interactions, such as asking for code explanations or generating new code. For QML, a specialized Code Llama 13B QML model can be used. For other languages general purpose models are employed.

The chat interface allows developers to highlight code and request explanations or modifications. For example, selecting a block of QML or C++ and asking the assistant to "explain the selected code" yields a detailed, context-aware explanation.

Test Case Generation

A notable feature is the ability to generate test cases from selected QML code. While the generated tests may require manual refinement, this automation can accelerate the initial setup of unit tests and reduce repetitive work. The plugin’s approach is to copy relevant code into the test, which may not always result in optimal reuse, but provides a useful starting point.

Model Choice

Developers can choose between different LLMs to use for the chat and review vs the code completion scenario. For QML model choice is separate, and offers including the fine-tuned models provided by Qt Company. This flexibility extends to hosting options, supporting both cloud and local deployments, depending on organizational needs and privacy considerations.

Further Resources

For a detailed walkthrough and live demonstrations, watch the following episodes of "The Curious Developer" series:

Additionally, the official Qt AI Assistant product page provides up-to-date information on features and availability: https://www.qt.io/product/ai-assistant.

Outlook

Future posts in this series will consider alternative coding tools useful for Qt and will bring the newest developments of the tools we mention here.

The post AI Coding with Qt: Qt AI Assistant for Qt Creator appeared first on KDAB.

Monday, 18 August 2025

Hello all,

I would like to show you my first QtCreator plugin. It is an all-in-one window to test Qml Code.

How often do you run into issue about QML code; not doing exactly what you want ?

Demo:

 

 

Examples demo:

 

Here it a simple tool to test quickly some QML code. No need to create a new Test Project.
Open the plugin, type or copy/paste your code, do some changes until it does what you want.

It is mostly inspired from some Qml online site, but it is available directly into QtCreator.

 

Git repo: https://github.com/obiwankennedy/QmlSampleEditor

Download: https://github.com/obiwankennedy/QmlSampleEditor/actions/runs/

The Kdenlive team is happy to announce the release of version 25.08.0 packed with over 300 commits and fixing more than 15 crashes. This release has no major shiny new features, just a ton of bug fixes and lots of polishing to give you a pleasant editing experience in the summer heat.

Interface and Usability

Mixer

Redesign of the audio mixer bringing levels with clearer visuals and thresholds. We also did some code refactoring and cleanup. This change fixes issues with HiDPI displays with fractional scaling.

Screenshot of <nil>
Screenshot of <nil>
Screenshot of <nil>
Screenshot of <nil>

Titler

This release the titler received some much needed love like improved SVG and image support with ability to move and resize items, added center resize with Shift + Drag, and renamed the Pattern tab to Templates and moved the templates dropdown to it:

Other fixes include:

  • Added timecode widget with ability to drag to seek in the Titler,(Shift+drag for 1 frame, CTRL+drag for fast seek) Fix issues when resizing images would also moves them
  • Fix titler selection on create / resize object
  • Fixed an issue where the titler's panel width was consuming half the screen
  • Save and restore the panel width on reopening
  • Fix title thumbnail not updating in timeline after change

Scopes

Improved Scope styling by using system palettes for better theme integration as well as bug fixes in artifacts on high zoom level and paint modes. Compare the old styling on the left side with the new styling on the right:

Screenshot of <nil>
Screenshot of <nil>
Screenshot of <nil>
Screenshot of <nil>

Subtitles and Speech-To-Text

  • Require shift + drag of a subtitle clip to create a new layer
  • Make the subtitle edit widget resizable to adapt to lower resolutions
  • Fix crash dropping media file on subtitle track
  • Subtitle code refactoring
  • Fix subtitle layer name width
  • Fix subtitles showing on the top layer rather than appearing in lower layers on project loading.
  • Fix Whisper STT using Python 3.13
  • Whisper: disable translation when the Turbo model is selected
  • Fix Vosk STT producing bad subtitles

Markers and Guides

Guides and Markers got a major overhaul this release to improve the project organization.

  • Clicking a marker in the list now always selects it in the timeline
  • When adding a new marker, it’s automatically selected in the guides list
  • Selecting a guide in the timeline also highlights it in the guides list
  • New option to show thumbnails in the markers list dialog
  • Added a “Show markers for all clips in the project” toggle to display markers in other sequences
  • Consistently use bookmark icon for guides/markers
  • Improves Project Notes integration
  • Render dialog now updates correctly when sequence offsets change
  • Sequence timecode offsets now propagate to the timeline ruler, monitor, and guides list
  • Guides are correctly adjusted when changing project profile to match a clip profile

Project Notes

image

Some highlights include: improve icons, automatically convert typed timecodes to links when pressing enter, fix pasting text with multiple lines, notes can create guides and markers directly, and the widget has improved icons and text handling

Monitors

  • Add handle to rotate an item using the Transform effect in the monitor
  • Fix rotoscoping shape not matching selection in monitor
  • Fix monitor overlay for Obscure and Alpha Shape effects
  • Fix Transform monitor tool resizing when rotated
  • Fix pattern/lines overlay of the project monitor misaligning if clip changes while zoomed in
  • Improved monitor snapping: added back snapping when resizing for non-rotated frames, snapping when moving a rotated frame, and added snapping support for all edges when moving instead of only top-left
  • Change Timecode color of active Monitor
  • Make sure playhead is always on top of indicators
  • Make transform effect monitor grid setting apply to both monitors
  • Fix keyframe in monitor not correctly reported on clip selection
  • Adjust monitor timecode for sequence clips with timecode offset
  • Monitor code cleanup

Video Processing

We've added work on rendering, encoding, decoding, and transcoding such as:

Decoding

  • Added Enable Hardware Decoding option in the Config Wizard in preparation for future hardware acceleration features

Rendering / Encoding

Screenshot of <nil>
Screenshot of <nil>
  • Added power management option to disable sleep while rendering and playing
  • Added Nvidia 10 bit x265 encoding
  • Added 10 bit export profiles in the render dialog (Do note that it will be converted to 8 bit when using compositing or non avfilter effects)
  • Fix image sequence render incorrectly reported as failed
  • Ensure audio checkbox is disabled if rendering to an image sequence
  • Fix possible locale issue on render in Mac/Windows
  • Added ability to show log files in render dialog Job Queue tab
  • Added option to keep log files in the render dialog options
  • Replace AV1 profile with faster SVT-AV1 and added preset option to control quality and speed
  • AddedSVT-AV1 to codecs which use CRF option
  • Fix canceling a render would leave Kdenlive in an unstable state
  • Warn when exiting Kdenlive when render jobs are running, allow to terminate all jobs
  • Update render dialog guides when sequence offset changes
  • Display timecode offset in render dialog

Under the hood

  • Reduced memory consumption of the background removal (SAM2) feature
  • Added more code tests to improve stability
  • Improved packaging in MacOS, Windows, Snaps and Flatpak
  • Cleanup plugins configuration page
  • Fix SAM2 use system packages hidden
  • Allow installing specific CUDA version for Whisper and SAM2
  • Fixes to undo/redo operations
  • OpentimelineIO (OTIO) fixes
  • Drop mediainfo dependency now that we can directly read timecode from MLT

Fixed platform specific issues:

  • MacOS: Allow opening project files by double click (3 year old bug)
  • Windows: Typewriter effect crash in Titler
  • AppImage: Fix missing / corrupted font making App unusable on Ubuntu 24.04

Upcoming events

image

The team will be in Berlin this September for two events. First, the Kdenlive Sprint which will include a community meetup on the 4th of September (stay tuned for more details) and on the 7th of September we'll be at Akademy, where Jean-Baptiste will give a talk about our fundraiser experience. Join us!

Give back to Kdenlive

Releases are possible thanks to donations by the community. Donate now!

Need help ?

As usual, you will find very useful tips in our documentation website. You can also get help and exchange your ideas in our Kdenlive users Matrix chat room.

Get involved

Kdenlive relies on its community, your help is always welcome. You can contribute by :

  • Helping to identify and triage bugs
  • Contribute to translating Kdenlive in your language
  • Promote Kdenlive in your local community

For the full changelog continue reading on kdenlive.org.