11.2. Single-Instance Applications

Sometimes it only makes sense to run one instance of an application. Examples include Kicker, the KDE panel, Kwin the KDE window manager, and KPPP, the Internet dial-up tool.

To allow developers to create single-instance applications with minimal effort, KDE offers KUniqueApplication. It is a subclass of KApplication and thus offers all of KApplication's functionality and ensures that only one instance of the application is running. To use KUniqueApplication, you need to modify your usual main() function a bit; see Listing 11.4.


Example 11.4. main.cpp: A main() Function Suitable for Starting a Single-Instance Application

   1 
   2  1: #include "kunique.h"
   3  2:
   4  3: void
   5  4: main (int argc, char *argv[])
   6  5: {
   7  6:   if (KUnique::start(argc, argv, "kunique"))
   8  7:     {
   9  8:       KUnique *kunique = new KUnique (argc, argv, "kunique");
  10  9:       kunique->exec();
  11 10:     }
  12 11: }
  13 

KUniqueapplication accomplishes the feat of starting only one application using DCOP, an interprocess communication system (see Chapter 13, "DCOP—Desktop Communication Protocol" for a discussion). When KUnique::start() is called, KUniqueApplication tries to register itself with DCOP under your application's name (kunique in this case). If that name is already in use, KUnique::start() returns false and your application exits. Otherwise, your application is registered under its name. In either case, a DCOP call is sent off, which calls the virtual method KUnique::newInstance() (see Listing 11.5).


Example 11.5. kunique.cpp: Class Definition for KUnique, a Single-Instance Application

   1 
   2  1: #include <kwin.h>
   3  2:
   4  3: #include "kunique.h"
   5  4: #include "ksimpleapp.h"
   6  5:
   7  6: KUnique::KUnique (int&argc, char** argv,
   8  7:           const QCString&rAppName = 0) :
   9  8:   KUniqueApplication (argc, argv, rAppName)
  10  9: {
  11 10:   ksimpleapp=0;
  12 11: }
  13 12:
  14 13: int
  15 14: KUnique::newInstance (QValueList<QCString> params)
  16 15: {
  17 16:   if (ksimpleapp==0)
  18 17:     {
  19 18:       ksimpleapp = new KSimpleApp;
  20 19:       ksimpleapp->show();
  21 20:     }
  22 21:   else
  23 22:     {
  24 23:       ksimpleapp->slotRepositionText();
  25 24:       KWin::setActiveWindow (ksimpleapp->winId());
  26 25:     }
  27 26: }
  28 

In the method newInstance() (lines 13-26), you either create a new instance of the main application widget (usually a subclass of KTMainWindow; here KSimpleApp is used—a main widget presented in Chapter 2) or, if it already exists, respond to the user's attempt to restart the application. Your application's response to a restart attempt might be the following:

  • To issue a "sorry" message with KMessageBox::sorry(), saying that the application is already running

  • To open the document requested, as a command-line parameter, in addition to or instead of the currently opened document

In any case, the response should indicate to the user that you are aware of the user's attempt to start the application. At a minimum, you should set the currently running window as the active window using the static method KWin::setActiveWindow(). This method is demonstrated on line 24. KUnique interprets a request to start the application again as a request to perform the only action it knows: to reposition the text (see Chapter 2 for an explanation of this action).

The final bit of code needed to compile KUnique, the header file, is given in Listing 11.6.


Example 11.6. kunique.h: Class Declaration for KUnique

   1 
   2  1: #ifndef __KUNIQUE_H__
   3  2: #define __KUNIQUE_H__
   4  3:
   5  4: #include <kuniqueapp.h>
   6  5:
   7  6: class KSimpleApp;
   8  7:
   9  8: class KUnique : public KUniqueApplication
  10  9: {
  11 10:  public:
  12 11:   KUnique (int&argc, char** argv,
  13 12:        const QCString&rAppName = 0);
  14 13:
  15 14:   int newInstance (QValueList<QCString> params);
  16 15:
  17 16:  private:
  18 17:   KSimpleApp *ksimpleapp;
  19 18: };
  20 19:
  21 20: #endif
  22