Qt for MCUs 2.2.2 Released

Qt for MCUs 2.2.2 has been released and is available for download. As a patch release, Qt for MCUs 2.2.2 provides bug fixes and other improvements, and maintains source compatibility with Qt for MCUs 2.2.x. It does not add any new functionality.

KDDockWidgets 1.6.0 released, Is the i.MX 8 right for your project? KDAB tools and video releases

 

&

96

 

­
­
­
­
­
­
­

Welcome to September’s news from KDAB

This month we had a company meeting in Vilnius and about 100 KDABians enjoyed being together in the same space for the first time in more than a few years. There was information sharing on multiple levels, getting to know new folk, and a good deal of fun. What else happened in Vilnius stays in Vilnius but suffice it to say there were a lot of potatoes involved 😉

We bring you a potato-free newsletter, nonetheless, with Choosing a CPU: is the i.MX 8 right for your project?, the release of KDDockWidgets 1.6.0 and news of other KDAB tool releases.

We also offer new releases in the Qt Widgets and More series and a multitude of videos from, and news about Events.

­
­
­
­
­
­
­
­
­

Choosing a CPU

Is the i.MX 8 right for your project?

­
­
­
­
­

by Till Adam

­

We’ve learned some hard-won lessons in using i.MX 8 silicon to bring customer projects to life and have helped customers determine which CPU is the most appropriate for their current product and future roadmap.

In this blog, we share some of our CPU choice considerations, helping eliminate some of the unknowns and hopefully clearing away some misconceptions in the process.

Read the blog.

­
­
­
­
­
­
­
­
­
­

KDDockWidgets 1.6.0 released

now supporting Qt 6.2

­
­
­
­
­

Our framework for custom-tailored docking systems in Qt got a major upgrade this month. Whilst it still, of course, supports Qt 5, now Qt 6 is supported from version 6.2.0. And there’s more.

Check out the release notes on github.

Find out more about KDDockWidgets.

­
­
­
­
­
­
­
­
­
­
­
­
­
­
­
­

KDAB tools re-licensed to MIT

KDAB recently made the decision to relicense many of our free tools from GPL to the less restrictive MIT. These are the tools we released this month – they can all be downloaded free.

­
­
­
­
­
­

KDChart 3.0.0

KDChart is a comprehensive business charting package with many different chart types and a large number of customization options.

KDChart 3 is the first release of KDChart that supports Qt 6, and both Qt 5 and Qt 6 can be co-installed.

Check out the release highlights.

Find out more and download KDChart.

­
­
­
­
­
­
­
­
­
­

KDSoap 2.1.0

KDSoap 2.1.0 was also released this September.

KD SOAP is a tool for creating client applications for web services. Among other things, KD SOAP makes it possible to interact with applications which have APIs that can be exported as SOAP objects. The web service then provides a machine-accessible interface to its functionality via HTTP.

Check out the release highlights.

Find out more and download KDSoap.

­
­
­
­
­
­
­
­
­
­

KDReports 2.2.0

KD Reports creates all kinds of reports from within Qt applications, generating printable and exportable reports from code and from XML descriptions.

Reports may contain text paragraphs, tables, headlines, charts, headers and footers and more.

KDReports 2.2.0 release notes are here.

Find out more and download KDReports.

­
­
­
­
­
­
­
­
­
­
­
­
­

Qt Widgets & More Releases

­
­
­
­
­

We kick off with two episodes where Jesper and Giuseppe D’Angelo have fun sharing their knowledge with you: Which String Class in Qt should I use? and QStringBuilder.

Then we have Save Re-compile Time – Include moc Files in Source Files, where Jesper explains how he went from 22 seconds to 5 when recompiling.

Finally, in Improving my Clang-Tidy Checks, Jesper reveals some of the not-so-welcome surprises he got from checking checks – and what he did about it.

Access the Qt Widgets and More playlist.

­
­
­
­
­

Which String Class in Qt should I use?

­
­

Save Re-compile Time – Include moc Files in Source Files

­
­
­
­

QStringBuilder

­
­

Improving my Clang-Tidy Checks

­
­
­
­
­
­
­
­
­
­
­
­

Video Releases from Qt Developer Conference

­

We released twelve more videos since the last Newsletter. They are all excellent. Take a look at the four randomly selected below, but see the full list here. There’s more to come!

­
­
­
­
­
­

KDE’s journey to Qt 6, by Nicolas Fella.

Since 25 years, code developed by the KDE Community has been ported to Qt. The next major version transition is coming with Qt 6.

Hybrid Qt Development: Boosting Your Projects with Python, by Dr Christián Maureira-Fredes.

About adding new technology to the Qt ecosystem.

25k Stars Later – How to Survive Maintaining a Popular GitHub Project in Your Spare Time, by C++ developer Niels Lohmann. The title says it well.

How Can I Make My Qt Apps More Rusty?

Andrew Hayzen and Leon Mathes offer a practical approach for adding Rust to existing C++ projects.

­
­
­
­
­

KDE’s Journey to Qt 6

­
­

25k Stars Later – How to Survive Maintaining a Popular GitHub Project in Your Spare Time

­
­
­
­

Boosting Your Projects with Python

­
­

How Can I Make My Qt Apps More Rusty?

­
­
­
­
­
­
­
­
­
­
­

ACCU Video Releases

­

Here are a couple of talks given by KDAB’s James Turner at ACCU earlier this year. We somehow missed them when they came out, so we thought maybe you did as wel

How Code Fails in the Real World

– about bugfixing an open source project: the horrors, the solutions.

Properties and Bindings for Modern C++

– about getting Qt’s declarative language goodness into C++.

Sit down and enjoy a highly informative and fun ride.

There’s a playlist for ACCU here.

­
­
­
­
­
­
­
­
­
­
­
­
­
­
­
­
­
­
­

More on Events

CppCon happened last week (see the pre-release videos here), KDE Akademy is about to happen (Oct 1 – 7), and we are proud to have sponsored both events.

­
­
­
­

This month, instead of the usual rundown of what’s coming up, we decided to simply share our KDAB News report where you’ll find out about Qt World Summit (November 9th, plus meetups later) as well as other news.

Most importantly though, founder Jens Weller talks about Meeting C++ (November 17 – 19), and what it’s like running such an event 10 years on.

While we’re on the subject, if C++ is your bag, you might also like to watch or listen to this – an in-depth discussion on the Future of C++ – an international panel discussion with C++ experts.

­
­
­
­
­
­
­
­ ­
­
­

 

The post KDDockWidgets 1.6.0 released, Is the i.MX 8 right for your project? KDAB tools and video releases appeared first on KDAB.

Qt 6.4 Released

Today we have released Qt 6.4! The latest version of Qt introduces support for a new platform, brings lots of new functionality - some as technology previews (TP) - and plenty of improvements under the hood. Let's start with the biggest highlight.

Dialogs in Qt Quick

