Skip to content

KDSingleApplication: a class for single-instance policy applications

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.

What is a 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.

Talk is cheap, show us the code

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

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.

2 thoughts on “KDSingleApplication: a class for single-instance policy applications”

  1. 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

    1. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *