• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..17-Aug-2021-

LICENSEH A D01-May-20211.2 KiB2519

README.mdH A D01-May-20217.9 KiB266196

config.h.inH A D01-May-202153 32

singleapplication.cppH A D09-Sep-20218.3 KiB271139

singleapplication.hH A D31-Aug-20214.9 KiB15438

singleapplication_p.cppH A D09-Sep-202113.2 KiB472312

singleapplication_p.hH A D25-Sep-20213.1 KiB11266

singlecoreapplication.cppH A D09-Sep-20218.5 KiB271139

singlecoreapplication.hH A D31-Aug-20214.8 KiB15338

singlecoreapplication_p.cppH A D09-Sep-202113.3 KiB472312

singlecoreapplication_p.hH A D09-Sep-20213.2 KiB11266

README.md

1SingleApplication
2=================
3
4This is a replacement of the QtSingleApplication for `Qt5`.
5
6Keeps the Primary Instance of your Application and kills each subsequent
7instances. It can (if enabled) spawn secondary (non-related to the primary)
8instances and can send data to the primary instance from secondary instances.
9
10Usage
11-----
12
13The `SingleApplication` class inherits from whatever `Q[Core|Gui]Application`
14class you specify via the `QAPPLICATION_CLASS` macro (`QCoreApplication` is the
15default). Further usage is similar to the use of the `Q[Core|Gui]Application`
16classes.
17
18The library sets up a `QLocalServer` and a `QSharedMemory` block. The first
19instance of your Application is your Primary Instance. It would check if the
20shared memory block exists and if not it will start a `QLocalServer` and listen
21for connections. Each subsequent instance of your application would check if the
22shared memory block exists and if it does, it will connect to the QLocalServer
23to notify the primary instance that a new instance had been started, after which
24it would terminate with status code `0`. In the Primary Instance
25`SingleApplication` would emit the `instanceStarted()` signal upon detecting
26that a new instance had been started.
27
28The library uses `stdlib` to terminate the program with the `exit()` function.
29
30You can use the library as if you use any other `QCoreApplication` derived
31class:
32
33```cpp
34#include <QApplication>
35#include <SingleApplication.h>
36
37int main( int argc, char* argv[] )
38{
39    SingleApplication app( argc, argv );
40
41    return app.exec();
42}
43```
44
45To include the library files I would recommend that you add it as a git
46submodule to your project and include it's contents with a `.pri` file. Here is
47how:
48
49```bash
50git submodule add git@github.com:itay-grudev/SingleApplication.git singleapplication
51```
52
53Then include the `singleapplication.pri` file in your `.pro` project file. Also
54don't forget to specify which `QCoreApplication` class your app is using if it
55is not `QCoreApplication`.
56
57```qmake
58include(singleapplication/singleapplication.pri)
59DEFINES += QAPPLICATION_CLASS=QApplication
60```
61
62The `Instance Started` signal
63------------------------
64
65The SingleApplication class implements a `instanceStarted()` signal. You can
66bind to that signal to raise your application's window when a new instance had
67been started, for example.
68
69```cpp
70// window is a QWindow instance
71QObject::connect(
72    &app,
73    &SingleApplication::instanceStarted,
74    &window,
75    &QWindow::raise
76);
77```
78
79Using `SingleApplication::instance()` is a neat way to get the
80`SingleApplication` instance for binding to it's signals anywhere in your
81program.
82
83__Note:__ On Windows the ability to bring the application windows to the
84foreground is restricted. See [Windows specific implementations](Windows.md)
85for a workaround and an example implementation.
86
87
88Secondary Instances
89-------------------
90
91If you want to be able to launch additional Secondary Instances (not related to
92your Primary Instance) you have to enable that with the third parameter of the
93`SingleApplication` constructor. The default is `false` meaning no Secondary
94Instances. Here is an example of how you would start a Secondary Instance send
95a message with the command line arguments to the primary instance and then shut
96down.
97
98```cpp
99int main(int argc, char *argv[])
100{
101    SingleApplication app( argc, argv, true );
102
103    if( app.isSecondary() ) {
104        app.sendMessage(  app.arguments().join(' ')).toUtf8() );
105        app.exit( 0 );
106    }
107
108    return app.exec();
109}
110```
111
112*__Note:__ A secondary instance won't cause the emission of the
113`instanceStarted()` signal by default. See `SingleApplication::Mode` for more
114details.*
115
116You can check whether your instance is a primary or secondary with the following
117methods:
118
119```cpp
120app.isPrimary();
121// or
122app.isSecondary();
123```
124
125*__Note:__ If your Primary Instance is terminated a newly launched instance
126will replace the Primary one even if the Secondary flag has been set.*
127
128API
129---
130
131### Members
132
133```cpp
134SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 )
135```
136
137Depending on whether `allowSecondary` is set, this constructor may terminate
138your app if there is already a primary instance running. Additional `Options`
139can be specified to set whether the SingleApplication block should work
140user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be
141used to notify the primary instance whenever a secondary instance had been
142started (disabled by default). `timeout` specifies the maximum time in
143milliseconds to wait for blocking operations.
144
145*__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it
146recognizes.*
147
148*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
149and the secondary instance.*
150
151*__Note:__ Operating system can restrict the shared memory blocks to the same
152user, in which case the User/System modes will have no effect and the block will
153be user wide.*
154
155---
156
157```cpp
158bool SingleApplication::sendMessage( QByteArray message, int timeout = 100 )
159```
160
161Sends `message` to the Primary Instance. Uses `timeout` as a the maximum timeout
162in milliseconds for blocking functions
163
164---
165
166```cpp
167bool SingleApplication::isPrimary()
168```
169
170Returns if the instance is the primary instance.
171
172---
173
174```cpp
175bool SingleApplication::isSecondary()
176```
177Returns if the instance is a secondary instance.
178
179---
180
181```cpp
182quint32 SingleApplication::instanceId()
183```
184
185Returns a unique identifier for the current instance.
186
187---
188
189```cpp
190qint64 SingleApplication::primaryPid()
191```
192
193Returns the process ID (PID) of the primary instance.
194
195### Signals
196
197```cpp
198void SingleApplication::instanceStarted()
199```
200
201Triggered whenever a new instance had been started, except for secondary
202instances if the `Mode::SecondaryNotification` flag is not specified.
203
204---
205
206```cpp
207void SingleApplication::receivedMessage( quint32 instanceId, QByteArray message )
208```
209
210Triggered whenever there is a message received from a secondary instance.
211
212---
213
214### Flags
215
216```cpp
217enum SingleApplication::Mode
218```
219
220*   `Mode::User` - The SingleApplication block should apply user wide. This adds
221    user specific data to the key used for the shared memory and server name.
222    This is the default functionality.
223*   `Mode::System` – The SingleApplication block applies system-wide.
224*   `Mode::SecondaryNotification` – Whether to trigger `instanceStarted()` even
225    whenever secondary instances are started.
226*   `Mode::ExcludeAppPath` – Excludes the application path from the server name
227    (and memory block) hash.
228*   `Mode::ExcludeAppVersion` – Excludes the application version from the server
229    name (and memory block) hash.
230
231*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
232and the secondary instance.*
233
234*__Note:__ Operating system can restrict the shared memory blocks to the same
235user, in which case the User/System modes will have no effect and the block will
236be user wide.*
237
238---
239
240Versioning
241----------
242
243Each major version introduces either very significant changes or is not
244backwards compatible with the previous version. Minor versions only add
245additional features, bug fixes or performance improvements and are backwards
246compatible with the previous release. See [`CHANGELOG.md`](CHANGELOG.md) for
247more details.
248
249Implementation
250--------------
251
252The library is implemented with a QSharedMemory block which is thread safe and
253guarantees a race condition will not occur. It also uses a QLocalSocket to
254notify the main process that a new instance had been spawned and thus invoke the
255`instanceStarted()` signal and for messaging the primary instance.
256
257Additionally the library can recover from being forcefully killed on *nix
258systems and will reset the memory block given that there are no other
259instances running.
260
261License
262-------
263This library and it's supporting documentation are released under
264`The MIT License (MIT)` with the exception of the Qt calculator examples which
265is distributed under the BSD license.
266