The Qt Quick Dialogs module has undergone a lot of changes in the last two years. Its purpose has always been to make it simple for developers to add dialogs to their applications. Native dialogs should be used by default on platforms that have a native dialog for a specific dialog type, and if the system can't provide one, then the module should fall back to a suitable dialog that's implemented in Qt.

How to create a REST API with QtHttpServer

Current status of QtHttpServer

Back in 2019 we announced QtHttpServer to the public, now we are extremely happy to introduce a technical preview,
starting in Qt 6.4. for this project.

What is QtHttpServer

Qt Http Server is a high-level API that provides easy support for implementing an HTTP server in your application.
It is designed to be embedded in applications to expose things on a trusted network and does not have robustness/security as a goal, it is not suitable for use on the public internet.

How does the REST API work

The REST API communicates with the server using HTTP. The REST API is used to perform CRUD - create, read, update, delete - operations on a given resource. This uses a variety of HTTP methods (e.g. GET for reading operations, POST for creating operations, PUT and PATCH for updating resources, and DELETE for deleting data). Data is usually transmitted via HTTP request/response bodies in the form of JSON objects.

Implementing a REST API

For the sake of simplicity, we will discuss only a few of the most important parts like routing, handling requests, creating responses and basic authorization. Fully functional examples can be found in the documentation.

Hello world

#include <QtCore>
#include <QtHttpServer>

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);
    QHttpServer httpServer;

    const auto port = httpServer.listen(QHostAddress::Any);

    if (!port)
        return 0;

    qDebug() << QCoreApplication::translate("QHttpServerExample",
            "Running on http://127.0.0.1:%1/ (Press CTRL+C to quit)").arg(port);
    return app.exec(); 
} 


Let's start with the backbone of our server. We create a QCoreApplication with QHttpServer running on our local address. We leave QHttpServer to choose a port. Next, we need to make the server route specific requests to suitable handlers.

Define routes

Does WebAssembly Matter for Embedded System Makers?

WebAssembly is an emerging technology that allows high-performance apps programmed with languages like C++ to run in web browsers. These applications are compiled into binary format and then executed in the browser in a sandboxed environment. This is excellent news for developers that create resource-intensive desktop applications such as image processing or gaming. But how is WebAssembly relevant for embedded device makers?

Getting started with VS Code for Python: Setting up a development environment

Setting up a working development environment is the first step for any project. Your development environment setup will determine how easy it is to develop and maintain your projects over time. That makes it important to choose the right tools for your project. This article will guide you through how to set up Visual Studio Code, which is a popular free-to-use, cross-platform code editor developed by Microsoft, in order to develop Python applications.

Visual Studio Code is not to be confused with Visual Studio, which is a separate product also offered by Microsoft. Visual Studio is a fully-fledged IDE that is mainly geared towards Windows application development using C# and the .NET Framework.

Setup a Python environment

In case you haven't already done this, Python needs to be installed on the development machine. You can do this by going to python.org and grabbing the specific installer for either Windows or macOS. Python is also available for installation via Microsoft Store on Windows devices.

Make sure that you select the option to Add Python to PATH during installation (via the installer).

If you are on Linux, you can check if Python is already installed on your machine by typing python3 --version in a terminal. If it returns an error, you need to install it from your distribution's repository. On Ubuntu/Debian, this can be done by typing sudo apt install python3. Both pip (or pip3) and venv are distributed as separate packages on Ubuntu/Debian and can also be installed by typing sudo apt install python3-pip python3-venv.

Setup Visual Studio Code

First, head over to to code.visualstudio.com and grab the installer for your specific platform.

If you are on a Raspberry Pi (with Raspberry Pi OS), you can also install VS Code by simply typing sudo apt install code. On Linux distributions that support Snaps, you can do it by typing sudo snap install code --classic.

Once VS Code is installed, head over to the Extensions tab in the sidebar on the left by clicking on it or by pressing CTRL+SHIFT+X. Search for the 'Python' extension published by Microsoft and click on Install.

The Extensions tab in the left-hand sidebar The Extensions tab in the left-hand sidebar.

Usage and Configuration

Now that you have finished setting up VS Code, you can go ahead and create a new Python file. Remember that the Python extension only works if you open a .py file or have selected the language mode for the active file as Python.

To change the language mode for the active file, simply press CTRL+K once and then press M after releasing the previous keys. This kind of keyboard shortcut is called a chord in VS Code. You can see more of them by pressing CTRL+K CTRL+S (another chord).

The Python extension in VS Code allows you to directly run a Python file by clicking on the 'Play' button on the top-right corner of the editor (without having to type python file.py in the terminal).

You can also do it by pressing CTRL+SHIFT+P to open the Command Palette and running the > Python: Run File in Terminal command.

Finally, you can configure VS Code's settings by going to File > Preferences > Settings or by pressing CTRL+COMMA. In VS Code, each individual setting has an unique identifier which you can see by clicking on the cog wheel that appears to the left of each setting and clicking on 'Copy Setting ID'. This ID is what will be referred to while talking about a specific setting. You can also search for this ID in the search bar under Settings.

Linting and Formatting Support (Optional)

Linters make it easier to find errors and check the quality of your code. On the other hand, code formatters help keep the source code of your application compliant with PEP (Python Enhancement Proposal) standards, which make it easier for other developers to read your code and collaborate with you.

For VS Code to provide linting support for your projects, you must first install a preferred linter like flake8 or pylint.

bash
pip install flake8

Then, go to Settings in VS Code and toggle the relevant setting (e.g. python.linting.flake8Enabled) for the Python extension depending on what you installed. You also need to make sure that python.linting.enabled is toggled on.

A similar process must be followed for code formatting. First, install something like autopep8 or black.

bash
pip install autopep8

You then need to tell VS Code which formatter to use by modifying python.formatting.provider and toggle on editor.formatOnSave so that it works without manual intervention.

If pip warns that the installed modules aren't in your PATH, you may have to specify the path to their location in VS Code (under Settings). Follow the method described under Working With Virtual Environments to do that.

Now, when you create a new Python file, VS Code automatically gives you a list of Problems (CTRL+SHIFT+M) in your program and formats the code on saving the file.

Identified problems in the source code. Identified problems in the source code, along with a description and line/column numbers.

You can also find the location of identified problems from the source overview on the right hand, inside the scrollbar.

Working With Virtual Environments

Virtual environments are a way of life for Python developers. Most Python projects require the installation of external packages and modules (via pip). Virtual environments allow you to separate one project's packages from your other projects, which may require a different version of those same packages. Hence, it allows all those projects to have the specific dependencies they require to work.

The Python extension makes it easier for you by automatically activating the desired virtual environment for the in-built terminal and Run Python File command after you set the path to the Python interpreter. By default, the path is set to use the system's Python installation (without a virtual environment).

To use a virtual environment for your project/workspace, you need to first make a new one by opening a terminal (View > Terminal) and typing python -m venv .venv. Then, you can set the default interpreter for that project by opening the Command Palette (CTRL+SHIFT+P) and selecting > Python: Select Interpreter.

