351 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			351 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /****************************************************************************
 | |
| **
 | |
| ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | |
| ** Contact: http://www.qt-project.org/legal
 | |
| **
 | |
| ** This file is part of the Qt Solutions component.
 | |
| **
 | |
| ** $QT_BEGIN_LICENSE:BSD$
 | |
| ** You may use this file under the terms of the BSD license as follows:
 | |
| **
 | |
| ** "Redistribution and use in source and binary forms, with or without
 | |
| ** modification, are permitted provided that the following conditions are
 | |
| ** met:
 | |
| **   * Redistributions of source code must retain the above copyright
 | |
| **     notice, this list of conditions and the following disclaimer.
 | |
| **   * Redistributions in binary form must reproduce the above copyright
 | |
| **     notice, this list of conditions and the following disclaimer in
 | |
| **     the documentation and/or other materials provided with the
 | |
| **     distribution.
 | |
| **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
 | |
| **     of its contributors may be used to endorse or promote products derived
 | |
| **     from this software without specific prior written permission.
 | |
| **
 | |
| **
 | |
| ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 | |
| **
 | |
| ** $QT_END_LICENSE$
 | |
| **
 | |
| ****************************************************************************/
 | |
| 
 | |
| 
 | |
| #include "qtsingleapplication.h"
 | |
| #include "qtlocalpeer.h"
 | |
| #include <QWidget>
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     \class QtSingleApplication qtsingleapplication.h
 | |
|     \brief The QtSingleApplication class provides an API to detect and
 | |
|     communicate with running instances of an application.
 | |
| 
 | |
|     This class allows you to create applications where only one
 | |
|     instance should be running at a time. I.e., if the user tries to
 | |
|     launch another instance, the already running instance will be
 | |
|     activated instead. Another usecase is a client-server system,
 | |
|     where the first started instance will assume the role of server,
 | |
|     and the later instances will act as clients of that server.
 | |
| 
 | |
|     By default, the full path of the executable file is used to
 | |
|     determine whether two processes are instances of the same
 | |
|     application. You can also provide an explicit identifier string
 | |
|     that will be compared instead.
 | |
| 
 | |
|     The application should create the QtSingleApplication object early
 | |
|     in the startup phase, and call isRunning() to find out if another
 | |
|     instance of this application is already running. If isRunning()
 | |
|     returns false, it means that no other instance is running, and
 | |
|     this instance has assumed the role as the running instance. In
 | |
|     this case, the application should continue with the initialization
 | |
|     of the application user interface before entering the event loop
 | |
|     with exec(), as normal.
 | |
| 
 | |
|     The messageReceived() signal will be emitted when the running
 | |
|     application receives messages from another instance of the same
 | |
|     application. When a message is received it might be helpful to the
 | |
|     user to raise the application so that it becomes visible. To
 | |
|     facilitate this, QtSingleApplication provides the
 | |
|     setActivationWindow() function and the activateWindow() slot.
 | |
| 
 | |
|     If isRunning() returns true, another instance is already
 | |
|     running. It may be alerted to the fact that another instance has
 | |
|     started by using the sendMessage() function. Also data such as
 | |
|     startup parameters (e.g. the name of the file the user wanted this
 | |
|     new instance to open) can be passed to the running instance with
 | |
|     this function. Then, the application should terminate (or enter
 | |
|     client mode).
 | |
| 
 | |
|     If isRunning() returns true, but sendMessage() fails, that is an
 | |
|     indication that the running instance is frozen.
 | |
| 
 | |
|     Here's an example that shows how to convert an existing
 | |
|     application to use QtSingleApplication. It is very simple and does
 | |
|     not make use of all QtSingleApplication's functionality (see the
 | |
|     examples for that).
 | |
| 
 | |
|     \code
 | |
|     // Original
 | |
|     int main(int argc, char **argv)
 | |
|     {
 | |
|         QApplication app(argc, argv);
 | |
| 
 | |
|         MyMainWidget mmw;
 | |
|         mmw.show();
 | |
|         return app.exec();
 | |
|     }
 | |
