Sign up for the KDAB Newsletter
Stay on top of the latest news, publications, events and more.
Go to Sign-up
Another day, another blog about some of KDAB's utility classes. Now it's the turn of KDSingleApplication, a class that helps implement applications that follow the single-instance policy.
Single-instance policy refers to those applications that want to spawn a unique instance for a given user session. Even when launched multiple times, such applications will not spawn a number of separate instances. Instead, the existing instance will be notified, somehow, and some action will be taken by that instance. Typically, its window will be shown (if hidden) and raised to the foreground.
This mechanism works even when the application is launched indirectly, like from a file manager when opening a file type associated with the application. In this case, the new instance (launched by the file manager) will simply tell the existing instance to open the selected file, and then the new instance will immediately quit.
The problem is: on most operating systems we do normally get a new instance every time we launch an application! Therefore, some logic is needed to honor a single-instance policy. KDSingleApplication implements such logic.
KDSingleApplication is a redesign of QtSingleApplication and other similar code that lives around in a few repositories.
The biggest advantage of KDSingleApplication over the old solutions is that it does not replace QCoreApplication/QGuiApplication/QApplication by inheriting from them. Such an inheritance is, generally speaking, a symptom of bad design. Unless we modify the solution's own code, we cannot control which application class we're using. Moreover, we cannot use the solution and another custom subclass of the application class. This is useful in some scenarios, because there can be only one application object!
KDSingleApplication instead complements your application object. You're simply supposed to create an application object (of whatever kind is necessary) and then create a KDSingleApplication object:
int main(int argc, char **argv)
{
QApplication app(argc, argv);
KDSingleApplication kdsa;
After that, we will need to check whether our instance is the main ("primary") instance, or a "secondary" one. The idea is that primary instances can receive arbitrary messages from the secondary instances and act on them in application-specific ways (open a file, show and raise the application's main window, and so on).
The check looks like this:
if (kdsa.isPrimaryInstance()) {
/* primary: listen to messages */
QObject::connect(&kdsa, &KDSingleApplication::messageReceived,
/* handle messages from the secondary instances */);
} else {
/* secondary: send message to the primary */
kdsa.sendMessage("some message to the primary");
/* quit */
return 0;
}
The example shipped with KDSingleApplication illustrates the handling of messages in more detail.
You can download KDSingleApplication from its GitHub repository: https://github.com/KDAB/KDSingleApplication; it is distributed under the MIT license. Yes, for various practical reasons, KDSingleApplication lives in its own repository. Nonetheless, enjoy!
About KDAB
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications. In addition to being leading experts in Qt, C++ and 3D technologies for over two decades, KDAB provides deep expertise across the stack, including Linux, Rust and modern UI frameworks. With 100+ employees from 20 countries and offices in Sweden, Germany, USA, France and UK, we serve clients around the world.
Stay on top of the latest news, publications, events and more.
Go to Sign-up
Learn Modern C++
Our hands-on Modern C++ training courses are designed to quickly familiarize newcomers with the language. They also update professional C++ developers on the latest changes in the language and standard library introduced in recent C++ editions.
Learn more
2 Comments
25 - Feb - 2021
Guilhem
Nicely done.
Just a small technical question: I use this implemented with a share-memory instead of your combination of a lock-file and a local server. Are there advantages from one solution over the other ?
Thanks
25 - Feb - 2021
Giuseppe D'Angelo
Hi,
Indeed, shared memory is a viable implementation option (want to contribute it to KDSA? :-)). The only (minor?) advantages that come to mind of a local server implementation is 1) the ease of passing arbitrary amounts of data, so it's not tied to a particular SHM size; and 2) not having to manage concurrency / locks / etc. in case of multiple secondaries that activate at the same time.