Vladimir Golovnev
5 years ago
committed by
GitHub
25 changed files with 163 additions and 863 deletions
@ -0,0 +1,82 @@ |
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent. |
||||||
|
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru> |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License |
||||||
|
* as published by the Free Software Foundation; either version 2 |
||||||
|
* of the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
* |
||||||
|
* In addition, as a special exception, the copyright holders give permission to |
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library), |
||||||
|
* and distribute the linked executables. You must obey the GNU General Public |
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you |
||||||
|
* modify file(s), you may extend this exception to your version of the file(s), |
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||||
|
* exception statement from your version. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "applicationinstancemanager.h" |
||||||
|
|
||||||
|
#ifdef Q_OS_WIN |
||||||
|
#include <windows.h> |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <QDebug> |
||||||
|
#include <QSharedMemory> |
||||||
|
|
||||||
|
#include "qtlocalpeer/qtlocalpeer.h" |
||||||
|
|
||||||
|
ApplicationInstanceManager::ApplicationInstanceManager(const QString &appId, QObject *parent) |
||||||
|
: QObject {parent} |
||||||
|
, m_peer {new QtLocalPeer {this, appId}} |
||||||
|
, m_isFirstInstance {!m_peer->isClient()} |
||||||
|
{ |
||||||
|
connect(m_peer, &QtLocalPeer::messageReceived, this, &ApplicationInstanceManager::messageReceived); |
||||||
|
|
||||||
|
#ifdef Q_OS_WIN |
||||||
|
auto sharedMem = new QSharedMemory {appId + QLatin1String {"-shared-memory-key"}, this}; |
||||||
|
if (m_isFirstInstance) { |
||||||
|
// First instance creates shared memory and store PID
|
||||||
|
if (sharedMem->create(sizeof(DWORD)) && sharedMem->lock()) { |
||||||
|
*(static_cast<DWORD *>(sharedMem->data())) = ::GetCurrentProcessId(); |
||||||
|
sharedMem->unlock(); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
// Later instances attach to shared memory and retrieve PID
|
||||||
|
if (sharedMem->attach() && sharedMem->lock()) { |
||||||
|
::AllowSetForegroundWindow(*(static_cast<DWORD *>(sharedMem->data()))); |
||||||
|
sharedMem->unlock(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (!sharedMem->isAttached()) |
||||||
|
qCritical() << "Failed to initialize shared memory: " << sharedMem->errorString(); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
bool ApplicationInstanceManager::isFirstInstance() const |
||||||
|
{ |
||||||
|
return m_isFirstInstance; |
||||||
|
} |
||||||
|
|
||||||
|
bool ApplicationInstanceManager::sendMessage(const QString &message, const int timeout) |
||||||
|
{ |
||||||
|
return m_peer->sendMessage(message, timeout); |
||||||
|
} |
||||||
|
|
||||||
|
QString ApplicationInstanceManager::appId() const |
||||||
|
{ |
||||||
|
return m_peer->applicationId(); |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent. |
||||||
|
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru> |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License |
||||||
|
* as published by the Free Software Foundation; either version 2 |
||||||
|
* of the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
* |
||||||
|
* In addition, as a special exception, the copyright holders give permission to |
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library), |
||||||
|
* and distribute the linked executables. You must obey the GNU General Public |
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you |
||||||
|
* modify file(s), you may extend this exception to your version of the file(s), |
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||||
|
* exception statement from your version. |
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QObject> |
||||||
|
|
||||||
|
class QtLocalPeer; |
||||||
|
|
||||||
|
class ApplicationInstanceManager : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
Q_DISABLE_COPY(ApplicationInstanceManager) |
||||||
|
|
||||||
|
public: |
||||||
|
explicit ApplicationInstanceManager(const QString &appId, QObject *parent = nullptr); |
||||||
|
|
||||||
|
bool isFirstInstance() const; |
||||||
|
QString appId() const; |
||||||
|
|
||||||
|
public slots: |
||||||
|
bool sendMessage(const QString &message, int timeout = 5000); |
||||||
|
|
||||||
|
signals: |
||||||
|
void messageReceived(const QString &message); |
||||||
|
|
||||||
|
private: |
||||||
|
QtLocalPeer *m_peer; |
||||||
|
const bool m_isFirstInstance; |
||||||
|
}; |
@ -1,31 +0,0 @@ |
|||||||
project(qtsingleapplication) |
|
||||||
|
|
||||||
set(QBT_QTSINGLEAPPLICATION_HEADERS |
|
||||||
qtlocalpeer.h |
|
||||||
) |
|
||||||
|
|
||||||
set(QBT_QTSINGLEAPPLICATION_SOURCES |
|
||||||
qtlocalpeer.cpp |
|
||||||
) |
|
||||||
|
|
||||||
if (Qt5Widgets_FOUND) |
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsingleapplication.h) |
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsingleapplication.cpp) |
|
||||||
else (Qt5Widgets_FOUND) |
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsinglecoreapplication.h) |
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsinglecoreapplication.cpp) |
|
||||||
endif (Qt5Widgets_FOUND) |
|
||||||
|
|
||||||
add_library(qtsingleapplication STATIC ${QBT_QTSINGLEAPPLICATION_HEADERS} ${QBT_QTSINGLEAPPLICATION_SOURCES}) |
|
||||||
target_include_directories(qtsingleapplication INTERFACE "${qtsingleapplication_SOURCE_DIR}") |
|
||||||
target_link_libraries(qtsingleapplication PRIVATE Qt5::Network) |
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") |
|
||||||
target_compile_options(qtsingleapplication PRIVATE "-w") # disable warning for 3rdparty code |
|
||||||
endif() |
|
||||||
|
|
||||||
if (Qt5Widgets_FOUND) |
|
||||||
target_link_libraries(qtsingleapplication PRIVATE Qt5::Widgets) |
|
||||||
endif (Qt5Widgets_FOUND) |
|
||||||
|
|
||||||
add_library(QtSingleApplication::QtSingleApplication ALIAS qtsingleapplication) |
|
@ -1 +0,0 @@ |
|||||||
#include "qtlockedfile.h" |
|
@ -1 +0,0 @@ |
|||||||
#include "qtsingleapplication.h" |
|
@ -1,347 +0,0 @@ |
|||||||
/****************************************************************************
|
|
||||||
** |
|
||||||
** 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(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\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 |
|
||||||
*/ |
|
@ -1,105 +0,0 @@ |
|||||||
/****************************************************************************
|
|
||||||
** |
|
||||||
** 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$ |
|
||||||
** |
|
||||||
****************************************************************************/ |
|
||||||
|
|
||||||
#ifndef QTSINGLEAPPLICATION_H |
|
||||||
#define QTSINGLEAPPLICATION_H |
|
||||||
|
|
||||||
#include <QApplication> |
|
||||||
|
|
||||||
class QtLocalPeer; |
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) |
|
||||||
# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) |
|
||||||
# define QT_QTSINGLEAPPLICATION_EXPORT |
|
||||||
# elif defined(QT_QTSINGLEAPPLICATION_IMPORT) |
|
||||||
# if defined(QT_QTSINGLEAPPLICATION_EXPORT) |
|
||||||
# undef QT_QTSINGLEAPPLICATION_EXPORT |
|
||||||
# endif |
|
||||||
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) |
|
||||||
# elif defined(QT_QTSINGLEAPPLICATION_EXPORT) |
|
||||||
# undef QT_QTSINGLEAPPLICATION_EXPORT |
|
||||||
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) |
|
||||||
# endif |
|
||||||
#else |
|
||||||
# define QT_QTSINGLEAPPLICATION_EXPORT |
|
||||||
#endif |
|
||||||
|
|
||||||
class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication |
|
||||||
{ |
|
||||||
Q_OBJECT |
|
||||||
|
|
||||||
public: |
|
||||||
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); |
|
||||||
QtSingleApplication(const QString &id, int &argc, char **argv); |
|
||||||
#if QT_VERSION < 0x050000 |
|
||||||
QtSingleApplication(int &argc, char **argv, Type type); |
|
||||||
# if defined(Q_WS_X11) |
|
||||||
QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); |
|
||||||
QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); |
|
||||||
QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); |
|
||||||
# endif // Q_WS_X11
|
|
||||||
#endif // QT_VERSION < 0x050000
|
|
||||||
|
|
||||||
bool isRunning(); |
|
||||||
QString id() const; |
|
||||||
|
|
||||||
void setActivationWindow(QWidget* aw, bool activateOnMessage = true); |
|
||||||
QWidget* activationWindow() const; |
|
||||||
|
|
||||||
// Obsolete:
|
|
||||||
void initialize(bool dummy = true) |
|
||||||
{ isRunning(); Q_UNUSED(dummy) } |
|
||||||
|
|
||||||
public Q_SLOTS: |
|
||||||
bool sendMessage(const QString &message, int timeout = 5000); |
|
||||||
void activateWindow(); |
|
||||||
|
|
||||||
|
|
||||||
Q_SIGNALS: |
|
||||||
void messageReceived(const QString &message); |
|
||||||
|
|
||||||
|
|
||||||
private: |
|
||||||
void sysInit(const QString &appId = QString()); |
|
||||||
QtLocalPeer *peer; |
|
||||||
QWidget *actWin; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // QTSINGLEAPPLICATION_H
|
|
@ -1,16 +0,0 @@ |
|||||||
INCLUDEPATH += $$PWD |
|
||||||
DEPENDPATH += $$PWD |
|
||||||
QT *= network |
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets |
|
||||||
|
|
||||||
qtsingleapplication-uselib:!qtsingleapplication-buildlib { |
|
||||||
LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME |
|
||||||
} else { |
|
||||||
SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp |
|
||||||
HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h |
|
||||||
} |
|
||||||
|
|
||||||
win32 { |
|
||||||
contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT |
|
||||||
else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT |
|
||||||
} |
|
@ -1,149 +0,0 @@ |
|||||||
/****************************************************************************
|
|
||||||
** |
|
||||||
** 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 "qtsinglecoreapplication.h" |
|
||||||
#include "qtlocalpeer.h" |
|
||||||
|
|
||||||
/*!
|
|
||||||
\class QtSingleCoreApplication qtsinglecoreapplication.h |
|
||||||
\brief A variant of the QtSingleApplication class for non-GUI applications. |
|
||||||
|
|
||||||
This class is a variant of QtSingleApplication suited for use in |
|
||||||
console (non-GUI) applications. It is an extension of |
|
||||||
QCoreApplication (instead of QApplication). It does not require |
|
||||||
the QtGui library. |
|
||||||
|
|
||||||
The API and usage is identical to QtSingleApplication, except that |
|
||||||
functions relating to the "activation window" are not present, for |
|
||||||
obvious reasons. Please refer to the QtSingleApplication |
|
||||||
documentation for explanation of the usage. |
|
||||||
|
|
||||||
A QtSingleCoreApplication instance can communicate to a |
|
||||||
QtSingleApplication instance if they share the same application |
|
||||||
id. Hence, this class can be used to create a light-weight |
|
||||||
command-line tool that sends commands to a GUI application. |
|
||||||
|
|
||||||
\sa QtSingleApplication |
|
||||||
*/ |
|
||||||
|
|
||||||
/*!
|
|
||||||
Creates a QtSingleCoreApplication object. The application identifier |
|
||||||
will be QCoreApplication::applicationFilePath(). \a argc and \a |
|
||||||
argv are passed on to the QCoreAppliation constructor. |
|
||||||
*/ |
|
||||||
|
|
||||||
QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) |
|
||||||
: QCoreApplication(argc, argv) |
|
||||||
{ |
|
||||||
peer = new QtLocalPeer(this); |
|
||||||
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Creates a QtSingleCoreApplication object with the application |
|
||||||
identifier \a appId. \a argc and \a argv are passed on to the |
|
||||||
QCoreAppliation constructor. |
|
||||||
*/ |
|
||||||
QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) |
|
||||||
: QCoreApplication(argc, argv) |
|
||||||
{ |
|
||||||
peer = new QtLocalPeer(this, appId); |
|
||||||
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
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 QtSingleCoreApplication::isRunning() |
|
||||||
{ |
|
||||||
return peer->isClient(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Tries to send the text \a message to the currently running |
|
||||||
instance. The QtSingleCoreApplication 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 QtSingleCoreApplication::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 QtSingleCoreApplication::id() const |
|
||||||
{ |
|
||||||
return peer->applicationId(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn void QtSingleCoreApplication::messageReceived(const QString& message) |
|
||||||
|
|
||||||
This signal is emitted when the current instance receives a \a |
|
||||||
message from another instance of this application. |
|
||||||
|
|
||||||
\sa sendMessage() |
|
||||||
*/ |
|
@ -1,71 +0,0 @@ |
|||||||
/****************************************************************************
|
|
||||||
** |
|
||||||
** 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$ |
|
||||||
** |
|
||||||
****************************************************************************/ |
|
||||||
|
|
||||||
#ifndef QTSINGLECOREAPPLICATION_H |
|
||||||
#define QTSINGLECOREAPPLICATION_H |
|
||||||
|
|
||||||
#include <QCoreApplication> |
|
||||||
|
|
||||||
class QtLocalPeer; |
|
||||||
|
|
||||||
class QtSingleCoreApplication : public QCoreApplication |
|
||||||
{ |
|
||||||
Q_OBJECT |
|
||||||
|
|
||||||
public: |
|
||||||
QtSingleCoreApplication(int &argc, char **argv); |
|
||||||
QtSingleCoreApplication(const QString &id, int &argc, char **argv); |
|
||||||
|
|
||||||
bool isRunning(); |
|
||||||
QString id() const; |
|
||||||
|
|
||||||
public Q_SLOTS: |
|
||||||
bool sendMessage(const QString &message, int timeout = 5000); |
|
||||||
|
|
||||||
|
|
||||||
Q_SIGNALS: |
|
||||||
void messageReceived(const QString &message); |
|
||||||
|
|
||||||
|
|
||||||
private: |
|
||||||
QtLocalPeer* peer; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // QTSINGLECOREAPPLICATION_H
|
|
@ -1,10 +0,0 @@ |
|||||||
INCLUDEPATH += $$PWD |
|
||||||
DEPENDPATH += $$PWD |
|
||||||
HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h |
|
||||||
SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp |
|
||||||
|
|
||||||
QT *= network |
|
||||||
|
|
||||||
win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { |
|
||||||
DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) |
|
||||||
} |
|
Loading…
Reference in new issue