| 
 | |
|     // Single instance
 | |
|     int main(int argc, char **argv)
 | |
|     {
 | |
|         QtSingleApplication app(argc, argv);
 | |
| 
 | |
|         if (app.isRunning())
 | |
|             return !app.sendMessage(someDataString);
 | |
| 
 | |
|         MyMainWidget mmw;
 | |
|         app.setActivationWindow(&mmw);
 | |
|         mmw.show();
 | |
|         return app.exec();
 | |
|     }
 | |
|     \endcode
 | |
| 
 | |
|     Once this QtSingleApplication instance is destroyed (normally when
 | |
|     the process exits or crashes), when the user next attempts to run the
 | |
|     application this instance will not, of course, be encountered. The
 | |
|     next instance to call isRunning() or sendMessage() will assume the
 | |
|     role as the new running instance.
 | |
| 
 | |
|     For console (non-GUI) applications, QtSingleCoreApplication may be
 | |
|     used instead of this class, to avoid the dependency on the QtGui
 | |
|     library.
 | |
| 
 | |
|     \sa QtSingleCoreApplication
 | |
| */
 | |
| 
 | |
| 
 | |
| void QtSingleApplication::sysInit(const QString &appId)
 | |
| {
 | |
|     actWin = 0;
 | |
|     peer = new QtLocalPeer(this, appId);
 | |
|     connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     Creates a QtSingleApplication object. The application identifier
 | |
|     will be QCoreApplication::applicationFilePath(). \a argc, \a
 | |
|     argv, and \a GUIenabled are passed on to the QAppliation constructor.
 | |
| 
 | |
|     If you are creating a console application (i.e. setting \a
 | |
|     GUIenabled to false), you may consider using
 | |
|     QtSingleCoreApplication instead.
 | |
| */
 | |
| 
 | |
| QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
 | |
|     : QApplication(argc, argv, GUIenabled)
 | |
| {
 | |
|     sysInit();
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     Creates a QtSingleApplication object with the application
 | |
|     identifier \a appId. \a argc and \a argv are passed on to the
 | |
|     QAppliation constructor.
 | |
| */
 | |
| 
 | |
| QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
 | |
|     : QApplication(argc, argv)
 | |
| {
 | |
|     sysInit(appId);
 | |
| }
 | |
| 
 | |
| #if QT_VERSION < 0x050000
 | |
| 
 | |
| /*!
 | |
|     Creates a QtSingleApplication object. The application identifier
 | |
|     will be QCoreApplication::applicationFilePath(). \a argc, \a
 | |
|     argv, and \a type are passed on to the QAppliation constructor.
 | |
| */
 | |
| QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type)
 | |
|     : QApplication(argc, argv, type)
 | |
| {
 | |
|     sysInit();
 | |
| }
 | |
| 
 | |
| 
 | |
| #  if defined(Q_WS_X11)
 | |
| /*!
 | |
|   Special constructor for X11, ref. the documentation of
 | |
|   QApplication's corresponding constructor. The application identifier
 | |
|   will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
 | |
|   and \a cmap are passed on to the QApplication constructor.
 | |
| */
 | |
| QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
 | |
|     : QApplication(dpy, visual, cmap)
 | |
| {
 | |
|     sysInit();
 | |
| }
 | |
| 
 | |
| /*!
 | |
|   Special constructor for X11, ref. the documentation of
 | |
|   QApplication's corresponding constructor. The application identifier
 | |
|   will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
 | |
|   argv, \a visual, and \a cmap are passed on to the QApplication
 | |
|   constructor.
 | |
| */
 | |
| QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
 | |
|     : QApplication(dpy, argc, argv, visual, cmap)
 | |
| {
 | |
|     sysInit();
 | |
| }
 | |
| 
 | |
| /*!
 | |
|   Special constructor for X11, ref. the documentation of
 | |
|   QApplication's corresponding constructor. The application identifier
 | |
|   will be \a appId. \a dpy, \a argc, \a
 | |
|   argv, \a visual, and \a cmap are passed on to the QApplication
 | |
|   constructor.
 | |
| */
 | |
| QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
 | |
|     : QApplication(dpy, argc, argv, visual, cmap)
 | |
| {
 | |
|     sysInit(appId);
 | |
| }
 | |
| #  endif // Q_WS_X11
 | |
| #endif // QT_VERSION < 0x050000
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     Returns true if another instance of this application is running;
 | |
|     otherwise false.
 | |
| 
 | |
|     This function does not find instances of this application that are
 | |
|     being run by a different user (on Windows: that are running in
 | |
|     another session).
 | |
| 
 | |
|     \sa sendMessage()
 | |
| */
 | |
| 
 | |
| bool QtSingleApplication::isRunning()
 | |
| {
 | |
|     return peer->isClient();
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     Tries to send the text \a message to the currently running
 | |
|     instance. The QtSingleApplication object in the running instance
 | |
|     will emit the messageReceived() signal when it receives the
 | |
|     message.
 | |
| 
 | |
|     This function returns true if the message has been sent to, and
 | |
|     processed by, the current instance. If there is no instance
 | |
|     currently running, or if the running instance fails to process the
 | |
|     message within \a timeout milliseconds, this function return false.
 | |
| 
 | |
|     \sa isRunning(), messageReceived()
 | |
| */
 | |
| bool QtSingleApplication::sendMessage(const QString &message, int timeout)
 | |
| {
 | |
|     return peer->sendMessage(message, timeout);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     Returns the application identifier. Two processes with the same
 | |
|     identifier will be regarded as instances of the same application.
 | |
| */
 | |
| QString QtSingleApplication::id() const
 | |
| {
 | |
|     return peer->applicationId();
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
|   Sets the activation window of this application to \a aw. The
 | |
|   activation window is the widget that will be activated by
 | |
|   activateWindow(). This is typically the application's main window.
 | |
| 
 | |
|   If \a activateOnMessage is true (the default), the window will be
 | |
|   activated automatically every time a message is received, just prior
 | |
|   to the messageReceived() signal being emitted.
 | |
| 
 | |
|   \sa activateWindow(), messageReceived()
 | |
| */
 | |
| 
 | |
| void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
 | |
| {
 | |
|     actWin = aw;
 | |
|     if (activateOnMessage)
 | |
|         connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
 | |
|     else
 | |
|         disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     Returns the applications activation window if one has been set by
 | |
|     calling setActivationWindow(), otherwise returns 0.
 | |
| 
 | |
|     \sa setActivationWindow()
 | |
| */
 | |
| QWidget* QtSingleApplication::activationWindow() const
 | |
| {
 | |
|     return actWin;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
|   De-minimizes, raises, and activates this application's activation window.
 | |
|   This function does nothing if no activation window has been set.
 | |
| 
 | |
|   This is a convenience function to show the user that this
 | |
|   application instance has been activated when he has tried to start
 | |
|   another instance.
 | |
| 
 | |
|   This function should typically be called in response to the
 | |
|   messageReceived() signal. By default, that will happen
 | |
|   automatically, if an activation window has been set.
 | |
| 
 | |
|   \sa setActivationWindow(), messageReceived(), initialize()
 | |
| */
 | |
| void QtSingleApplication::activateWindow()
 | |
| {
 | |
|     if (actWin) {
 | |
|         actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
 | |
|         actWin->raise();
 | |
|         actWin->activateWindow();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void QtSingleApplication::finish()
 | |
| { 
 | |
|   delete peer; peer = 0;
 | |
| }
 | |
| 
 | |
| /*!
 | |
|     \fn void QtSingleApplication::messageReceived(const QString& message)
 | |
| 
 | |
|     This signal is emitted when the current instance receives a \a
 | |
|     message from another instance of this application.
 | |
| 
 | |
|     \sa sendMessage(), setActivationWindow(), activateWindow()
 | |
| */
 | |
| 
 | |
| 
 | |
| /*!
 | |
|     \fn void QtSingleApplication::initialize(bool dummy = true)
 | |
| 
 | |
|     \obsolete
 | |
| */
 |