You should now either close the terminal pane in VS Code and open a new one or type source .venv/bin/activate into the existing one to start using the virtual environment. Then, install the required packages for your project by typing pip install <package_name>.

VS Code, by default, looks for tools like linters and code formatters in the current Python environment. If you don't want to keep installing them over and over again for each new virtual environment you make (unless your project requires a specific version of that tool), you can specify the path to their location under Settings in VS Code. - flake8 - python.linting.flake8Path - autopep8 - python.formatting.autopep8Path

To find the global location of these packages on macOS and Linux, type which flake8 and which autopep8 in a terminal. If you are on Windows, you can use where <command_name>. Both these commands assume that flake8 and autopep8 are in your PATH.

Understanding Workspaces in VS Code

VS Code has a concept of Workspaces. Each 'project folder' (or the root/top folder) is treated as a separate workspace. This allows you to have project-specific settings and enable/disable certain extensions for that workspace. It is also what allows VS Code to quickly recover the UI state (e.g. files that were previously kept open) when you open that workspace again.

In VS Code, each workspace (or folder) has to be 'trusted' before certain features like linters, autocomplete suggestions and the in-built terminal are allowed to work.

In the context of Python projects, if you tend to keep your virtual environments outside the workspace (where VS Code is unable to detect it), you can use this feature to set the default path to the Python interpreter for that workspace. To do that, first Open a Folder (CTRL+K CTRL+O) and then go to File > Preferences > Settings > Workspace to modify python.defaultInterpreterPath.

Setting the default interpreter path for the workspace. Setting the default interpreter path for the workspace.

In VS Code settings you can search for settings by name using the bar at the top.

You can also use this approach to do things like use a different linter for that workspace or disable the code formatter for it. The workspace-specific settings you change are saved in a .vscode folder inside that workspace, which you can share with others.

If your VS Code is not recognizing libraries you are using in your code, double check the correct interpreter is being used. You can find which Python version you're using on the command line by running which python or which python3 on macOS/Linux, or where python or where python3 on Windows.

Working With Git in VS Code (Optional)

Using Version Control is required for developing applications. VS Code does have in-built support for Git but it is pretty barebones, not allowing much more than tracking changes that you have currently made and committing/pushing those changes once you are done.

For the best experience, it is recommended to use the GitLens extension. It lets you view your commit history, check who made the changes and much more. To set it up, you first need to have Git set up on your machine (go here) and then install GitLens from the Extensions tab in the sidebar on the left. You can now use those Git-related features by going to the Git tab in the sidebar (CTRL+SHIFT+G).

There are more Git-related extensions you could try as well, like Git History and GitLab Workflow. Give them a whirl too!

Community-driven & open source alternatives

While VS Code is open source (MIT-licensed), the distributed versions include some Microsoft-specific proprietary modifications, such as telemetry (app tracking). If you would like to avoid this, there is also a community-driven distribution of Visual Studio Code called VSCodium that provides freely-licensed binaries without telemetry.

Due to legal restrictions, VSCodium is unable to use the official Visual Studio Marketplace for extensions. Instead, it uses a separate vendor neutral, open source marketplace called Open VSX Registry. It doesn't have every extension, especially proprietary ones, and some are not kept up-to-date but both the Python and GitLens extensions are available on it.

You can also use the open source Jedi language server for the Python extension, rather than the bundled Pylance language server/extension, by configuring the python.languageServer setting. You can then completely disable Pylance by going to the Extensions tab. Note that, if you are on VSCodium, Jedi is used by default (as Pylance is not available on Open VSX Registry) when you install the Python extension.

Conclusion

Having the right tools and making sure they're set up correctly will greatly simplify your development process. While Visual Studio starts as a simple tool, it is flexible and extendable with plugins to suit your own preferred workflow. In this tutorial we've covered the basics of setting up your environment, and you should now be ready to start developing your own applications with Python!

For an in-depth guide to building GUIs with Python see my PyQt6 book.

KDChart 3.0.0 Released

We just released KDChart version 3.0.0!

KDChart is a comprehensive business charting package with many different chart types and a large number of customization options. We are constantly improving the package, and have been doing so for years.

This is the first release of KDChart that supports Qt 6, and both Qt 5 and Qt 6 can be co-installed.

And get this: KDChart 3.0.0 is completely free! We’ve relicensed KDChart from the GPL to the MIT license and removed our commercial offering. This means that you can use it as you want without license restrictions. Find out more about the MIT license, here.

We’ll also be relicensing KDReports, KDSoap, and a few other KDAB products in the not-too-distant future. Feel free to subscribe to our “KDAB Blogs” RSS feed or check out the KDAB GitHub to keep track of the when and where.

For more information…

Find out more about KD Chart here.

To access KDChart 3.0.0 and see the release highlights, visit the GitHub.

Prebuilt packages for some popular Linux distributions are here: https://build.opensuse.org/project/repositories/isv:KDAB

KDAB provides homebrew formulas for Mac users, at https://github.com/KDAB/homebrew-tap.

About KDAB

If you like this article and want to read similar material, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post KDChart 3.0.0 Released appeared first on KDAB.

Flutter vs React Native vs Qt in 2022

Choosing the best framework to develop an application is a tough task. Nonetheless, that is a critical decision to make before starting the development of your next project. Currently, quite a popular method of software development is cross platform software development. What is cross platform development? This is an approach that allows you to reuse code between different operating systems like iOS and Android or macOS and Windows. Following this way of apps development is first of all cost and time effective. In multiple cases, it is a better approach than native app development. Therefore, if you want to follow this approach, reduce costs and develop apps more quickly, you need to use a cross platform framework such as Flutter, React Native or Qt. But which one to choose? In this article, we compare Flutter vs React Native vs Qt to help you answer that question.

The Future of CI

For years, we at KDAB have been using Buildbot as our build and continuous integration system. Gerrit hosts all our projects and is our code review platform. Our deployment of Buildbot and build machines has naturally grown over the years. It builds hundreds of configurations and up to a thousand builds daily, but issues with reliability and quality of service called for a major restructuring. Over the past year, we gradually developed and migrated to new infrastructure and, once that was in place, we were finally able to add some long-awaited features.

Buildbot at KDAB

Buildbot is a continuous integration system written in Python. It offers a high degree of flexibility, because the build configuration is fully written in Python. Thanks to an extensive homegrown library of functions and features, we need only a few lines of code to build, test and package a new C++ and Qt/QML application on Linux, Windows, Mac as well as Android, iOS and other platforms. Many of our projects build against multiple different compilers and Qt versions per platform. Sometimes application bundles need to be signed and notarized (looking at you, Apple). Once the build is finished, the apps are offered for download from our servers and developer app stores like Visual Studio App Center. Developers are notified about build failures per email, our chat system and, of course, in our code review tool Gerrit.

System Architecture

