Qt 5.14.1 Released
I am happy to announce we have released Qt 5.14.1 today. As a patch release, Qt 5.14.1 does not add any new functionality but provides many bug fixes and other improvements.
The Future of Embedded Software
As the world continues its steady march towards ubiquitous computing, almost everything from airplanes to toasters is being powered by embedded software. In fact, technology is so pervasive, we take connected homes, advanced medical equipment, and self-driving cars almost for granted.
However, many of us who work in the industry have some misgivings about what this explosion in embedded software ultimately means. There are some very important issues that need to be openly discussed and solved before it’s too late.
For instance, why are there no standards to ensure embedded products are designed with quality in mind? A washing machine breaking down due to poorly designed code is one thing, but what about a car? In an industry with no professional certification, who’s responsible for software-related tragedies? It’s easy to think that companies are sparing no expense to build and maintain critical software to the utmost degree of excellence – when we all know that the opposite may be closer to the truth.
And if concern over poorly designed software running our banks, power plants, and other parts of our infrastructure doesn’t keep us up at night, what about the fact that when much of this software was built, nobody was thinking about security? Moreover, why is it most new developers are writing code with a focus on features rather than security? This is a problem that threatens to get bigger the more sophisticated our embedded systems become.
Another issue that needs addressing is the kind of data that consumers of embedded products are sharing, sometimes unknowingly. Unfortunately, much of the public thinks that this is only a concern for credit card companies and cheating spouses. As a result, a couple of huge players are well on their way to owning everyone’s data with no controls or oversight.
These and other big concerns are shared by many of us in the embedded software industry. Who’s going to solve them – industry bodies, concerned citizens, our governments? Download a new report on the Future of Embedded Software. The answer may surprise you.
If you like this blog and want to read similar articles, 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 Embedded Software appeared first on KDAB.
Qt Online Installer 3.2.1 Released
We are happy to announce that Qt Online Installer, based on the Installer Framework 3.2.0, has been released. The biggest change is the installation flow, where Open Source Qt users have to explicitly accept open source usage obligations. We changed the flow to help our customers with the commercial license compliancy. Our customers have been concerned about unintentional Open Source Qt installations in software projects, using Commercial Qt.
QML CachingLoader: Caching loaded pages
TL;DR: When switching back and forth between pages in a QML UI, caching the contents speeds up the loading time of the pages. When writing QML, using a Loader can come in handy: Certain UI elements are loaded in a deferred way, e.g. not at app startup, but when the user clicks a button. When alternating between source elements of a Loader, the old component will always be deleted, as the documentation states: "Setting source to a new URL will also cause the item created by the previous URL to be unloaded." This might not always be what the user wants, so we have written a CachingLoader component, which (you guessed it) caches all components that have been loaded before: https://github.com/edelhirsch/cachingloader For benchmarking the code the above repository loads 2 pages with big images to simulate non-trivial loading time of sub-pages. The test shows that for the first time when a page is loaded, all three ways of deferred loading (Loader with "source" property, Loader with "sourceComponent" property, CachingLoader) behave the same. However, when a previously loaded page is loaded again, the Loader object has to re-read it from disk. The CachingLoader has not unloaded it, but just restores it from the cache for immediate displaying without reading anything from disk: In this example there is no real difference when loading files via the "source" or "sourceComponent" attribute, the slight differences seem to be only variation between measurements. Memory usage is a bit harder to measure, because QML does not seem to release the deleted pages right away, but waits for the garbage collector to kick in. However, in general the CachingLoader is trading loading time vs. memory usage, which means when using the CachingLoader the memory usage will be higher. A normal Loader object can release the memory of previously loaded pages, while the CachingLoader keeps all pages in its cache. The next steps for the CachingLoader would be to introduce a "property bool isCacheable" to have more control about whether pages should be cached or not. Small caveat: When the CachingLoader caches one of its pages, it sets its "enabled" attribute to false, which means it won't receive no more mouse and keyboard events (when loading it from the cache the attribute is of course set to true again). However, care must be taken for other activity coming from e.g. Connections attributes; those should probably made active only when the root page is active.
The Future of Embedded Software
There are many big challenges that face software development today, such as developing for cybersecurity, creating a code of professional ethics, and maintaining data privacy. In this downloadable magazine, we hear from pundits with honest insights into these deep questions about the direction the industry is heading.
The post The Future of Embedded Software appeared first on KDAB.
KDAB Challenge Solutions
Task 1
Proxy types can be tricky. If we got a QChar (or a reference to a QChar) by accessing a character in a QString with the operator[] as most people would expect to, the automatic type deduction requested by auto current = hello[i] would deduce that current is of type QChar.
But QString::operator[] does not return a QChar. It returns a QCharRef. Even if we think of it as a reference to a QChar, the compiler does not, and the automatic type deduction can not remove the reference part like it would if the return type was a proper reference (QChar&).
This means that current will be a value of type QCharRef. When we modify it, it will modify the original string (contrary to what most people expect because of C++’s value semantics).
One of the solutions here is not to use automatic type deduction and explicitly specify the type of current to be QChar.
QChar current = hello[i];
Another thing that could help is to declare the hello string to be const. It is a good practise to use const by default when declaring variables.
The second issue in the first task was that the original string ends with an exclamation mark, while the string in the Q_ASSERT does not.
Task 2
The problem in the second task is similar to the previous one. When we see strings being concatenated, we assume that the result is also a string.
String concatenation is slow (you can check out this post for more info) and Qt allows us to activate delayed (lazy) concatenation by defining QT_USE_QSTRINGBUILDER. Instead of operator+ returning a string, it will return a class called QStringBuilder which will keep references to all strings we want to concatenate and perform the concatenation only when we convert it to a QString.
This means that when we use the automatic type deduction – auto message = ... – we get a message variable that is not a string, but rather an object that keeps references to all the strings we want to concatenate. When we try to print it out with qDebug, it will concatenate all the strings and print out the result.
The problem is that one of the references in our example will be a dangling reference – reference to a temporary string returned by the tr function that has been destroyed before the actual concatenation is performed. So, we get undefined behavior (most likely a crash in this case).
This is easily fixed by explicitly specifying the type of message to be a QString. This will perform the concatenation before the temporary string returned by the tr function is destroyed.
Task 3
The final task is quite different to the previous ones. It shows a function implemented with two for loops nested into each other. The time complexity of the function is O(m*n) where m is the length of xs and n is the length of ys. The memory complexity is O(1).
If we analyze the function, we can deduce that it counts all the items in xs that are smaller than or equal to the smallest value in ys. While the provided example uses sorted vectors, it is obvious that this function also works for unsorted vectors.
One approach (a frequently submitted one) to solving this using the algorithms found in the standard library is to sort both collections and then use the lower_bound to find the first element in (now sorted) xs that is not smaller than the smallest element in ys (ys[0] after sorting). We can then use std::distance to get the count how many elements we have between xs.cbegin() and the item we just found.
The time complexity of this solution is O(n log n + m log m) which is better than the original implementation, but the memory complexity grew to O(m + n) because we need to copy the original vectors in order to sort them, which is significantly worse.
If we go a bit deeper, we can see that we are using just ys[0] so we don’t really need to have the whole vector sorted. We just need the smallest value in ys. We can find this in linear time with the std::min_element algorithm.
With this, we would end up with O(m log m + n) time complexity and O(m) memory complexity, as we are still sorting the xs. Better, but not good enough.
Now the question is whether we really need to sort the xs?
If we know the minimum of ys we need to compare xs against, it is much cheaper just to go through all the unsorted xs one by one and check which ones are smaller than to sort the xs first. This can easily be done with std::count_if:
int counting(const std::vector<int>& xs, const std::vector<int>& ys)
{
if (ys.empty()) return xs.size();
const int min_y = *std::min_element(ys.begin(), ys.end());
return std::count_if(xs.begin(), xs.end(), [=] (int x) {
return x <= min_y;
});
}
The time complexity of this solution is O(m + n) and the memory complexity is O(1) which is the best we can do for this problem.
The post KDAB Challenge Solutions appeared first on KDAB.
gbgcpp – Ribbons using Qt
I’ve been involved in the gbgcpp group, a part of the larger Sweden C++ community, for a couple of years. It is fun to see that there is a lot of C++ developers out there, once you start looking for them.
In the next meetup, this Wednesday, there will be both C++ and Qt. The topic is to implement Ribbons in Qt, based on a seminar by Dag Brück. If you happen to be in the vicinity of Gothenburg, I recommend you to go there!
I’d also like reach out and thank Sylog for hosting the event!
Build GUI layouts with Qt Designer for PyQt5 apps
Extending Qt Bridge
Qt WebAssembly faster builds
Admittedly, building Qt WebAssembly apps takes what seems like forever. Technically, it is the linking part that takes a huge amount of time, as that is where the magic happens.
You may have missed my first blog regarding faster build times for Qt WebAssembly apps:
http://qtandeverything.blogspot.com/2019/06/faster-link-time-for-qt-webassembly.html
Here is how to get set up to use this now integrated feature.
1. You need emscripten with upstream clang, which has support for transpiling directly to wasm, instead of taking the intermediary step of building javascript, then outputting wasm binary with that. Starting with version 1.39.0, upstream clang is the default. You can use "latest" to get 1.39.x or something like "sdk-upstream-1.38.43-64bit" to get an earlier version.
./emsdk install latest
./emsdk activate --embedded latest
source ./emsdk_env.sh
You can then configure and rebuild Qt with -device-option WASM_OBJECT_FILES=1
configure -xplatform wasm-emscripten -developer-build -nomake tests -nomake examples -opensource -confirm-license -verbose -compile-examples -no-warnings-are-errors -release -device-option WASM_OBJECT_FILES=1
Then you can build your Qt app as normal using the qmake from that build, and watch the build time speed up!
*NOTE* Using WASM_OBJECT_FILES with a multi-threaded build is still experimental, as both threads and using wasm object files in emscriptem/wasm and Qt are experimental. I have not seen any real issues regarding the use of both of these at the same time.
You can read more about Qt for WebAssembly, mobile and embedded development in the book Hands-On Mobile and Embedded Development with Qt 5
About my Qt times, and a Qt for Python voice assistant
About my Qt times, and a Qt for Python voice assistant
I spent a short time @Qt, but a fruitful one. I was lucky to work with the great Qt for Python team that made me feel very welcomed. I was also lucky to have had a great mentor, Cristián Maureira-Fredes, that was super supportive and cool to work with.
Aussie firestorms
As some may know, I currently reside in Australia, which is undergoing an unprecedented bush fire season. Total burnt area is about the size of Demark, with no end in sight. Whole forests and towns are being incinerated. Millions of animals, both wild and farm are being killed and injured by the swiftly moving crown fire being whipped up by high dry winds.
There are people that need help, and people that rescue animal need help as well.
https://www.news.com.au/technology/environment/bushfire-relief-how-you-can-help-those-in-need/news-story/a0476ac3538b8c373f281ea6be204421
Some of you may have seen that I authored a book that was published by Packt this last year
Hands on Mobile and Embedded Development with Qt 5
I have decided the donate all my last quarters royalties to the WIRES Emergency Fund for Wildlife. It's not much, but I wanted to help out creatures that cannot help themselves or cannot seek out help. If there is any interest, I will donate the next quarters royalties as well.
LearnPyQt — One year in, and much more to come.
It's been a very good year.
Back in May I was looking through my collection of PyQt tutorials and videos and trying to decide what to do with them. They were pretty popular, but being hosted on multiple sites meant they lacked structure between them and were less useful than they could be. I needed somewhere to put them.
Having looked the options available for hosting tutorials and courses I couldn't find something that fit my requirements. So I committed the #1 programmer mistake of building my own. LearnPyQt.com was born, and it turned out pretty great.
Built on the Django-based Wagtail CMS it has been extended with some custom apps into a fully-fledged learning management system. But it's far from complete. Plans include adding progress tracking, certificates and some lightweight gamification. The goal here is to provide little hooks and challenges, to keep you inspired and experimenting with PyQt (and Python). The site uses a freemium model — detailed tutorials, with an upgrade to buy video courses and books for those that want them.
The availability of free tutorials is key — not everyone wants videos or books and not wanting those things shouldn't stop you learning. Even so, the upgrade is a one-off payment to keep it affordable for as many people as possible, no subscriptions here!
New Tutorials
Once the existing tutorials and videos were up and running I set about creating more. These new tutorials were modelled on the popular multithreading tutorial, taking frequently asked PyQt5 questions and pain points and tackling them in detail together with working examples. This led first to the (often dreaded) ModelView architecture which really isn't that bad and then later to bitmap graphics which unlocks the power of QPainter giving you the ability to create your own custom widgets.
As the list of obvious targets dries up I'll be adding a topic-voting system on site to allow students to request and vote for their particular topics of interest, to keep me on topic with what people actually want.
New Videos
The video tutorials were where it all started, however in the past year these have fallen a little behind. This will be rectified in the coming months, with new video tutorials recorded for the advanced tutorials and updates to the existing videos following shortly after. The issue has been balancing between writing new content and recording new content, but that problem is solved now we have...
New Writers
With the long list of things to tackle I was very happy to be joined this year by a new writer — John Lim. John is a Python developer from Malaysia, who's been developing with PyQt5 for over 2 years and still remembers all the pain points getting started. His first tutorials covered embedding custom widgets from Qt Designer and basic plotting with PyQtGraph both of which were a huge success.
If you're interested in becoming a writer, you can! You get paid, and — assuming you enjoy writing about PyQt — it's a lot of fun.
New Types of Content
In addition to all the new tutorials and videos, we've been experimenting with new types of content on the site. First of all we have been working on a set of example apps and widgets which you can use for inspiration — or just plain use the code from — for your own projects. Everything on the site is open source and free to use.
We've also been experimenting with alternatives short-form tutorials & docs for core Qt widgets and features. The first of these by John covers adding scrollable regions with QScrollArea to your app. We'll have more of these, together with more complete documentation re-written for Python coming soon.
New Year
That's all for this year.
Almost. We're currently running a 50% discount on all courses and books with the code NEWYEAR20. Every purchase gets unlimited access to all future updates and upgrades, so this is a great way to get in ahead of all the good stuff coming down the pipeline.
The same code will give 20% off after New Year. Feel free to share it with the people you love, or wait a few days and share it with people you love slightly less.
Thanks for all your support in 2019, and here's to another great year of building GUI apps with Python!
2019 qutebrowser crowdfunding - reminder
Two months ago, I wrote:
Just like in the 2017/2018 crowdfundings, it'll be possible to get t-shirts and stickers again. I'll also add some new swag to the mix :)
Just a quick reminder: If you want physical rewards with the current perk levels, sign up to the GitHub Sponsors …
Qbs 1.15.0 released
UiWatchDog: a keepalive monitor for the GUI thread
Continuing our blog series about KDToolBox, this time we will discuss UiWatchDog, a keepalive monitor for the GUI thread.
Alive?
A fundamental rule when writing applications in event-driven UI frameworks such as Qt is: do not ever block the GUI thread!
The GUI thread is also usually called the main thread of the application — that is, the thread that runs main(). In Qt the GUI thread is somehow special, because it’s the only thread from which we can perform operations in our UI; these include creating, showing, modifying our controls; updating their contents on the screen; playing visual animations; handling keyboard and mouse events; and so on.
Doing any blocking I/O (such as disk access, networking, IPC), as well as running any computationally intensive operation from within the GUI thread is going to block it for a certain period of time.
If this period is too long, our GUI will become non-responsive, and there’s nothing more frustrating for the user to have an application that feels sluggish or worse doesn’t respond at all.
The definition of “too long” depends on the requirements we have. Of course, a few seconds is completely unacceptable — most operating systems will show that our application has frozen, and potentially will ask the user to terminate it. Below that limit, it really depends: while we could have some leeway for applications using Qt Widgets, a Qt Quick application that has animations all over the place would look terrible if those animations stutter. In other words, “too long” can be as small as a few milliseconds!
Using UiWatchDog
UiWatchDog is, by design, a header only utility to help detect when the GUI thread gets stuck. The usage is straightforward, just create an instance of it in your GUI thread and then call start():
#include "uiwatchdog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
UiWatchdog dog;
dog.start();
~~~
}
If the GUI thread ever hangs for longer than a configurable time period, UiWatchDog will print debug messages to notify you of the fact. Under the hood, UiWatchDog simply spawns a separate thread that will keep checking that the GUI thread is not blocked, by “poking” it at regular intervals.
Note that you are supposed to modify the code in order to customize what should happen in case the GUI thread gets stuck; a self-explanatory comment in the source code will tell you exactly where. On Windows you can also make UiWatchDog request a debugger to be started; on other platforms it’s necessary to have a debugger already running and to install a breakpoint in the right place.
UIWatchDog is part of KDToolBox, KDAB’s collection of miscellaneous useful C++ classes and stuff. You can download it from our GitHub repository here. Have fun!
About KDAB
KDAB is a consulting company offering a wide variety of expert services in Qt, C++ and 3D/OpenGL and providing training courses in:
KDAB believes that it is critical for our business to contribute to the Qt framework and C++ thinking, to keep pushing these technologies forward to ensure they remain competitive.
The post UiWatchDog: a keepalive monitor for the GUI thread appeared first on KDAB.
Welcome the Qt Champions of 2019!
Qt Design Studio 1.4 released
We are happy to announce that the Qt Design Studio 1.4 is now available via the online offline installers. Here’s a quick summary of the new features and functions in 1.4 release. For detailed information about the Qt Design Studio, visit the online documentation page.
Grantlee version 5.2 (Alles hat ein Ende, nur die Wurst hat zwei) now available
The Grantlee community is pleased to announce the release of Grantlee version 5.2.0.
For the benefit of the uninitiated, Grantlee is a set of Qt based libraries including an advanced string template system in the style of the Django template system.
{# This is a simple template #}
{% for item in list %}
{% if item.quantity == 0 %}
We're out of {{ item.name }}!
{% endif %}
{% endfor %}
Included in this release contains a major update to the script bindings used in Grantlee to provide Javascript implementations of custom features. Allan Jensen provided a port from the old QtScript bindings to new bindings based on the QtQml engine. This is a significant future-proofing of the library. Another feature which keeps pace with Qt is the ability to introspect classes decorated with Q_GADGET provided by Volker Krause. Various cleanups and bug fixes make up the rest of the release. I made some effort to modernize it as this is the last release I intend to make of Grantlee.
This release comes over 3 and a half years after the previous release, because I have difficulty coming up with new codenames for releases. Just joking of course, but I haven’t been making releases as frequently as I should have, and it is having an impact on the users of Grantlee, largely in KDE applications. To remedy that, I am submitting Grantlee for inclusion in KDE Frameworks. This will mean releases will happen monthly and in an automated fashion. There is some infrastructure to complete in order to complete that transition, so hopefully it will be done early in the new year.
Building Qt Creator plugins with GitHub Actions
In order to build a Qt Creator plugin you need:
- A C++ compiler
- The Qt SDK
- The Qt Creator SDK
Not many plugin developers know that Qt Creator is shipping an SDK. You don't need to compile Qt Creator in order to develop a Qt Creator plugin. Also having access to all three platforms (Windows, Linux, macOS) is not a common thing for most C++ developers.
GitHub Actions
GitHub Actions is a CI/CD infrastructure provided by GitHub which would give access to all three platforms!
GitHub is also hosting a few Qt Creator plugin repositories, so I decided to try to build the Doxygen plugin (my fork with the GitHub Actions script).
GitHub Actions currently offers the following virtual machines (runners):
How to create a Qt Creator plugin in C++, a working example explained
This article will show you all you need to know to create a Qt Creator plugin in C++.
Qt Creator is the official IDE of Qt and one of the most used by C++ developers. Creating a plugin for Qt Creator is the best way to extend its functionalities and it’s pretty easy to do as you’re going to learn here.
Before we start, you need to know that everything you will find here is based and tested on Qt 5.14 and Qt Creator 4.11, which are the latest versions at the time of writing. Things might change a bit in the future, but hopefully key concepts will stay the same.
Some theory
Before moving to something practical, it’s good to understand few concepts behind plugin design and implementation.
Plugin Structure
From a software design point of view, a Qt Creator plugin is extremely simple. In the simplest case, the only class you really need is one that implements the ExtensionSystem::IPlugin interface.

More realistically, you probably need to handle user settings as well, hence you might also need to implement the following classes:
- Something that stores your user settings during execution (like the class Settings).
- An implementation the Core::IOptionsPage interface for every option page you want in the Qt Creator options dialog (Tools > Options).
- A class extending a QWidget to populate the content of an option page.
Don’t worry if things seem a bit abstract now, they will become more clear after going trough the code later.
Plugin Lifecycle
Qt Creator plugins have a well defined lifecycle for both startup and shutdown and it’s important you know how things work before creating one.
When the application starts, all plugins are put in a loading queue according to their dependencies (i.e.: what other plugins they depend on).
After that, the first part of the initialization process can begin and for each plugin:
- Plugin() constructor is called following queue order
- initialize() is called following queue order – everything that requires dependencies can be done here
- extensionsInitialized() is called in reverse queue order – use it to access initialized dependencies
- Core::ICore sends the signal coreAboutToOpen()
Then the Qt Creator UI is shown on screen and the second part of the inizialization process begins:
- Core::ICore sends the signal coreOpened()
- delayedInitialize() is called in reverse queue order and with some delay between each call – this is for non critical initialization to minimize loading time of Qt Creator
- PluginManager sends the initializationDone() signal
At this stage every plugin should be initialized and fully operational.
A similar process happens when the application is about to close:
- Core::ICore sends the coreAboutToClose() signal
- aboutToShutdown() is called following queue order and what happens next depends on the value returned:
- Return SynchronousShutdown to notify termination
- Return AsynchronousShutdown to make Qt Creator wait until the plugin sends the signal asynchronousShutdownFinished()
- ~Plugin() destructor is called in reverse queue order
An example Qt Creator plugin: QtC Timer
The plugin we’re going to create here is pretty simple. It shows a message to suggest the user to take a break after using Qt Creator for a certain amount of time.

To make things a bit more interesting, the plugin also has a dedicated options page in the Options dialog accessible from the Tools menu of Qt Creator. The only option available is the time between 2 messages.

Keep in mind that you don’t have to use the Options dialog for your settings. You could create a sub-menu under the Tools menu or you could handle everything in a context menu that appears only when needed. There’s no right way to do this, it’s entirely up to you and your project.
I decided to keep this plugin as simple as possible to focus on the key concepts, but it’s not hard to extend it with more complex features. For example:
- Better time handling (consider inactivity, when the window is minimized, etc..)
- Different messages at different times (intervals or absolute)
- Allow to accept/cancel notification
- Usage tracking (session length, session times, user response, etc…)
- Play sounds when showing a message
- More options to handle all the new features
As you can see, even something this simple can be extended quite a lot. Your imagination is the limit.
Let’s create a Qt Creator plugin
After seeing the basic concepts and defining what we are going to create, it’s time to write some code!
Setting up
The first step to create a Qt Creator plugin is to download and to install the latest versions of Qt and Qt Creator from the Qt website. The easiest way to do that is with the online installer. You will also need to install the Qt Script package which is required to build Qt Creator (even if it’s deprecated).
The second step is cloning the repository of Qt Creator to get its source code:
$ git clone http://code.qt.io/qt-creator/qt-creator.git
Then, you want to make sure you are going to build the code of a specific release. To do that just create a branch which points to the most recent tag:
$ cd qt-creator $ git checkout -b 4.11 v4.11.0
Finally, you want to initialize all the submodules of the repository:
$ git submodule init $ git submodule update --recursive
Now you have all you need to build the source code and to do that just launch Qt Creator and open qtcreator.pro, which you can find in the root directory of the repository. After a bit of loading the project will be ready and you can start to build. I recommend to build it in debug and release mode using shadow builds.
Something to remember when building Qt Creator from code is that ideally you need to use the same compiler and the same version of Qt used by its developers to build the official binaries. You can find this information in the About Qt Creator dialog in the Help menu. For example, Qt Creator 4.11 has been built on Linux using gcc 5.3.1 and Qt 5.14. Using similar compilers (like gcc 5.4) is usually fine, but changing things too much (for example Clang) is probably not going to work.
Create a Qt Creator plugin project
After launching Qt Creator, you can create a plugin using the New Project wizard.
To find the right wizard, navigate these menus in the toolbar: File > New File or Project > Projects > Library > Qt Creator Plugin

The first step in the wizard will let you choose a location for your files and a project name.
Then you select a kit to use to build the plugin, make sure to match compiler and Qt version with the ones used to build Qt Creator from code.
Finally, you can enter plugin information that will be shown in the plugin details page in Qt Creator. All fields are pretty self-explanatory.

The only field that is not so obvious is “Deploy into”, which offers 2 options:
-
- Local user settings – for installing your plugin in the system directory. This makes it available to every instance of Qt Creator you launch.
- Qt Creator build – for installing your plugin only for your local build of Qt Creator (the one you use to compile the plugin).
Anyway, don’t worry too much about anything in this wizard page as you will be able to change things later.
Plugin project
After finishing the new project wizard you have a basic default project with the following files in it:
- qtctimer.pro – qmake project file
- qtctimerplugin.h/.cpp – plugin class files
- qtctimer_global.h – header with macros to export symbols of your plugin. In most cases you can delete this and all the related #includes as well
- qtctimerconstants.h – constants used by your plugin. Eventually you can delete this as well
- QtCTimer.json.in – this stores the plugin information (and, for some reason, it’s the only file which is not all lowercase)
The next step after creating a plugin project is setting the following variables in the build environment for both Debug and Release modes:
- QTC_SOURCE – path to the source code of Qt Creator (same for debug and release)
- QTC_BUILD – path to the build directory of Qt Creator (this should be different for debug and release)

Eventually at some point you will also need to add plugin dependencies. You can do that by editing the QTC_PLUGIN_DEPENDS variable in your .pro file. Simply add the name of the plugins you depend on when needed.
The default project creates a simple plugin that adds a menu to the toolbar and shows an info dialog when its entry is clicked. You can build it to test that everything is fine, but after that delete all the code inside the functions in the cpp file to start from scratch.
Plugin source code
It’s time to dive into the code of our plugin, which contains the following classes:
- QtCTimerPlugin – the plugin class that inherits from ExtensionSystem::IPlugin
- Settings – the class handling the options
- OptPageMain – the options page that inherits from Core::IOptionsPage
- OptPageMainWidget – a QWidget that defines the content of the options page
In the following paragraphs I am going to describe in detail the first 3 classes. The QWidget is not described here because it’s simple Qt code to define a basic UI.
For simplicity I have also omitted some less important parts of the code. Don’t worry about them for now, you can read and experiment with the full source code later.
The plugin class – header
First of all, you need a class that handles all the logic of the plugin and acts like mediator to connect the other ones. This class is the one that inherits from ExtensionSystem::IPlugin.
#include <extensionsystem/iplugin.h>
class QtCTimerPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QtCTimer.json")
This class is automatically created by the project wizard and you don’t need to take care of implementation details like adding the right macros. You will only need to implement its pure virtual functions like initialize() and extensionsInitialized(), but also any other virtual member you might need like aboutToShutdown().
public:
bool initialize(const QStringList & arguments, QString * errorString) override;
void extensionsInitialized() override;
ShutdownFlag aboutToShutdown() override;
}
The plugin class – implementation
The first member to implement is initialize(), which does 2 things:
First, it creates the Settings object to store and handle user settings. It also create the option page that will allow the user to change such settings.
bool QtCTimerPlugin::initialize(const QStringList & arguments, QString * errorString)
{
// -- OPTIONS PAGE --
mSettings = new Settings;
mSettings->Load();
mOptionsPage = new OptPageMain(mSettings, this);
connect(mOptionsPage, &OptPageMain::SettingsChanged, this, &QtCTimerPlugin::UpdateTimer);
When the settings change, we execute the slot UpdateTimer, which updates the timer we are about to create.
The second part of this method creates and initializes the timer that controls when to show a message on screen.
// -- TIMING --
mTimer = new QTimer;
UpdateTimer();
connect(mTimer, &QTimer::timeout, this, &QtCTimerPlugin::OnTimeout);
mTimer->start();
return true;
}
Every time the timeout signal is emitted, we execute the slot OnTimeout, which uses a QMessageBox to show a dialog with a message.
As we don’t really need to do anything with extensionsInitialized(), we can leave it empty.
In aboutToShutdown() we disconnect all the signals and stop the timer as we are about to exit.
ExtensionSystem::IPlugin::ShutdownFlag QtCTimerPlugin::aboutToShutdown()
{
mTimer->stop();
mTimer->disconnect();
mOptionsPage->disconnect();
return SynchronousShutdown;
}
All the objects created with new are destroyed in the destructor, but I am not going to show the code here as it’s nothing special or complicated.
The Settings class – header
This class stores the user settings during execution. It also takes care of loading and saving them.
The header file is pretty simple and it can be divided in 3 parts:
- Setters and getters for the data (omitted here for simplicity)
- 2 functions to load and save data
- 2 operators to compare a pair of Settings objects
class Settings
{
public:
// ...DATA getters and setters...
// -- I/O --
void Load();
void Save();
// -- OPERATORS --
bool operator==(const Settings & other) const;
bool operator!=(const Settings & other) const;
};
This is also the only class of this plugin which is not a QObject.
The Settings class – implementation
The Load() member handles only 1 option (mTimeLimit), but it shows all you need to handle any number.
The first thing you need to do when working with Qt Creator settings is to get access to a QSettings object to read/write user settings. You can do that with a single static call:
void Settings::Load()
{
QSettings * s = Core::ICore::settings();
Now you can use the QSettings object to access your options. You do that with the function beginGroup(), which takes as parameter a QString that identifies your group of settings.
Once you are inside your group of settings you can get the value of any option by calling the value() function. This function takes a QString (OPT_TIME_LIMIT) that identifies the specific setting and a default value (DEF_TIME_LIMIT) that is returned when the wanted setting is missing. This function returns a QVariant, so you have to call the right conversion function (toInt() in this case) to get a proper value,
s->beginGroup(GROUP);
mTimeLimit = s->value(OPT_TIME_LIMIT, DEF_TIME_LIMIT).toInt();
s->endGroup();
}
When you are done loading all the settings you can close the group with endGroup().
Saving is specular to loading. The only difference is that this time you call the function setValue() to store each setting. The function takes a QString (OPT_TIME_LIMIT) that identifies the specific setting and a QVariant that contains the data to save. Remember that QVariant has many implicit constructors, so unless you need to save some complex data, you can just rely on that.
void Settings::Save()
{
QSettings * s = Core::ICore::settings();
s->beginGroup(GROUP);
s->setValue(OPT_TIME_LIMIT, mTimeLimit);
s->endGroup();
}
The 2 operators (== and !=) are pretty straightforward as they only compare data members, so I will not discuss them here, but you can check their code later.
Options page – header
For every page you need in the Options dialog of Qt Creator, you need to implement a Core::IOptionsPage, which contains the meta information necessary to populate the dialog.
#include <coreplugin/dialogs/ioptionspage.h>
class OptPageMain : public Core::IOptionsPage
{
Q_OBJECT
public:
OptPageMain(Settings * settings, QObject * parent = nullptr);
Every option page should have access to the Settings object as that’s needed for reading and writing settings. Hence, it’s good practice to pass it to its constructor.
Then it’s necessary to override the following 3 members as they are pure virtual in the interface class.
QWidget * widget() override;
void apply() override;
void finish() override;
Finally, it’s good to have a signal to notify the plugin class when things change.
signals:
void SettingsChanged();
};
Options page – implementation
The class constructor sets all the meta data needed by Qt Creator to handle the page properly.
OptPageMain::OptPageMain(Settings * settings, QObject * parent)
: IOptionsPage(parent)
, mSettings(settings)
{
setId("QtCTimerSettings"); // page ID
setDisplayName("General"); // page label in tabs
setCategory("QtC Timer"); // category ID
setDisplayCategory("QtC Timer"); // category label in options - set once
setCategoryIcon(Utils::Icon(":/imgs/icon_timer.png")); // category icon - set once
}
The setId() and setDisplayName() functions define the ID and the visible name of the page, whereas the setCategory(), setDisplayCategory() and setCategoryIcon() define the ID, visible name and icon of the group of pages used by our plugin. You need to call the last 2 functions only once, and you can do that in the first page you create.
The widget() functions simply creates the widget that defines all the content of the page and returns it.
QWidget * OptPageMain::widget()
{
if(nullptr == mWidget)
mWidget = new OptPageMainWidget(mSettings);
return mWidget;
}
Eventually you could create a widget only once, for example in the constructor, but usually it’s better to create it when needed and to destroy it when the dialog is closed to save memory.
The apply() method is called when the settings are accepted by the user, which is when they push the buttons “Ok” or “Apply” of the options dialog.
void OptPageMain::apply()
{
const Settings newSettings = mWidget->GenerateSettings();
if(newSettings != *mSettings)
{
*mSettings = newSettings;
mSettings->Save();
emit SettingsChanged();
}
}
This member gets a new Settings object from the widget, which eventually replaces the existing one if something has changed.
Things might be more elaborated when you have to handle complex settings and the Settings object gets bigger, but in our case (and in many others) this is enough.
The finish() method is called when the options dialog is closed.
void OptPageMain::finish()
{
delete mWidget;
mWidget = nullptr;
}
It simply deletes the widget to save memory, as discussed before.
Resources and references
Get the source code
The full source code of this plugin is available on GitHub and released under the Unlicense license.
Remember that you will also need the source code of Qt Creator to build this example.
A more advanced plugin: SIGBUILD
In case you wanted to experiment with something more advanced you can check out my plugin SIGBUILD, available on GitHub as well.
SIGBUILD notifies you when your builds terminate and tracks their stats. It offers several types of notifications and it comes with a nice systray icon you can use to monitor your builds without even opening Qt Creator.
Support this blog
If you find this post useful you might consider to sponsor me on GitHub.
With your contribution I will be able to spend more time writing posts about Qt like this one and working on my other open source project like SIGBUILD.
Stay connected
Don’t forget to subscribe to the blog newsletter to get notified of future posts.
You can also get updates following me on Github, LinkedIn and Twitter.
The post How to create a Qt Creator plugin in C++, a working example explained appeared first on Bits of Bytes.
New UI Git plugin for QtCreator: GitQlient
Today I’m really happy to announce that the first version of the Git plugin for QtCreator has been released! In the last post I advanced some of the final work that will be part of the first version of GitQlient. But what I didn’t explain so far is that that refactor, the re-work and addition […]
New UI Git plugin for QtCreator: GitQlient first appeared on My C++ & Qt blog - Cesc M..
Qt World Summit 2019: Roundup
Once again the Qt World Summit is over. basysKom presented on a number of topics – ranging from Qt Quick on low end hardware, Qt and its place in a world that has been heavily influenced by web-technology as well as an introduction to the Qt OPC UA module. Please find the PDFs for the … Continue reading Qt World Summit 2019: Roundup
Release 3.3.0: Update to Qt 5.13.2 and Qt Creator 4.10.2, Jira Tima App Demo
Felgo 3.3.0 adds support for Qt 5.13.2 and Qt Creator 4.10.2, which brings many features and improvements and fixes. On top of that, you get access to a lot of new APIs and theming options on all supported platforms. Check out a new Jira time tracker demo application, that shows how to use several of the new APIs.
Migration Hints (Android Platform)
The new Qt version 5.13.2 requires an increase of the minimum SDK version to 21. Google requires the target SDK version set to 28 for submission to the Play Store. The new versions required in the AndroidManifest.xml file of your projects are:
- android:minSdkVersion=”21“
- android:targetSdkVersion=”28“
If you are interested, you can check out the full Qt changelog of this new version in the official Qt docs.
New Jira Tima Mini Demo App
This new demo shows best practices for UI design with a shared code-base across Android, iOS and desktop. It works with dummy data based on the Jira time tracking software. It uses several of the latest APIs released with Felgo 3.3.0.
It is based on the official Jira Tima mobile app developed by Felgo.
| iOS | Android | Desktop |
|---|---|---|
![]() |
![]() |
![]() |
New Features and APIs with Felgo 3.3.0
Improvements to Desktop Hover effects and Responsiveness
The desktop theme now features hover effects and uses the mouse pointer cursor for all input elements as well as the RippleMouseArea. You also have new styling options for the main navigation on desktop, which are listed in the “New Features” section of this release.

