File indexing completed on 2024-12-22 04:40:50
0001 /**************************************************************************** 0002 ** 0003 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 0004 ** Contact: http://www.qt-project.org/legal 0005 ** 0006 ** This file is part of the Qt Solutions component. 0007 ** 0008 ** $QT_BEGIN_LICENSE:BSD$ 0009 ** You may use this file under the terms of the BSD license as follows: 0010 ** 0011 ** "Redistribution and use in source and binary forms, with or without 0012 ** modification, are permitted provided that the following conditions are 0013 ** met: 0014 ** * Redistributions of source code must retain the above copyright 0015 ** notice, this list of conditions and the following disclaimer. 0016 ** * Redistributions in binary form must reproduce the above copyright 0017 ** notice, this list of conditions and the following disclaimer in 0018 ** the documentation and/or other materials provided with the 0019 ** distribution. 0020 ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 0021 ** of its contributors may be used to endorse or promote products derived 0022 ** from this software without specific prior written permission. 0023 ** 0024 ** 0025 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 0026 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 0027 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 0028 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 0029 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 0030 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 0031 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0032 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0033 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0034 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 0035 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 0036 ** 0037 ** $QT_END_LICENSE$ 0038 ** 0039 ****************************************************************************/ 0040 0041 0042 #include "qtsingleapplication.h" 0043 #include "qtlocalpeer.h" 0044 #include <QWidget> 0045 0046 0047 /*! 0048 \class QtSingleApplication qtsingleapplication.h 0049 \brief The QtSingleApplication class provides an API to detect and 0050 communicate with running instances of an application. 0051 0052 This class allows you to create applications where only one 0053 instance should be running at a time. I.e., if the user tries to 0054 launch another instance, the already running instance will be 0055 activated instead. Another usecase is a client-server system, 0056 where the first started instance will assume the role of server, 0057 and the later instances will act as clients of that server. 0058 0059 By default, the full path of the executable file is used to 0060 determine whether two processes are instances of the same 0061 application. You can also provide an explicit identifier string 0062 that will be compared instead. 0063 0064 The application should create the QtSingleApplication object early 0065 in the startup phase, and call isRunning() to find out if another 0066 instance of this application is already running. If isRunning() 0067 returns false, it means that no other instance is running, and 0068 this instance has assumed the role as the running instance. In 0069 this case, the application should continue with the initialization 0070 of the application user interface before entering the event loop 0071 with exec(), as normal. 0072 0073 The messageReceived() signal will be emitted when the running 0074 application receives messages from another instance of the same 0075 application. When a message is received it might be helpful to the 0076 user to raise the application so that it becomes visible. To 0077 facilitate this, QtSingleApplication provides the 0078 setActivationWindow() function and the activateWindow() slot. 0079 0080 If isRunning() returns true, another instance is already 0081 running. It may be alerted to the fact that another instance has 0082 started by using the sendMessage() function. Also data such as 0083 startup parameters (e.g. the name of the file the user wanted this 0084 new instance to open) can be passed to the running instance with 0085 this function. Then, the application should terminate (or enter 0086 client mode). 0087 0088 If isRunning() returns true, but sendMessage() fails, that is an 0089 indication that the running instance is frozen. 0090 0091 Here's an example that shows how to convert an existing 0092 application to use QtSingleApplication. It is very simple and does 0093 not make use of all QtSingleApplication's functionality (see the 0094 examples for that). 0095 0096 \code 0097 // Original 0098 int main(int argc, char **argv) 0099 { 0100 QApplication app(argc, argv); 0101 0102 MyMainWidget mmw; 0103 mmw.show(); 0104 return app.exec(); 0105 } 0106 0107 // Single instance 0108 int main(int argc, char **argv) 0109 { 0110 QtSingleApplication app(argc, argv); 0111 0112 if (app.isRunning()) 0113 return !app.sendMessage(someDataString); 0114 0115 MyMainWidget mmw; 0116 app.setActivationWindow(&mmw); 0117 mmw.show(); 0118 return app.exec(); 0119 } 0120 \endcode 0121 0122 Once this QtSingleApplication instance is destroyed (normally when 0123 the process exits or crashes), when the user next attempts to run the 0124 application this instance will not, of course, be encountered. The 0125 next instance to call isRunning() or sendMessage() will assume the 0126 role as the new running instance. 0127 0128 For console (non-GUI) applications, QtSingleCoreApplication may be 0129 used instead of this class, to avoid the dependency on the QtGui 0130 library. 0131 0132 \sa QtSingleCoreApplication 0133 */ 0134 0135 0136 void QtSingleApplication::sysInit(const QString &appId) 0137 { 0138 actWin = nullptr; 0139 peer = new QtLocalPeer(this, appId); 0140 connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::messageReceived); 0141 } 0142 0143 0144 /*! 0145 Creates a QtSingleApplication object. The application identifier 0146 will be QCoreApplication::applicationFilePath(). \a argc, \a 0147 argv, and \a GUIenabled are passed on to the QAppliation constructor. 0148 0149 If you are creating a console application (i.e. setting \a 0150 GUIenabled to false), you may consider using 0151 QtSingleCoreApplication instead. 0152 */ 0153 0154 QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) 0155 : QApplication(argc, argv, GUIenabled) 0156 { 0157 sysInit(); 0158 } 0159 0160 0161 /*! 0162 Creates a QtSingleApplication object with the application 0163 identifier \a appId. \a argc and \a argv are passed on to the 0164 QAppliation constructor. 0165 */ 0166 0167 QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) 0168 : QApplication(argc, argv) 0169 { 0170 sysInit(appId); 0171 } 0172 0173 #if QT_VERSION < 0x050000 0174 0175 /*! 0176 Creates a QtSingleApplication object. The application identifier 0177 will be QCoreApplication::applicationFilePath(). \a argc, \a 0178 argv, and \a type are passed on to the QAppliation constructor. 0179 */ 0180 QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) 0181 : QApplication(argc, argv, type) 0182 { 0183 } 0184 0185 0186 # if defined(Q_WS_X11) 0187 /*! 0188 Special constructor for X11, ref. the documentation of 0189 QApplication's corresponding constructor. The application identifier 0190 will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, 0191 and \a cmap are passed on to the QApplication constructor. 0192 */ 0193 QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) 0194 : QApplication(dpy, visual, cmap) 0195 { 0196 sysInit(); 0197 } 0198 0199 /*! 0200 Special constructor for X11, ref. the documentation of 0201 QApplication's corresponding constructor. The application identifier 0202 will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a 0203 argv, \a visual, and \a cmap are passed on to the QApplication 0204 constructor. 0205 */ 0206 QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) 0207 : QApplication(dpy, argc, argv, visual, cmap) 0208 { 0209 sysInit(); 0210 } 0211 0212 /*! 0213 Special constructor for X11, ref. the documentation of 0214 QApplication's corresponding constructor. The application identifier 0215 will be \a appId. \a dpy, \a argc, \a 0216 argv, \a visual, and \a cmap are passed on to the QApplication 0217 constructor. 0218 */ 0219 QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) 0220 : QApplication(dpy, argc, argv, visual, cmap) 0221 { 0222 sysInit(appId); 0223 } 0224 # endif // Q_WS_X11 0225 #endif // QT_VERSION < 0x050000 0226 0227 0228 /*! 0229 Returns true if another instance of this application is running; 0230 otherwise false. 0231 0232 This function does not find instances of this application that are 0233 being run by a different user (on Windows: that are running in 0234 another session). 0235 0236 \sa sendMessage() 0237 */ 0238 0239 bool QtSingleApplication::isRunning() 0240 { 0241 return peer->isClient(); 0242 } 0243 0244 void QtSingleApplication::setAppId(const QString &id) 0245 { 0246 sysInit(id); 0247 } 0248 0249 0250 /*! 0251 Tries to send the text \a message to the currently running 0252 instance. The QtSingleApplication object in the running instance 0253 will Q_EMIT the messageReceived() signal when it receives the 0254 message. 0255 0256 This function returns true if the message has been sent to, and 0257 processed by, the current instance. If there is no instance 0258 currently running, or if the running instance fails to process the 0259 message within \a timeout milliseconds, this function return false. 0260 0261 \sa isRunning(), messageReceived() 0262 */ 0263 bool QtSingleApplication::sendMessage(const QString &message, int timeout) 0264 { 0265 return peer->sendMessage(message, timeout); 0266 } 0267 0268 0269 /*! 0270 Returns the application identifier. Two processes with the same 0271 identifier will be regarded as instances of the same application. 0272 */ 0273 QString QtSingleApplication::id() const 0274 { 0275 return peer->applicationId(); 0276 } 0277 0278 0279 /*! 0280 Sets the activation window of this application to \a aw. The 0281 activation window is the widget that will be activated by 0282 activateWindow(). This is typically the application's main window. 0283 0284 If \a activateOnMessage is true (the default), the window will be 0285 activated automatically every time a message is received, just prior 0286 to the messageReceived() signal being emitted. 0287 0288 \sa activateWindow(), messageReceived() 0289 */ 0290 0291 void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) 0292 { 0293 actWin = aw; 0294 if (activateOnMessage) 0295 connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); 0296 else 0297 disconnect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); 0298 } 0299 0300 0301 /*! 0302 Returns the applications activation window if one has been set by 0303 calling setActivationWindow(), otherwise returns 0. 0304 0305 \sa setActivationWindow() 0306 */ 0307 QWidget* QtSingleApplication::activationWindow() const 0308 { 0309 return actWin; 0310 } 0311 0312 void QtSingleApplication::removeLockFile() 0313 { 0314 peer->removeLockedFile(); 0315 } 0316 0317 0318 /*! 0319 De-minimizes, raises, and activates this application's activation window. 0320 This function does nothing if no activation window has been set. 0321 0322 This is a convenience function to show the user that this 0323 application instance has been activated when he has tried to start 0324 another instance. 0325 0326 This function should typically be called in response to the 0327 messageReceived() signal. By default, that will happen 0328 automatically, if an activation window has been set. 0329 0330 \sa setActivationWindow(), messageReceived(), initialize() 0331 */ 0332 void QtSingleApplication::activateWindow() 0333 { 0334 if (actWin) { 0335 actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); 0336 actWin->raise(); 0337 actWin->activateWindow(); 0338 } 0339 } 0340 0341 0342 /*! 0343 \fn void QtSingleApplication::messageReceived(const QString& message) 0344 0345 This signal is emitted when the current instance receives a \a 0346 message from another instance of this application. 0347 0348 \sa sendMessage(), setActivationWindow(), activateWindow() 0349 */ 0350 0351 0352 /*! 0353 \fn void QtSingleApplication::initialize(bool dummy = true) 0354 0355 \obsolete 0356 */