From a system architecture point of view, Buildbot follows a master/worker paradigm: Workers are virtual machines, bare metal servers or docker containers with build environments. Each worker runs a Buildbot process which receives and executes build commands. A central master keeps track of changes in Gerrit, build configurations, workers, builds and build results. In large deployments like ours, the master is made up of multiple Buildbot processes with different responsibilities: One process to serve the web interface, and another to coordinate builds. They rely on a variety of additional services: MariaDB for data storage, Apache2 to manage user authentication and Crossbar.io to coordinate messages between the master’s Buildbot processes. The Buildbot master centrally controls how builds are run on the workers and issues every build command individually to the respective worker.

Diagram of Buildbot Infrastructure at KDAB

This setup enabled, among others, the following features:

  • build 100s of projects, configurations and builds daily, 
  • monitor 100s of Git repositories for changes, hosted on our internal Gerrit, on GitHub and other platforms
  • report build results via email, into our chat system, to Gerrit and GitHub – accessible to customers and KDABians alike
  • web interface to provide insight into builds (for KDABians only) and build artifacts

Over the past years, the number of projects and daily builds has grown steadily. The speed of builds and of the web interface degraded correspondingly. The master processes and all accompanying services were hosted on a single VM with a networked file system – and the file system was quickly identified as main bottleneck. Unfortunately, the traditional approach to deployment hampered our efforts to move the system to bare metal hardware with decent file system speed: All dependencies, the services and Buildbot itself were installed directly on the system using the system package manager and Python’s pip. Buildbot configuration relied heavily on hard-coded values, including IP addresses and file system paths. For every new instance we would have to recreate the setup step by step, a very laborious process that would have left us with a setup just as inflexible as the old one.

Modern Buildbot at KDAB

Therefore, we decided to encapsulate Buildbot and all services in Docker containers and use Docker Compose to describe the whole stack. To that end, we undertook the following steps:

  • refactor the Buildbot configuration so that the configuration supports multiple independent instances of the Buildbot master:
    • read instance-specific parameters like URL, website name, address of back-end services, etc. from environment variables
    • allow to read different Python scripts to describe builds and build workers, configured via environment variables
  • create Docker images
    • for Buildbot, including all dependencies and our custom patches
    • for Apache2
    • for an SSH server to receive artifact uploads from workers
    • a monitoring solution (Telegraf) to collect performance data from the services
    • and more
  • create a Docker Compose configuration to describe the services and their interactions

The Docker Compose configuration is instance-independent: In order to create a new instance of Buildbot master, with its own set of workers, build configuration, URL, name and so forth, we simply copy the Docker Compose configuration to the host system and create an environment file which describes the instance. Now, setting up a new Buildbot instance.

Quality of Service Improved

Provided with these new tools, we directly created two new Buildbot instances: One to replace the old instance for KDAB-internal and customer projects, and another to build projects of one of our larger customers. For this customer we already provided code hosting and continuous integration services, but their developers could not directly access Buildbot’s web interface with details on the builds, due to limitations in Buildbot’s access management. The new separate instance removes this obstacle, and our customer now has full access to builds.

The transition brought about many other improvements to our customers, developers and system administrators:

  • Build speed improved drastically: The time from creation of a commit on Gerrit to the beginning of the respective builds lowered from typically more than 5 minutes to less than a second. The overall build time often sank by more than 50 %.
  • The system became more reliable with less crashes and freezes.
  • Time to update build configuration on the fly, e.g. to add a new project, decreased from minutes to a few seconds.
  • Special configuration of Apache2 allows to easily brand the Buildbot web interface not only by changing the instance’s name but also by changing colors, a feature which Buildbot does not offer natively.
  • We can offer dedicated Buildbot instances to customers so that they have direct access to build results.

Build Results in Gerrit

For years platforms like GitHub present build results in the web interface and have build failures block merges. Gerrit has only offered rudimentary support for this. Buildbot could block submission of patches. It could also create comments to inform about build errors. But the presentation in Gerrit was cluttered and often confusing, a workaround.

Luckily, Gerrit 3.4 introduced the Checks API. JavaScript plug-ins in Gerrit fetch information from a CI system and supply it to the Gerrit web interface. Gerrit then displays the build results right there with the commit message and review comments. The interface shows every build configuration separately, and even build output like compile errors or test failures are right there in Gerrit. The Gerrit project provides an example of what it can look like:

Example of Gerrit's Check UI

So far, there is no plug-in for Buildbot publicly available, so we developed our own. Now, when a developer opens a change on Gerrit, our JavaScript plug-in queries Buildbot’s REST API for builds. The script will automatically determine the correct instance of Buildbot, and whether the user has access to that particular instance at all.

We needed to come up with a few tricks to make this happen. First, Buildbot did not allow to efficiently query builds for a Gerrit change. We added that feature, provided the patch to Buildbot upstream, and deployed it on our instances. This, by the way, is not our first contribution to Buildbot. Over the years we contributed 40 patches. Second, we introduced an additional endpoint on the web server to gracefully check whether a Gerrit user has access to a particular Buildbot instance in the first place. We do this to avoid unnecessary log-in dialogs in the web interface. Third, we created a custom data store in Gerrit to map repositories to Buildbot instances.

The new Docker Compose configuration helped significantly with this: We could easily develop and test all of these changes on local development instances of Buildbot. Deployment to the production instances was also quick and efficient. Fundamentally, without the performance improvements that the new instances brought, this feature would have not been possible. Feedback by our developers has been great so far.

Conclusion

This is not all, of course. We are currently looking into using Docker and VM images to create reproducible build environments. Developers get access and can then debug build failures  in the exact same environment as the CI. We are also investigating ways to upstream the Gerrit plug-in.

We at KDAB consider best practices and efficient workflows to be a large part of creating great software. That is why we keep investing into better infrastructure, for ourselves and for our customers. If you’d like to learn details about our infrastructure or discuss similar projects, feel free to get in touch.

 

About KDAB

If you like this article and want to read similar material, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post The Future of CI appeared first on KDAB.

Which Python GUI library should you use in 2022?

Python is a popular programming used for everything from scripting routine tasks to building websites and performing complex data analysis. While you can accomplish a lot with command line tools, some tasks are better suited to graphical interfaces. You may also find yourself wanting to build a desktop front-end for an existing tool to improve usability for non-technical users. Or maybe you're building some hardware or a mobile app and want an intuitive touchscreen interface.

To create graphical user interfaces with Python, you need a GUI library. Unfortunately, at this point things get pretty confusing -- there are many different GUI libraries available for Python, all with different capabilities and licensing. Which Python GUI library should you use for your project?

In this article, we will look at a selection of the most popular Python GUI frameworks currently available and why you should consider using them for your own projects. You'll learn about the relative strengths of each library, understand the licensing limitations and see a simple Hello, World! application written in each. By the end of the article you should feel confident choosing the right library for your project.

Tkinter

Best for simple tool GUIs, small portable applications