Improved AppTextField with New APIs
AppTextField is now based on Qt Quick Controls 2 and offers several new APIs.

With the new AppTextField::inputMode property, you can use a set of predefined input modes for different types of text fields:
- inputModeDefault: Default text input without any special features.
- inputModeUsername: Displays a clear button by default if the field is not empty and has focus, which can be changed with AppTextField::showClearButton.
- inputModeEmail: Only accepts characters allowed in Emails using the TextField::validator property. Displays a clear button by default if the field is not empty and has focus, which can be changed with AppTextField::showClearButton.
- inputModeUrl: Only accepts characters allowed in URLs using the TextField::validator property. Displays a clear button by default if the field is not empty and has focus, which can be changed with AppTextField::showClearButton.
- inputModePassword: Hides the input using disc characters instead using the TextField::echoMode property. Shows a button to display the password by default, which can be changed using AppTextField::showPasswordVisibleButton. The password can also be displayed using the AppTextField::passwordVisible property.
import QtQuick 2.0
import Felgo 3.0
App {
NavigationStack {
Page {
title: "AppTextField::inputMode"
AppTextField {
width: parent.width
inputMode: inputModeEmail
}
}
}
}
You can find details on other new properties like AppTextField::passwordVisible and AppTextField::showPasswordVisibleButton in the associated documentation.
Note: This also applies to SearchBar which uses an AppTextField internally.
The AppTextField::clickEnabled property is used for text fields without manual input. When the user selects this text field, the AppTextField::clicked signal is fired instead of setting focus to the text field. This makes sense e.g. for date input fields, where you can show a date picker when the field is selected.
import QtQuick 2.0
import Felgo 3.0
App {
NavigationStack {
Page {
title: "AppTextField::clickEnabled"
AppTextField {
id: textField
width: parent.width
placeholderText: "Select date"
clickEnabled: true
onClicked: {
nativeUtils.displayDatePicker()
}
Connections {
target: nativeUtils
onDatePickerFinished: {
if(accepted) textField.text = date
}
}
}
}
}
}
Display Options of Navigation Drawer and Sidebar Option on Desktop
You can use the new property Navigation::drawerInline to display the navigation drawer inline with the content and not as an overlay. With Navigation::drawerFixed you can also disable collapsing and expanding of the drawer, resulting in a fixed navigation sidebar. This is ideal for big tablets or desktops.
Additionally you can display the drawer in a minified sidebar version containing only icons, with Navigation::drawerMinifyEnabled.
You can add your logo to the navigation drawer now, with the Navigation::drawerLogoSource, Navigation::drawerLogoBackgroundColor and Navigation::drawerLogoHeight properties.
An AppDrawer can now be minified using AppDrawer::minifyEnabled. This will cause the drawer to appear as small sidebar with only icons displayed, while the labels are hidden.
This example lets you play around with the new display options:

