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 */