Tkinter is the defacto GUI framework for Python. It comes bundled with Python on both Windows and macOS. (On Linux, it may require downloading an additional package from your distribution's repo.) Tkinter is a wrapper written around the Tk GUI toolkit. Its name is an amalgamation of the words Tk and Interface.

Tkinter is a simple library with support for standard layouts and widgets, as well as more complex widgets such as tabbed views & progressbars. Tkinter is a pure GUI library, not a framework. There is no built-in support for GUIs driven from data sources, databases, or for displaying or manipulating multimedia or hardware. However, if you need to make something simple that doesn't require any additional dependencies, Tkinter may be what you are looking for. Tkinter is cross-platform however the widgets can look outdated, particularly on Windows.

Installation Already installed with Python on Windows and macOS. Ubuntu/Debian Linux sudo apt install python3-tk

A simple hello world application in Tkinter is shown below.

python
import tkinter as tk

window = tk.Tk()
window.title("Hello World")


def handle_button_press(event):
    window.destroy()


button = tk.Button(text="My simple app.")
button.bind("", handle_button_press)
button.pack()

# Start the event loop.
window.mainloop()

python
from tkinter import Tk, Button


class Window(Tk):
    def __init__(self):
        super().__init__()

        self.title("Hello World")

        self.button = Button(text="My simple app.")
        self.button.bind("", self.handle_button_press)
        self.button.pack()

    def handle_button_press(self, event):
        self.destroy()


# Start the event loop.
window = Window()
window.mainloop()

Tkinter Application Screenshot Hello world application built using Tkinter, running on Windows 11

Tkinter was originally developed by Steen Lumholt and Guido Van Rossum, who designed Python itself. Both the GUI framework and the language are licensed under the same Python Software Foundation (PSF) License. While the license is compatible with the GPL, it is a 'permissive' license (similar to the MIT License) that allows it to be used for proprietary applications and modifications.

PyQt or PySide

Best for desktop applications, multimedia, scientific and engineering software

PyQt and PySide are wrappers around the Qt framework. They allow you to easily create modern interfaces that look right at home on any platform, including Windows, macOS, Linux and even Android. They also have solid tooling with the most notable being Qt Creator, which includes a WYSIWYG editor for designing GUI interfaces quickly and easily. Being backed by a commercial project means that you will find plenty of support and online learning resources to help you develop your application.

Qt (and by extension PyQt & PySide) is not just a GUI library, but a complete application development framework. In addition to standard UI elements, such as widgets and layouts, Qt provides MVC-like data-driven views (spreadsheets, tables), database interfaces & models, graph plotting, vector graphics visualization, multimedia playback, sound effects & playlists and built-in interfaces for hardware such as printing. The Qt signals and slots models allows large applications to be built from re-usable and isolated components.

While other toolkits can work great when building small & simple tools, Qt really comes into its own for building real commercial-quality applications where you will benefit from the pre-built components. This comes at the expense of a slight learning curve. However, for smaller projects Qt is not really any more complex than other libraries. Qt Widgets-based applications use platform native widgets to ensure they look and feel at home on Windows, macOS and Qt-based Linux desktops.

Installation pip install pyqt6 or pip install pyside6

A simple hello world application in PyQt6, using the Qt Widgets API is shown below.

python
from PyQt6.QtWidgets import QMainWindow, QApplication, QPushButton

import sys


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Hello World")

        button = QPushButton("My simple app.")
        button.pressed.connect(self.close)

        self.setCentralWidget(button)
        self.show()


app = QApplication(sys.argv)
w = MainWindow()
app.exec()

python
from PySide6.QtWidgets import QMainWindow, QApplication, QPushButton

import sys


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Hello World")

        button = QPushButton("My simple app.")
        button.pressed.connect(self.close)

        self.setCentralWidget(button)
        self.show()


app = QApplication(sys.argv)
w = MainWindow()
app.exec()

As you can see, the code is almost identical between PyQt & PySide, so it's not something to be concerned about when you start developing with either: you can always migrate easily if you need to.

PyQt6 Application Screenshot Hello world application built using PyQt6, running on Windows 11

Before the Qt Company (under Nokia) released the officially supported PySide library in 2009, Riverbank Computing had released PyQt in 1998. The main difference between these two libraries is in licensing. The free-to-use version of PyQt is licensed under GNU General Public License (GPL) v3 but PySide is licensed under GNU Lesser General Public License (LGPL). This means that PyQt is limited GPL-licensed applications unless you purchase its commercial version, while PySide may be used in non-GPL applications without any additional fee. However, note that both these libraries are separate from Qt itself which also has a free-to-use, open source version and a paid, commercial version.

For a more information see our article on PyQt vs PySide licensing.

PyQt/PySide with QML

Best for Raspberry Pi, microcontrollers, industrial and consumer electronics

When using PyQt and PySide you actually have two options for building your GUIs. We've already introduced the Qt Widgets API which is well-suited for building desktop applications. But Qt also provides a declarative API in the form of Qt Quick/QML.

Using Qt Quick/QML you have access to the entire Qt framework for building your applications. Your UI consists of two parts: the Python code which handles the business logic and the QML which defines the structure and behavior of the UI itself. You can control the UI from Python, or use embedded Javascript code to handle events and animations.

Qt Quick/QML is ideally suited for building modern touchscreen interfaces for microcontrollers or device interfaces -- for example, building interfaces for microcontrollers like the Raspberry Pi. However you can also use it on desktop to build completely customized application experiences, like those you find in media player applications like Spotify, or to desktop games.

Installation pip install pyqt6 or pip install pyside6

A simple Hello World app in PyQt6 with QML. Save the QML file in the same folder as the Python file, and run as normally.

python
import sys

from PyQt6.QtGui import QGuiApplication
from PyQt6.QtQml import QQmlApplicationEngine


app = QGuiApplication(sys.argv)

engine = QQmlApplicationEngine()
engine.quit.connect(app.quit)
engine.load('main.qml')

sys.exit(app.exec())

qml
import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 600
    height: 500
    title: "HelloApp"

    Text {
        anchors.centerIn: parent
        text: "Hello World"
        font.pixelSize: 24
    }

}

Licensing for Qt Quick/QML applications is the same as for other PyQt/PySide apps.

PyQt6 QML Application Screenshot Hello world application built using PyQt6 & QML, running on Windows 11

Kivy

Best for Python mobile app development

While most other GUI frameworks are bindings to toolkits written in other programming languages, Kivy is perhaps the only framework which is primarily written in pure Python. If you want to create touchscreen-oriented interfaces with a focus on mobile platforms such as Android and iOS, this is the way to go. This does run on desktop platforms (Windows, macOS, Linux) as well but note that your application may not look and behave like a native application. However, there is a pretty large community around this framework and you can easily find resources to help you learn it online.

The look and feel of Kivy is extremely customizable, allowing it to be used as an alternative to libraries like Pygame (for making games with Python). The developers have also released a number of separate libraries for Kivy. Some provide Kivy with better integration and access to certain platform-specific features, or help package your application for distribution on platforms like Android and iOS. Kivy has it's own design language called Kv, which is similar to QML for Qt. It allows you to easily separate the interface design from your application's logic.

There is a 3rd party add-on for Kivy named KivyMD that replaces Kivy's widgets with ones that are compliant with Google's Material Design.