import QtQuick 2.0
import Felgo 3.0
App {
Navigation {
id: navigation
NavigationItem {
title: "Item1"
icon: IconType.heart
NavigationStack {
Page {
title: "Page1"
Column {
anchors.centerIn: parent
spacing: dp(15)
Row {
AppText {
text: "drawerInline "
}
AppSwitch {
checked: navigation.drawerInline
updateChecked: false
onToggled: navigation.drawerInline = !navigation.drawerInline
}
}
Row {
AppText {
text: "drawerFixed "
}
AppSwitch {
checked: navigation.drawerFixed
updateChecked: false
onToggled: navigation.drawerFixed = !navigation.drawerFixed
}
}
Row {
AppText {
text: "drawerMinifyEnabled "
}
AppSwitch {
checked: navigation.drawerMinifyEnabled
updateChecked: false
onToggled: navigation.drawerMinifyEnabled = !navigation.drawerMinifyEnabled
}
}
}
}
}
}
NavigationItem {
title: "Item2"
icon: IconType.star
NavigationStack {
Page {
title: "Page2"
}
}
}
}
}
Better Theming Support for Dialogs
The Dialog and InputDialog components now have a new material style on Android. They can also be further customized with the new ThemeDialog properties.
You can now also access the title item with Dialog::titleItem alias as well as manually set Dialog::titleDividerVisible.

