Commit | Line | Data |
---|---|---|
15c988f7 JB |
1 | /**************************************************************************** |
2 | ** | |
3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | |
4 | ** All rights reserved. | |
5 | ** | |
6 | ** Contact: Nokia Corporation (qt-info@nokia.com) | |
7 | ** | |
8 | ** This file is part of a Qt Solutions component. | |
9 | ** | |
10 | ** You may use this file under the terms of the BSD license as follows: | |
11 | ** | |
12 | ** "Redistribution and use in source and binary forms, with or without | |
13 | ** modification, are permitted provided that the following conditions are | |
14 | ** met: | |
15 | ** * Redistributions of source code must retain the above copyright | |
16 | ** notice, this list of conditions and the following disclaimer. | |
17 | ** * Redistributions in binary form must reproduce the above copyright | |
18 | ** notice, this list of conditions and the following disclaimer in | |
19 | ** the documentation and/or other materials provided with the | |
20 | ** distribution. | |
21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor | |
22 | ** the names of its contributors may be used to endorse or promote | |
23 | ** products derived from this software without specific prior written | |
24 | ** permission. | |
25 | ** | |
26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | |
37 | ** | |
38 | ****************************************************************************/ | |
39 | ||
40 | ||
41 | #include "qtsingleapplication.h" | |
42 | #include "qtlocalpeer.h" | |
43 | #include <QtGui/QWidget> | |
44 | ||
45 | ||
46 | /*! | |
47 | \class QtSingleApplication qtsingleapplication.h | |
48 | \brief The QtSingleApplication class provides an API to detect and | |
49 | communicate with running instances of an application. | |
50 | ||
51 | This class allows you to create applications where only one | |
52 | instance should be running at a time. I.e., if the user tries to | |
53 | launch another instance, the already running instance will be | |
54 | activated instead. Another usecase is a client-server system, | |
55 | where the first started instance will assume the role of server, | |
56 | and the later instances will act as clients of that server. | |
57 | ||
58 | By default, the full path of the executable file is used to | |
59 | determine whether two processes are instances of the same | |
60 | application. You can also provide an explicit identifier string | |
61 | that will be compared instead. | |
62 | ||
63 | The application should create the QtSingleApplication object early | |
64 | in the startup phase, and call isRunning() to find out if another | |
65 | instance of this application is already running. If isRunning() | |
66 | returns false, it means that no other instance is running, and | |
67 | this instance has assumed the role as the running instance. In | |
68 | this case, the application should continue with the initialization | |
69 | of the application user interface before entering the event loop | |
70 | with exec(), as normal. | |
71 | ||
72 | The messageReceived() signal will be emitted when the running | |
73 | application receives messages from another instance of the same | |
74 | application. When a message is received it might be helpful to the | |
75 | user to raise the application so that it becomes visible. To | |
76 | facilitate this, QtSingleApplication provides the | |
77 | setActivationWindow() function and the activateWindow() slot. | |
78 | ||
79 | If isRunning() returns true, another instance is already | |
80 | running. It may be alerted to the fact that another instance has | |
81 | started by using the sendMessage() function. Also data such as | |
82 | startup parameters (e.g. the name of the file the user wanted this | |
83 | new instance to open) can be passed to the running instance with | |
84 | this function. Then, the application should terminate (or enter | |
85 | client mode). | |
86 | ||
87 | If isRunning() returns true, but sendMessage() fails, that is an | |
88 | indication that the running instance is frozen. | |
89 | ||
90 | Here's an example that shows how to convert an existing | |
91 | application to use QtSingleApplication. It is very simple and does | |
92 | not make use of all QtSingleApplication's functionality (see the | |
93 | examples for that). | |
94 | ||
95 | \code | |
96 | // Original | |
97 | int main(int argc, char **argv) | |
98 | { | |
99 | QApplication app(argc, argv); | |
100 | ||
101 | MyMainWidget mmw; | |
102 | mmw.show(); | |
103 | return app.exec(); | |
104 | } | |
105 | ||
106 | // Single instance | |
107 | int main(int argc, char **argv) | |
108 | { | |
109 | QtSingleApplication app(argc, argv); | |
110 | ||
111 | if (app.isRunning()) | |
112 | return !app.sendMessage(someDataString); | |
113 | ||
114 | MyMainWidget mmw; | |
115 | app.setActivationWindow(&mmw); | |
116 | mmw.show(); | |
117 | return app.exec(); | |
118 | } | |
119 | \endcode | |
120 | ||
121 | Once this QtSingleApplication instance is destroyed (normally when | |
122 | the process exits or crashes), when the user next attempts to run the | |
123 | application this instance will not, of course, be encountered. The | |
124 | next instance to call isRunning() or sendMessage() will assume the | |
125 | role as the new running instance. | |
126 | ||
127 | For console (non-GUI) applications, QtSingleCoreApplication may be | |
128 | used instead of this class, to avoid the dependency on the QtGui | |
129 | library. | |
130 | ||
131 | \sa QtSingleCoreApplication | |
132 | */ | |
133 | ||
134 | ||
135 | void QtSingleApplication::sysInit(const QString &appId) | |
136 | { | |
137 | actWin = 0; | |
138 | peer = new QtLocalPeer(this, appId); | |
139 | connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); | |
140 | } | |
141 | ||
142 | ||
143 | /*! | |
144 | Creates a QtSingleApplication object. The application identifier | |
145 | will be QCoreApplication::applicationFilePath(). \a argc, \a | |
146 | argv, and \a GUIenabled are passed on to the QAppliation constructor. | |
147 | ||
148 | If you are creating a console application (i.e. setting \a | |
149 | GUIenabled to false), you may consider using | |
150 | QtSingleCoreApplication instead. | |
151 | */ | |
152 | ||
153 | QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) | |
154 | : QApplication(argc, argv, GUIenabled) | |
155 | { | |
156 | sysInit(); | |
157 | } | |
158 | ||
159 | ||
160 | /*! | |
161 | Creates a QtSingleApplication object with the application | |
162 | identifier \a appId. \a argc and \a argv are passed on to the | |
163 | QAppliation constructor. | |
164 | */ | |
165 | ||
166 | QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) | |
167 | : QApplication(argc, argv) | |
168 | { | |
169 | sysInit(appId); | |
170 | } | |
171 | ||
172 | ||
173 | /*! | |
174 | Creates a QtSingleApplication object. The application identifier | |
175 | will be QCoreApplication::applicationFilePath(). \a argc, \a | |
176 | argv, and \a type are passed on to the QAppliation constructor. | |
177 | */ | |
178 | QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) | |
179 | : QApplication(argc, argv, type) | |
180 | { | |
181 | sysInit(); | |
182 | } | |
183 | ||
184 | ||
185 | #if defined(Q_WS_X11) | |
186 | /*! | |
187 | Special constructor for X11, ref. the documentation of | |
188 | QApplication's corresponding constructor. The application identifier | |
189 | will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, | |
190 | and \a cmap are passed on to the QApplication constructor. | |
191 | */ | |
192 | QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) | |
193 | : QApplication(dpy, visual, cmap) | |
194 | { | |
195 | sysInit(); | |
196 | } | |
197 | ||
198 | /*! | |
199 | Special constructor for X11, ref. the documentation of | |
200 | QApplication's corresponding constructor. The application identifier | |
201 | will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a | |
202 | argv, \a visual, and \a cmap are passed on to the QApplication | |
203 | constructor. | |
204 | */ | |
205 | QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) | |
206 | : QApplication(dpy, argc, argv, visual, cmap) | |
207 | { | |
208 | sysInit(); | |
209 | } | |
210 | ||
211 | /*! | |
212 | Special constructor for X11, ref. the documentation of | |
213 | QApplication's corresponding constructor. The application identifier | |
214 | will be \a appId. \a dpy, \a argc, \a | |
215 | argv, \a visual, and \a cmap are passed on to the QApplication | |
216 | constructor. | |
217 | */ | |
218 | QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) | |
219 | : QApplication(dpy, argc, argv, visual, cmap) | |
220 | { | |
221 | sysInit(appId); | |
222 | } | |
223 | #endif | |
224 | ||
225 | ||
226 | /*! | |
227 | Returns true if another instance of this application is running; | |
228 | otherwise false. | |
229 | ||
230 | This function does not find instances of this application that are | |
231 | being run by a different user (on Windows: that are running in | |
232 | another session). | |
233 | ||
234 | \sa sendMessage() | |
235 | */ | |
236 | ||
237 | bool QtSingleApplication::isRunning() | |
238 | { | |
239 | return peer->isClient(); | |
240 | } | |
241 | ||
242 | ||
243 | /*! | |
244 | Tries to send the text \a message to the currently running | |
245 | instance. The QtSingleApplication object in the running instance | |
246 | will emit the messageReceived() signal when it receives the | |
247 | message. | |
248 | ||
249 | This function returns true if the message has been sent to, and | |
250 | processed by, the current instance. If there is no instance | |
251 | currently running, or if the running instance fails to process the | |
252 | message within \a timeout milliseconds, this function return false. | |
253 | ||
254 | \sa isRunning(), messageReceived() | |
255 | */ | |
256 | bool QtSingleApplication::sendMessage(const QString &message, int timeout) | |
257 | { | |
258 | return peer->sendMessage(message, timeout); | |
259 | } | |
260 | ||
261 | ||
262 | /*! | |
263 | Returns the application identifier. Two processes with the same | |
264 | identifier will be regarded as instances of the same application. | |
265 | */ | |
266 | QString QtSingleApplication::id() const | |
267 | { | |
268 | return peer->applicationId(); | |
269 | } | |
270 | ||
271 | ||
272 | /*! | |
273 | Sets the activation window of this application to \a aw. The | |
274 | activation window is the widget that will be activated by | |
275 | activateWindow(). This is typically the application's main window. | |
276 | ||
277 | If \a activateOnMessage is true (the default), the window will be | |
278 | activated automatically every time a message is received, just prior | |
279 | to the messageReceived() signal being emitted. | |
280 | ||
281 | \sa activateWindow(), messageReceived() | |
282 | */ | |
283 | ||
284 | void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) | |
285 | { | |
286 | actWin = aw; | |
287 | if (activateOnMessage) | |
288 | connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); | |
289 | else | |
290 | disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); | |
291 | } | |
292 | ||
293 | ||
294 | /*! | |
295 | Returns the applications activation window if one has been set by | |
296 | calling setActivationWindow(), otherwise returns 0. | |
297 | ||
298 | \sa setActivationWindow() | |
299 | */ | |
300 | QWidget* QtSingleApplication::activationWindow() const | |
301 | { | |
302 | return actWin; | |
303 | } | |
304 | ||
305 | ||
306 | /*! | |
307 | De-minimizes, raises, and activates this application's activation window. | |
308 | This function does nothing if no activation window has been set. | |
309 | ||
310 | This is a convenience function to show the user that this | |
311 | application instance has been activated when he has tried to start | |
312 | another instance. | |
313 | ||
314 | This function should typically be called in response to the | |
315 | messageReceived() signal. By default, that will happen | |
316 | automatically, if an activation window has been set. | |
317 | ||
318 | \sa setActivationWindow(), messageReceived(), initialize() | |
319 | */ | |
320 | void QtSingleApplication::activateWindow() | |
321 | { | |
322 | if (actWin) { | |
323 | actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); | |
324 | actWin->raise(); | |
325 | actWin->activateWindow(); | |
326 | } | |
327 | } | |
328 | ||
329 | ||
330 | /*! | |
331 | \fn void QtSingleApplication::messageReceived(const QString& message) | |
332 | ||
333 | This signal is emitted when the current instance receives a \a | |
334 | message from another instance of this application. | |
335 | ||
336 | \sa sendMessage(), setActivationWindow(), activateWindow() | |
337 | */ | |
338 | ||
339 | ||
340 | /*! | |
341 | \fn void QtSingleApplication::initialize(bool dummy = true) | |
342 | ||
343 | \obsolete | |
344 | */ |