A simple hello world application in Kivy is shown below.

Installation pip install kivy

A simple hello world application in Kivy is shown below.

python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window

Window.size = (300, 200)


class MainWindow(BoxLayout):
    def __init__(self):
        super().__init__()
        self.button = Button(text="Hello, World?")
        self.button.bind(on_press=self.handle_button_clicked)

        self.add_widget(button)

    def handle_button_clicked(self, event):
        self.button.text = "Hello, World!"


class MyApp(App):
    def build(self):
        self.title = "Hello, World!"
        return MainWindow()


app = MyApp()
app.run()

Kivy Application Screenshot Hello world application built using Kivy, running on Windows 11

An equivalent application built using the Kv declarative language is shown below.

python
import kivy
kivy.require('1.0.5')

from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty


class Controller(FloatLayout):
    '''Create a controller that receives a custom widget from the kv lang file.

    Add an action to be called from the kv lang file.
    '''
    def button_pressed(self):
        self.button_wid.text = 'Hello, World!'


class ControllerApp(App):

    def build(self):
        return Controller()


if __name__ == '__main__':
    ControllerApp().run()

python
#:kivy 1.0

:
    button_wid: custom_button

    BoxLayout:
        orientation: 'vertical'
        padding: 20

        Button:
            id: custom_button
            text: 'Hello, World?'
            on_press: root.button_pressed()

The name of the Kv file must match the name of the class from the main application -- here Controller and controller.kv.

Kivy Kv Application Screenshot Hello world application built using Kivy + Kv, running on Windows 11

In February 2011, Kivy was released as the spiritual successor to a similar framework called PyMT. While they shared similar goals and was also led by the current core developers of Kivy, where Kivy differs is in its underlying design and a professional organization which actively develops and maintains it. Kivy is licensed under the MIT license, which is a 'permissive' license that allows you to use it freely in both open source and proprietary applications. As such, you are even allowed to make proprietary modifications to the framework itself.

PySimpleGUI

Best for quickly building UIs for simple tools, very portable

PySimpleGUI aims to simplify GUI application development for Python. It doesn't reinvent the wheel but provides a wrapper around other existing frameworks such as Tkinter, Qt (PySide 2), WxPython and Remi. By doing so, it not only lowers the barrier to creating a GUI but also allows you to easily migrate from one GUI framework to another by simply changing the import statement. While there is a separate port of PySimpleGUI for each of these frameworks, the Tkinter version is considered the most feature complete with the Qt version coming in at second. At the time of writing, the other ports are still more or less a work-in-progress.

There is a fair amount of good resources to help you learn to use PySimpleGUI, including an official Cookbook and a Udemy course offered by the developers themselves. According to their project website, PySimpleGUI was initially made (and later released in 2018) because the lead developer wanted a 'simplified' GUI framework to use in his upcoming project and wasn't able to find any that met his needs.

Installation pip install pysimplegui

python
import PySimpleGUI as sg


layout = [
    [sg.Button("My simple app.")]
]

window = sg.Window("Hello World", layout)

while True:
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED or event == "My simple app.":
        break

window.close()

PySimpleGUI Application Screenshot Hello world application built using PySimpleGUI, running on Windows 11

PySimpleGUI is licensed under the same LGPL v3 license as PySide, which allows its use in proprietary applications but modifications to the framework itself must be released as open source.

WxPython

Best for simple portable desktop applications

WxPython is a wrapper for the popular, cross-platform GUI toolkit called WxWidgets. It is implemented as a set of Python extension modules that wrap the GUI components of the popular wxWidgets cross platform library, which is written in C++.

WxPython uses native widgets on most platforms, ensure that your application looks and feels at home. However, WxPython is known to have certain platform-specific quirks and it also doesn't provide the same level of abstraction between platforms as Qt for example. This may affect how easy it is to maintain cross-platform compatibility for your application.

WxPython is under active development and is also currently being reimplemented from scratch under the name 'WxPython Phoenix'. The team behind WxWidgets is also responsible for WxPython, which was initially released in 1998.

Installation pip install wxpython

python
import wx


class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200, -1))

        self.button = wx.Button(self, label="My simple app.")
        self.Bind(
            wx.EVT_BUTTON, self.handle_button_click, self.button
        )

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.button)

        self.SetSizer(self.sizer)
        self.SetAutoLayout(True)
        self.Show()

    def handle_button_click(self, event):
        self.Close()


app = wx.App(False)
w = MainWindow(None, "Hello World")
app.MainLoop()

WxPython Application Screenshot Hello world application built using WxPython, running on Windows 11

Both WxWidgets and WxPython are licensed under a WxWindows Library License, which is a 'free software' license similar to LGPL (with a special exception). It allows both proprietary and open source applications to use and modify WxPython.

PyGObject (GTK+)

Best for developing applications for GNOME desktop

If you intend to create an application that integrates well with GNOME and other GTK-based desktop environments for Linux, PyGObject is the right choice. PyGObject itself is a language-binding to the GTK+ widget toolkit. It allows you to create modern, adaptive user interfaces that conform to GNOME's Human Interface Guidelines (HIG).

It also enables the development of 'convergent' applications that can run on both Linux desktop and mobile platforms. There are a few first-party and community-made, third-party tools available for it as well. This includes the likes of GNOME Builder and Glade, which is yet another WYSIWYG editor for building graphical interfaces quickly and easily.

Unfortunately, there aren't a whole lot of online resources to help you learn PyGObject application development, apart from this one rather well-documented tutorial. While cross-platform support does exist (e.g. Inkscape, GIMP), the resulting applications won't feel completely native on other desktops. Setting up a development environment for this, especially on Windows and macOS, also requires more steps than for most other frameworks in this article, which just need a working Python installation.

Installation Ubuntu/Debian sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-4.0, macOS Homebrew brew install pygobject4 gtk+4

python
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk

def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    btn = Gtk.Button(label="Hello, World!")
    btn.connect('clicked', lambda x: win.close())
    win.set_child(btn)
    win.present()

app = Gtk.Application(application_id='org.gtk.Example')
app.connect('activate', on_activate)
app.run(None)

PyGObject Application Screenshot Hello world application built using PyGObject, running on Ubuntu Linux 21.10

PyGObject is developed and maintained under the GNOME Foundation, who is also responsible for the GNOME desktop environment. PyGObject replaces several separate Python modules, including PyGTK, GIO and python-gnome, which were previously required to create a full GNOME/GTK application. Its initial release was in 2006 and it is licensed under an older version of LGPL (v2.1). While there are some differences with the current version of LGPL (v3), the license still allows its use in proprietary applications but requires any modification to the library itself to be released as open source.

Remi

Best for web based UIs for Python applications

Remi, which stands for REMote Interface, is the ideal solution for applications that are intended to be run on servers and other headless setups. (For example, on a Raspberry Pi.) Unlike most other GUI frameworks/libraries, Remi is rendered completely in the browser using a built-in web server. Hence, it is completely platform-independent and runs equally well on all platforms.