import QtQuick 2.0
import Felgo 3.0
App {
onInitTheme: {
// You can add custom styles for dialogs now
//Theme.dialog.backgroundColor = "yellow"
dialog.open()
}
NavigationStack {
Page {
title: "Dialog"
}
}
Dialog {
id: dialog
title: "Do you think this is awesome?"
autoSize: true
positiveActionLabel: "Yes"
negativeActionLabel: "No"
onCanceled: title = "Think again!"
onAccepted: close()
// You can use Theme.dialog.defaultContentPadding to align your
// custom content with the rest of the dialog UI.
AppText {
padding: dp(Theme.dialog.defaultContentPadding)
wrapMode: Text.WordWrap
width: parent.width
text: "This is a very long sentence to get some line breaks in this content!"
// Colors and alignment are platform depending for the best appearance
color: Theme.isIos ? Theme.colors.textColor : Theme.colors.secondaryTextColor
horizontalAlignment: Theme.isIos ? Text.AlignHCenter : Text.AlignLeft
}
}
}
New TextFieldRow Component for Basic Input Forms
Use the new TextFieldRow component to construct basic input forms on pages. It displays a label based on AppText together with a text field based on AppTextField.
import QtQuick 2.0
import Felgo 3.0
App {
NavigationStack {
Page {
title: "TextFieldRow"
Column {
id: column
width: parent.width
TextFieldRow {
width: parent.width
label: "Text"
placeHolder: "Add some text"
}
TextFieldRow {
id: dateRow
width: parent.width
label: "Date"
placeHolder: "Select date"
clickEnabled: true
onClicked: {
nativeUtils.displayDatePicker()
}
Connections {
target: nativeUtils
onDatePickerFinished: {
if(accepted) dateRow.value = date
}
}
}
}
}
}
}
Content Padding Theming Property and Helper for Cleaner Layouts
The new Theme::contentPadding property helps you streamline your layouts easier and match your content paddings with the overall app layout.
The Page offers a new Page::contentPaddingAnchorItem item that can be used to add default padding to your page content. You can anchor to it or just use its properties like margins or width for your layouts.