That also makes the application's interface accessible to any computer or device with a web browser that is connected to the same network. Although access can be restricted with a username and password, it doesn't implement any security strategies by default. Note that Remi is meant to be used as a desktop GUI framework and not for serving up web pages. If more than one user connects to the application at the same time, they will see and interact with the exact same things as if a single user was using it.

Remi requires no prior knowledge of HTML or other similar web technologies. You only need to have a working understanding of Python to use it, which is then automatically translated to HTML. It also comes included with a drag n drop GUI editor that is akin to Qt Designer for PyQt and PySide.

python
import remi.gui as gui
from remi import start, App

class MyApp(App):

    def main(self):
        container = gui.VBox(width=120, height=100)

        # Create a button, with the label "Hello, World!"
        self.bt = gui.Button('Hello, World?')
        self.bt.onclick.do(self.on_button_pressed)

        # Add the button to the container, and return it.
        container.append(self.bt)
        return container

    def on_button_pressed(self, widget):
        self.bt.set_text('Hello, World!')

start(MyApp)

Remi is licensed under the Apache License v2.0, which is another 'permissive' license similar to the MIT License. The license allows using it in both open source and proprietary applications, while also allowing proprietary modifications to be made to the framework itself. Its main conditions revolve around the preservation of copyright and license notices.

Remi Application Screenshot Hello world application built using Remi, running on Chrome on Windows 11

Conclusion

If you're looking to build GUI applications with Python, there is probably a GUI framework/library listed here that fits the bill for your project. Try and weigh up the capabilities & licensing of the different libraries with the scale of your project, both now and in the future.

Don't be afraid to experiment a bit with different libraries, to see which feel the best fit. While the APIs of GUI libraries are very different, they share many underlying concepts in common and things you learn in one library will often apply in another.

You are only limited by your own imagination. So go out there and make something!

For more, see the complete PySide2 tutorial.

Cutelyst v3.5 relicensed as BSD-3-Clause

Cutelyst the Qt Web framework just got a new license, the more permissive BSD-3-Clause. Back in 2013 when I started the project the LGPL was a perfectly fine license as software on servers can be closed as long they are not AGPL, thus it was permissive enough for the web and REST backends use-cases I had in mind.

Fast-forward almost 10 years and I have used for a few of projects where it was embedded into another application, and I realized that there might be users with commercial Qt license that would like to use it but can't due the current license.

Hesitate no more! It's amazing how much nicer it is to implement client-server applications using HTTP/REST APIs all with Qt/C++, and when real time is needed WebSockets is also there to the rescue.

Since Ubuntu 22.04 has Qt 5.15 and 6.2 releases, for the next releases 5.15.2 will be the new minimum as I want to increase the QStringView usage eventually doing a major version update.

*UPDATE: This release includes a QtWidgets example application showing how to use Cutelyst::Server embedded into a GUI application.

https://github.com/cutelyst/cutelyst/releases/tag/v3.5.0

How to integrate C++ and Qml? Registering Enums

We continue our series of blog posts about integrating C++ and Qml. Last time we covered registering C++ types as singletons in Qml. Today we will proceed with another frequently used technique in Qt software development ― utilizing C++ enums in Qml code. In this article we continue using the most recent method of integrating C++ code and Qml ― CMake command qt_add_qml_module().

Why do I need to pass sys.argv or [] when creating an instance of QApplication?other missing modules

The QApplication object is the core of every Qt Widgets application. Every application needs one and only one QApplication object to function. This object starts and holds the main event loop of your application which governs all user interaction with the GUI.

When developing applications with PyQt or PySide you will have created an instance of QApplication like in the example below, passing in sys.argv or an empty list [].

python
import sys
from PySide6.QtWidgets import QApplication

app = QApplication(sys.argv)
# or: app = QApplication([])

python
import sys
from PyQt6.QtWidgets import QApplication

app = QApplication(sys.argv)
# or: app = QApplication([])

While this works, you may have asked yourself: what is the meaning of sys.argv or the empty list [] and why do you need to pass it to QApplication?

What is sys.argv?

When your application starts, sys.argv contains the arguments used to launch your application. If you start a Python application from the command line, sys.argv will contain the name of your Python script file as the first entry.

The name argv is an abbreviation of argument vector. This name originates from the C programming language, where "vector" is the name used for a dynamic array or list.

For example, see the example command line below:

bash
python argtest.py

When executing this script sys.argv will contain the list ['argtest.py']. Anything further you add to the end of the command above will be appended to sys.argv.

To see this in action create the following simple Python script and save it under the name argtest.py.

python
import sys
print("Arguments:", sys.argv)

Now, run your argtest.py script from the command line and experiment with passing in your own arguments. For example, the following command line:

bash
python argtest.py --info

...will output...

bash
Arguments: ['argtest.py', '--info']

As you can see, the --info command-line argument is retrieved from sys.argv, beside the filename of the Python script.

Command-line arguments are split on spaces, so anything separated with a space will be treated as a new argument. To pass arguments that include spaces, you need to wrap those in quotes.

When we pass sys.argv to QApplication we are passing the command-line arguments to Qt. This allows us to pass any configuration settings to Qt at the startup of an application.

What command-line arguments are available?

Qt provides some built-in command-line arguments which are also available in PyQt and PySide.

Qt-specific command-line arguments

  • --platform platformName[:options] Specifies the Qt Platform Abstraction (QPA) plugin. This overrides the QT_QPA_PLATFORM environment variable.

This is commonly used when developing applications on the Raspberry Pi to redirect Qt output to a linux framebuffer device (e.g. a custom screen) without using XWindows. For example, -platform linuxfb:fb=/dev/fb1

  • --platformpluginpath path Specifies the path to platform plugins. This overrides the QT_QPA_PLATFORM_PLUGIN_PATH environment variable.

  • --platformtheme theme Specifies the platform theme. This overrides the QT_QPA_PLATFORMTHEME environment variable.

  • --plugin plugin Specifies additional plugins to load. The plugin value may be passed multiple times. This is concatenated with the plugins in the QT_QPA_GENERIC_PLUGINS environment variable.

  • --qmljsdebugger value Activates the QML/JavaScript debugger with a specified port passed as value. The value must be of format port:1234[,block], where block is optional and will make the application wait until a debugger connects to it.

  • --qwindowgeometry geometry Specifies a geometry for the main window using the X11 syntax which should be passed like --qwindowgeometry 100x100+50+50.

  • --qwindowicon icon Sets the default icon of a window.

  • --qwindowtitle title Sets a title of the first window.

  • --reverse Sets the application's layout direction to Qt.RightToLeft. This option is intended to aid debugging and should not be used in production. The default value is automatically detected from the system's locale.

  • --session session Restores the application from an earlier session.

General command-line arguments

  • -h or --help or -? Displays help on all the general command-line arguments, including this one. Note that the -? argument is only available on Windows.

  • --help-all Displays what --help does plus all the Qt-specific command-line arguments.

  • -v or --version Displays the version of an application.