import QtQuick 2.0
import Felgo 3.0
App {
NavigationStack {
Page {
id: page
title: "Page::contentPaddingAnchorItem"
Column {
id: column
spacing: dp(Theme.contentPadding)
anchors.fill: parent.contentPaddingAnchorItem
AppText {
width: parent.width
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
}
// Toggle the padding with this button
AppButton {
text: "Toggle padding"
horizontalMargin: 0
property bool toggle: true
onClicked: {
column.anchors.fill = toggle ? column.parent : column.parent.contentPaddingAnchorItem
toggle = !toggle
}
}
}
}
}
}
More Features, Improvements and Fixes
Felgo 3.3.0 includes many more features, for example:
- Page and ListPage components will now remove focus of any input element if the background is clicked.
- You can now change the app or game’s soft input behavior on Android with the new property NativeUtils::softInputMode.
- The RippleMouseArea now offers and hover effect on desktop, and uses the mouse pointer cursor on hover, with the new properties RippleMouseArea::hoverEffectEnabled and RippleMouseArea::hoverEffectRadius. This is enabled by default on desktop.
- The AppListView now allows you to easily display a SearchBar in the header, with the AppListView::showSearch property. Any search will trigger the AppListView::search signal.
- Same as with the AppListView, you can also display the SearchBar within a ListPage now. Additionally the ListPage will fire the signal ListPage::clickedBackground now when the background is clicked. It will also remove focus from any input element if the background is clicked.
- Show or hide a divider for the SearchBar with SearchBar::showDivider.
- Add new property SwipeOptionsContainer::overshoot and new methods SwipeOptionsContainer::showRightOption() and SwipeOptionsContainer::showLeftOption() to SwipeOptionsContainer.
- New convenience properties SimpleRow::badgeColor and SimpleRow::showDisclosure to customize a SimpleRow easier.
- The new option Theme.colors.statusBarStyleSystem allows you to display a default system themed status bar on Android. With this the system does not show the app in fullscreen mode. This can be useful for some native features. You can use this style like the following:
App { onInitTheme: Theme.colors.statusBarStyle = Theme.colors.statusBarStyleSystem } - The signal Store::storePurchased() now contains additional information about the payment transaction on iOS.
- The Facebook Plugin now uses the newest Facebook SDK v5.3.0 on iOS and Facebook SDK v5.5.0 on Android.
- Added property OneSignal::shareLocationEnabled to the OneSignal Plugin.
- The images returned from NativeUtils::displayImagePicker() and NativeUtils::displayCameraPicker() are now stored in a persistent location. Thus mobile operating systems do not delete them automatically.
Note: For this to work on Android, add the following line to android/res/xml/file_paths.xml:<files-path name="files" path="."/> - The Wikitude Plugin requires an update to your build.gradle file if you use Cloud Builds to distribute a 64-bit Android app. For that, have a look at the Android Integration Steps on how to set the new abiFilters definition.
- Fixes an issue of TexturePackerSpriteSequence that resulted in an endless loop of the first TexturePackerSprite within the sequence.
- Fixes a potential crash when deleting a physics Body with an attached MouseJoint.
- Fixes for FelgoMultiplayer logic involving triggerPreviousTurn() method and playerCount property.
For all relevant changes, features and fixes of recent Felgo updates, please check out the changelog.
How to Update Felgo
Test out these new features by following these steps:
- Open the Felgo SDK Maintenance Tool in your Felgo SDK directory.
- Choose “Update components” and finish the update process to get this release as described in the Felgo Update Guide.

If you haven’t installed Felgo yet, you can do so now with the latest installer from here. Now you can explore all of the new features included in this release!
For a full list of improvements and fixes to Felgo in this update, please check out the change log!
More Posts Like This

Release 3.2.0: Update to Qt 5.12.3 with ECMAScript 7, Subscriptions, Image Picker and Qt Creator 4.8.2

Release 3.1.0: New Felgo Plugins Version, Unified App Configuration and FlickablePage

Android 64-Bit Support with Qt and Felgo Cloud Builds
The post Release 3.3.0: Update to Qt 5.13.2 and Qt Creator 4.10.2, Jira Tima App Demo appeared first on Felgo.
Creating scrollable GUIs with QScrollArea in PyQt5
How to set up TravisCI for Qt apps
When I started GitQlient and GitQlientPlugin one of the first things I wanted was to setup a CI environment. The main reason is, of course, to have a system that checks a clean build of both projects.
The other reason, however, is that I think its a quite nice environment to deploy your build in GitHub. Locally, your system can be messed up with versions and old objects that are not cleared, etc. By doing it in this way, one is allowed to have a clean build in a really controlled environment. In addition, you can run as much versions and they are deploy independently.
How to set up TravisCI for Qt apps first appeared on My C++ & Qt blog - Cesc M..
Using QtWidgets in QML
TL;DR: Yeah, it's somewhat possible. The somewhat official story goes like this: You write your desktop application in QtWidgets, and an embedded UI with QML. QtWidgets offers an extensive set of controls, and QML is good for rapid prototyping and easily embedding fancy stuff like animations, because of its hardware-rendered backends like OpenGL. Porting a QtWidgets app to QML can be a huge task, and sometimes it might not be feasible at all, be it due to time constraints or due to some widgets missing their pendant in the QML world. Thus embedding QtWidgets in QML might be an option, i.e. writing some controls in QML and some in QtWidgets, and maybe gradually rewrite widgets in QML (or leave some widgets as they are). Here is a screenshot of a prototype: ... and here is the corresponding code (LGPLv2): https://github.com/edelhirsch/widgetitem The idea to do that is not really new, however there did not seem to be code publicly available for this. The code is using a QQuickPaintedItem in QML to draw the widget with a QPainter; a caveat of using widgets in QML is that you often need to call update() by hand once the widget has changed. Performance-wise, bigger widgets take several milliseconds to draw, and since the code always updates the whole widgets, it might not be possible to always get a frame rate of 60 frames per second, depending on the use case. For a rather static UI without animations it might still be good enough though. An alternative to a QQuickPaintedItem would have been to just render to widget to an QImage and use it in a custom QQuickItem which renders to a QSGSimpleTextureNode or similar. So far the code is just a prototype; feel free to let us know your suggestions, or just file a merge request!