Do I need to pass sys.argv?

No. While passing sys.argv allows you to pass command-line configuration through to Qt at the startup of your application, if you don't need or want to prevent configuration of Qt from the command line, you can instead either pass an empty list [] (using PyQt6, PyQt5, PySide2) or nothing at all (using PySide6).

python
# PyQt6

import sys
from PyQt6.QtWidgets import QApplication

app = QApplication([])

python
# PySide6

import sys
from PySide6.QtWidgets import QApplication

app = QApplication()

IMPORTANT: If you do not pass sys.argv, you are not forwarding command-line arguments to Qt. Therefore, you can not customize Qt's behavior from the command line.

Conclusion

Passing sys.argv to QApplication at startup allows you to customize the behavior of Qt from the command-line. If you don't want to pass command-line arguments to Qt you can skip passing sys.argv and instead pass nothing (PySide6) or [] (other PyQt or PySide versions).

Be sure to double check if you need any of Qt's command-line configuration — for example, you're developing for Raspberry Pi — before disabling this behavior.

For more, see the complete PyQt5 tutorial.

6 Steps for Legacy Software Migrations

Porting legacy code from Motif, MFC, Photon, or a previous Qt version to a more recent Qt version can be a big challenge. There are a number of pitfalls in a large porting effort that can significantly increase time, cost, and complexity, leading to risk of project derailment. You may have languages, frameworks, and windowing systems that are no longer supported or that leave you unable to find knowledgeable talent. On top of that, legacy UIs tend to look very dated compared to today’s fluid animations, context-sensitive controls, and responsive interactions, requiring more than just a simple port to bring them up-to-date. All of this may be so overwhelming that you aren’t sure where to even start.

Let’s say you’ve already made the decision to do a legacy software migration. So, what’s next? This blog will go over the most important steps in a legacy software migration, to help you execute your own.

Step One: Make It Build

The first step of a migration is to make the source code build on your system, to avoid working blindly when migrating the code base step-by-step afterwards. This might include commenting out source code temporarily, strip non-essential third-party dependencies or activating compatibility functions in the framework.

Do whatever it takes to make your application build. Stub out the bits that do not build, temporarily remove modules from your make files if they are too large to just stub out, use the preprocessor to remove blocks of lines from the build – just keep commenting
away until it builds.

The secret is to do this in a controlled, reproducible, and reversible way because you have to know exactly which bits you have temporarily removed so they can go back in again after they have been properly migrated. You might not need to migrate all of that stubbed out code; most codebases on long-evolved projects contain a fair amount of dead code, and a migration is the perfect opportunity to uncover and remove it.

To make sure you’re properly tracking migration-related comments, use a very distinct label, not just TODO. Although it may be a bit extreme, something like I_AM_STUBBING_THIS_OUT_BUT_IT_NEEDS_TO_GO_BACK_IN_LATER is a far better choice. Why? Chances are that your code is already littered with TODOs and you need to be able to clearly distinguish migration stubbing in the source. Don’t worry about making your code look ugly; these will all be removed once you are done.

Step Two: Start with the Fundamental Features

After you’ve managed to make things build, start migrating the key features. Establish a hierarchy in your code that identifies the key features of your application that are fundamental to everything else and work towards completing those pieces.

For a Motif migration, we would start by porting the core. It’s not very helpful to, for instance, work on a ‘Preferences’ dialog that lets the user configure how the drawing is displayed because you can’t create a drawing yet. It makes more sense to get the main window to draw content than to start with a ‘Preferences’ dialogue.

For an MFC migration, we would start by porting the dialogs, any reusable widgets, and finish with the main window. This is because the main window can keep using MFC while the dialogs use Qt, temporarily.

For the migration of an older version of Qt, the port is more horizontal. For instance, we would start by porting all usages of QPointer list, then port all usages of QCanvas and so on, and so on.

Step Three: Testing

To test the migrated code, developers run unit tests, if they’re ready, and do basic interactive testing. In addition, we have a quality team that can do more systematic testing, but this requires the customer’s giving us either a test plan or documentation that will help us create a test plan ourselves, such as a user manual. We don’t know the application as well as the customer does, of course, which is why it’s important that they provide us with this type of information. If the customer already has automated tests, for instance via Squish, that’s even better.

Once you’re confident that your test plan is complete and you can perform all tests with the expected outcome, then congratulations! You’ve completed your migration!

Step Four: Automated Tools

The parts of the migration that can be automated can range from simple search/replace to very complex parsing and replacement operations. We have developed internal scripts and tools for this. For example, in a migration from Motif to Qt, code like the following would likely occur rather often:

XmToggleButtonGadgetSetState(_onoff, sc && sc->isEnabled(), false);

This, with the right set of tools, can be automatically migrated to:

ui->_onoff->setChecked(sc && sc->isEnabled());

It’s not desirable for an engineer to type in all the input parameters each and every time; it’s time consuming and error-prone. However, an editor that’s configured with lots of intelligent macros to automate these types of transformations can be of tremendous help. Once the engineer identifies the situation, one can trigger the code transformation and review the outcome instead of having to manually look up parameter order, and copy and paste the separate bits.

Another example of tooling help is switching versions between the original, unchanged application and the new one under migration. We typically keep the two code trees next to each other, and use KDAB-designed tools to allow an engineer to quickly jump between the two versions of the same file in order to check on what any given piece of code looked like in the old version, open another window with the diffs, and so on. Search tools are also an indispensable part of a migration engineer’s toolbox. As an example, it’s a great help for an engineer to place the cursor over an identifier and hit a key combination to instantly locate its definition or any references throughout the source tree. While most modern IDEs offer these capabilities, many don’t function unless the source builds completely, which makes them useless for migration work. Text-based searches using complex regular expressions can provide many other ways to make pointed analysis, even on poorly-formed source code.

We have also developed actual C++ libraries to help with migrations by providing intermediate layers, for instance, Qt 3 compatibility functions and MFC containers for Qt items.

Step Five: Add New Features, If Any

Try not to add new features in the middle of the migration. We need to be able to compare the initial version with the migrated version. They should behave as much the same as possible. Of course, we’re happy to add the new features after the migration.

We know it is sometimes unavoidable for changes to occur during the migration, as clients sometimes need to make changes to the original version while we are doing the migration. In such cases, we can merge and port the customer’s changes after we have finished porting the original version of the application.

From KDAB’s Experience…

At KDAB, we’ve fine-tuned the migration process over 15 years, successfully migrating software from a wide variety of frameworks, with the majority migrating to Qt. Based on our experience, we know that, regardless of the framework, operating system, or language, all migrations share common steps that ensure success and have common pitfalls that derail the best of efforts. With this awareness, we’ve developed internal tools and know-how to help speed up the process. Feel free to contact our team at info@kdab.com or click the image below to find out more.

About KDAB

If you like this article and want to read similar material, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

 

The post 6 Steps for Legacy Software Migrations appeared first on KDAB.