Christophe Dumez
15 years ago
24 changed files with 1713 additions and 156 deletions
@ -0,0 +1 @@ |
|||||||
|
#include "qtsingleapplication.h" |
@ -0,0 +1,203 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
|
||||||
|
#include "qtlocalpeer.h" |
||||||
|
#include <QtCore/QCoreApplication> |
||||||
|
#include <QtCore/QTime> |
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) |
||||||
|
#include <QtCore/QLibrary> |
||||||
|
#include <QtCore/qt_windows.h> |
||||||
|
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); |
||||||
|
static PProcessIdToSessionId pProcessIdToSessionId = 0; |
||||||
|
#endif |
||||||
|
#if defined(Q_OS_UNIX) |
||||||
|
#include <time.h> |
||||||
|
#endif |
||||||
|
|
||||||
|
namespace QtLP_Private { |
||||||
|
#include "qtlockedfile.cpp" |
||||||
|
#if defined(Q_OS_WIN) |
||||||
|
#include "qtlockedfile_win.cpp" |
||||||
|
#else |
||||||
|
#include "qtlockedfile_unix.cpp" |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
const char* QtLocalPeer::ack = "ack"; |
||||||
|
|
||||||
|
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) |
||||||
|
: QObject(parent), id(appId) |
||||||
|
{ |
||||||
|
QString prefix = id; |
||||||
|
if (id.isEmpty()) { |
||||||
|
id = QCoreApplication::applicationFilePath(); |
||||||
|
#if defined(Q_OS_WIN) |
||||||
|
id = id.toLower(); |
||||||
|
#endif |
||||||
|
prefix = id.section(QLatin1Char('/'), -1); |
||||||
|
} |
||||||
|
prefix.remove(QRegExp("[^a-zA-Z]")); |
||||||
|
prefix.truncate(6); |
||||||
|
|
||||||
|
QByteArray idc = id.toUtf8(); |
||||||
|
quint16 idNum = qChecksum(idc.constData(), idc.size()); |
||||||
|
socketName = QLatin1String("qtsingleapp-") + prefix |
||||||
|
+ QLatin1Char('-') + QString::number(idNum, 16); |
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) |
||||||
|
if (!pProcessIdToSessionId) { |
||||||
|
QLibrary lib("kernel32"); |
||||||
|
pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); |
||||||
|
} |
||||||
|
if (pProcessIdToSessionId) { |
||||||
|
DWORD sessionId = 0; |
||||||
|
pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); |
||||||
|
socketName += QLatin1Char('-') + QString::number(sessionId, 16); |
||||||
|
} |
||||||
|
#else |
||||||
|
socketName += QLatin1Char('-') + QString::number(::getuid(), 16); |
||||||
|
#endif |
||||||
|
|
||||||
|
server = new QLocalServer(this); |
||||||
|
QString lockName = QDir(QDir::tempPath()).absolutePath() |
||||||
|
+ QLatin1Char('/') + socketName |
||||||
|
+ QLatin1String("-lockfile"); |
||||||
|
lockFile.setFileName(lockName); |
||||||
|
lockFile.open(QIODevice::ReadWrite); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool QtLocalPeer::isClient() |
||||||
|
{ |
||||||
|
if (lockFile.isLocked()) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) |
||||||
|
return true; |
||||||
|
|
||||||
|
bool res = server->listen(socketName); |
||||||
|
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) |
||||||
|
// ### Workaround
|
||||||
|
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { |
||||||
|
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); |
||||||
|
res = server->listen(socketName); |
||||||
|
} |
||||||
|
#endif |
||||||
|
if (!res) |
||||||
|
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); |
||||||
|
QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool QtLocalPeer::sendMessage(const QString &message, int timeout) |
||||||
|
{ |
||||||
|
if (!isClient()) |
||||||
|
return false; |
||||||
|
|
||||||
|
QLocalSocket socket; |
||||||
|
bool connOk = false; |
||||||
|
for(int i = 0; i < 2; i++) { |
||||||
|
// Try twice, in case the other instance is just starting up
|
||||||
|
socket.connectToServer(socketName); |
||||||
|
connOk = socket.waitForConnected(timeout/2); |
||||||
|
if (connOk || i) |
||||||
|
break; |
||||||
|
int ms = 250; |
||||||
|
#if defined(Q_OS_WIN) |
||||||
|
Sleep(DWORD(ms)); |
||||||
|
#else |
||||||
|
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; |
||||||
|
nanosleep(&ts, NULL); |
||||||
|
#endif |
||||||
|
} |
||||||
|
if (!connOk) |
||||||
|
return false; |
||||||
|
|
||||||
|
QByteArray uMsg(message.toUtf8()); |
||||||
|
QDataStream ds(&socket); |
||||||
|
ds.writeBytes(uMsg.constData(), uMsg.size()); |
||||||
|
bool res = socket.waitForBytesWritten(timeout); |
||||||
|
res &= socket.waitForReadyRead(timeout); // wait for ack
|
||||||
|
res &= (socket.read(qstrlen(ack)) == ack); |
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void QtLocalPeer::receiveConnection() |
||||||
|
{ |
||||||
|
QLocalSocket* socket = server->nextPendingConnection(); |
||||||
|
if (!socket) |
||||||
|
return; |
||||||
|
|
||||||
|
while (socket->bytesAvailable() < (int)sizeof(quint32)) |
||||||
|
socket->waitForReadyRead(); |
||||||
|
QDataStream ds(socket); |
||||||
|
QByteArray uMsg; |
||||||
|
quint32 remaining; |
||||||
|
ds >> remaining; |
||||||
|
uMsg.resize(remaining); |
||||||
|
int got = 0; |
||||||
|
char* uMsgBuf = uMsg.data(); |
||||||
|
do { |
||||||
|
got = ds.readRawData(uMsgBuf, remaining); |
||||||
|
remaining -= got; |
||||||
|
uMsgBuf += got; |
||||||
|
} while (remaining && got >= 0 && socket->waitForReadyRead(2000)); |
||||||
|
if (got < 0) { |
||||||
|
qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString(); |
||||||
|
delete socket; |
||||||
|
return; |
||||||
|
} |
||||||
|
QString message(QString::fromUtf8(uMsg)); |
||||||
|
socket->write(ack, qstrlen(ack)); |
||||||
|
socket->waitForBytesWritten(1000); |
||||||
|
delete socket; |
||||||
|
emit messageReceived(message); //### (might take a long time to return)
|
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
|
||||||
|
#include <QtNetwork/QLocalServer> |
||||||
|
#include <QtNetwork/QLocalSocket> |
||||||
|
#include <QtCore/QDir> |
||||||
|
|
||||||
|
namespace QtLP_Private { |
||||||
|
#include "qtlockedfile.h" |
||||||
|
} |
||||||
|
|
||||||
|
class QtLocalPeer : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); |
||||||
|
bool isClient(); |
||||||
|
bool sendMessage(const QString &message, int timeout); |
||||||
|
QString applicationId() const |
||||||
|
{ return id; } |
||||||
|
|
||||||
|
Q_SIGNALS: |
||||||
|
void messageReceived(const QString &message); |
||||||
|
|
||||||
|
protected Q_SLOTS: |
||||||
|
void receiveConnection(); |
||||||
|
|
||||||
|
protected: |
||||||
|
QString id; |
||||||
|
QString socketName; |
||||||
|
QLocalServer* server; |
||||||
|
QtLP_Private::QtLockedFile lockFile; |
||||||
|
|
||||||
|
private: |
||||||
|
static const char* ack; |
||||||
|
}; |
@ -0,0 +1,199 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#include "qtlockedfile.h" |
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QtLockedFile |
||||||
|
|
||||||
|
\brief The QtLockedFile class extends QFile with advisory locking |
||||||
|
functions. |
||||||
|
|
||||||
|
A file may be locked in read or write mode. Multiple instances of |
||||||
|
\e QtLockedFile, created in multiple processes running on the same |
||||||
|
machine, may have a file locked in read mode. Exactly one instance |
||||||
|
may have it locked in write mode. A read and a write lock cannot |
||||||
|
exist simultaneously on the same file. |
||||||
|
|
||||||
|
The file locks are advisory. This means that nothing prevents |
||||||
|
another process from manipulating a locked file using QFile or |
||||||
|
file system functions offered by the OS. Serialization is only |
||||||
|
guaranteed if all processes that access the file use |
||||||
|
QLockedFile. Also, while holding a lock on a file, a process |
||||||
|
must not open the same file again (through any API), or locks |
||||||
|
can be unexpectedly lost. |
||||||
|
|
||||||
|
The lock provided by an instance of \e QtLockedFile is released |
||||||
|
whenever the program terminates. This is true even when the |
||||||
|
program crashes and no destructors are called. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*! \enum QtLockedFile::LockMode
|
||||||
|
|
||||||
|
This enum describes the available lock modes. |
||||||
|
|
||||||
|
\value ReadLock A read lock. |
||||||
|
\value WriteLock A write lock. |
||||||
|
\value NoLock Neither a read lock nor a write lock. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs an unlocked \e QtLockedFile object. This constructor |
||||||
|
behaves in the same way as \e QFile::QFile(). |
||||||
|
|
||||||
|
\sa QFile::QFile() |
||||||
|
*/ |
||||||
|
QtLockedFile::QtLockedFile() |
||||||
|
: QFile() |
||||||
|
{ |
||||||
|
#ifdef Q_OS_WIN |
||||||
|
wmutex = 0; |
||||||
|
rmutex = 0; |
||||||
|
#endif |
||||||
|
m_lock_mode = NoLock; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs an unlocked QtLockedFile object with file \a name. This |
||||||
|
constructor behaves in the same way as \e QFile::QFile(const |
||||||
|
QString&). |
||||||
|
|
||||||
|
\sa QFile::QFile() |
||||||
|
*/ |
||||||
|
QtLockedFile::QtLockedFile(const QString &name) |
||||||
|
: QFile(name) |
||||||
|
{ |
||||||
|
#ifdef Q_OS_WIN |
||||||
|
wmutex = 0; |
||||||
|
rmutex = 0; |
||||||
|
#endif |
||||||
|
m_lock_mode = NoLock; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
Opens the file in OpenMode \a mode. |
||||||
|
|
||||||
|
This is identical to QFile::open(), with the one exception that the |
||||||
|
Truncate mode flag is disallowed. Truncation would conflict with the |
||||||
|
advisory file locking, since the file would be modified before the |
||||||
|
write lock is obtained. If truncation is required, use resize(0) |
||||||
|
after obtaining the write lock. |
||||||
|
|
||||||
|
Returns true if successful; otherwise false. |
||||||
|
|
||||||
|
\sa QFile::open(), QFile::resize() |
||||||
|
*/ |
||||||
|
bool QtLockedFile::open(OpenMode mode) |
||||||
|
{ |
||||||
|
if (mode & QIODevice::Truncate) { |
||||||
|
qWarning("QtLockedFile::open(): Truncate mode not allowed."); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return QFile::open(mode); |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns \e true if this object has a in read or write lock; |
||||||
|
otherwise returns \e false. |
||||||
|
|
||||||
|
\sa lockMode() |
||||||
|
*/ |
||||||
|
bool QtLockedFile::isLocked() const |
||||||
|
{ |
||||||
|
return m_lock_mode != NoLock; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the type of lock currently held by this object, or \e |
||||||
|
QtLockedFile::NoLock. |
||||||
|
|
||||||
|
\sa isLocked() |
||||||
|
*/ |
||||||
|
QtLockedFile::LockMode QtLockedFile::lockMode() const |
||||||
|
{ |
||||||
|
return m_lock_mode; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool QtLockedFile::lock(LockMode mode, bool block = true) |
||||||
|
|
||||||
|
Obtains a lock of type \a mode. The file must be opened before it |
||||||
|
can be locked. |
||||||
|
|
||||||
|
If \a block is true, this function will block until the lock is |
||||||
|
aquired. If \a block is false, this function returns \e false |
||||||
|
immediately if the lock cannot be aquired. |
||||||
|
|
||||||
|
If this object already has a lock of type \a mode, this function |
||||||
|
returns \e true immediately. If this object has a lock of a |
||||||
|
different type than \a mode, the lock is first released and then a |
||||||
|
new lock is obtained. |
||||||
|
|
||||||
|
This function returns \e true if, after it executes, the file is |
||||||
|
locked by this object, and \e false otherwise. |
||||||
|
|
||||||
|
\sa unlock(), isLocked(), lockMode() |
||||||
|
*/ |
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool QtLockedFile::unlock() |
||||||
|
|
||||||
|
Releases a lock. |
||||||
|
|
||||||
|
If the object has no lock, this function returns immediately. |
||||||
|
|
||||||
|
This function returns \e true if, after it executes, the file is |
||||||
|
not locked by this object, and \e false otherwise. |
||||||
|
|
||||||
|
\sa lock(), isLocked(), lockMode() |
||||||
|
*/ |
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QtLockedFile::~QtLockedFile() |
||||||
|
|
||||||
|
Destroys the \e QtLockedFile object. If any locks were held, they |
||||||
|
are released. |
||||||
|
*/ |
@ -0,0 +1,101 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#ifndef QTLOCKEDFILE_H |
||||||
|
#define QTLOCKEDFILE_H |
||||||
|
|
||||||
|
#include <QtCore/QFile> |
||||||
|
#ifdef Q_OS_WIN |
||||||
|
#include <QtCore/QVector> |
||||||
|
#endif |
||||||
|
|
||||||
|
#if defined(Q_WS_WIN) |
||||||
|
# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) |
||||||
|
# define QT_QTLOCKEDFILE_EXPORT |
||||||
|
# elif defined(QT_QTLOCKEDFILE_IMPORT) |
||||||
|
# if defined(QT_QTLOCKEDFILE_EXPORT) |
||||||
|
# undef QT_QTLOCKEDFILE_EXPORT |
||||||
|
# endif |
||||||
|
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) |
||||||
|
# elif defined(QT_QTLOCKEDFILE_EXPORT) |
||||||
|
# undef QT_QTLOCKEDFILE_EXPORT |
||||||
|
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) |
||||||
|
# endif |
||||||
|
#else |
||||||
|
# define QT_QTLOCKEDFILE_EXPORT |
||||||
|
#endif |
||||||
|
|
||||||
|
class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile |
||||||
|
{ |
||||||
|
public: |
||||||
|
enum LockMode { NoLock = 0, ReadLock, WriteLock }; |
||||||
|
|
||||||
|
QtLockedFile(); |
||||||
|
QtLockedFile(const QString &name); |
||||||
|
~QtLockedFile(); |
||||||
|
|
||||||
|
bool open(OpenMode mode); |
||||||
|
|
||||||
|
bool lock(LockMode mode, bool block = true); |
||||||
|
bool unlock(); |
||||||
|
bool isLocked() const; |
||||||
|
LockMode lockMode() const; |
||||||
|
|
||||||
|
private: |
||||||
|
#ifdef Q_OS_WIN |
||||||
|
Qt::HANDLE wmutex; |
||||||
|
Qt::HANDLE rmutex; |
||||||
|
QVector<Qt::HANDLE> rmutexes; |
||||||
|
QString mutexname; |
||||||
|
|
||||||
|
Qt::HANDLE getMutexHandle(int idx, bool doCreate); |
||||||
|
bool waitMutex(Qt::HANDLE mutex, bool doBlock); |
||||||
|
|
||||||
|
#endif |
||||||
|
LockMode m_lock_mode; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,121 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
#include <errno.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <fcntl.h> |
||||||
|
|
||||||
|
#include "qtlockedfile.h" |
||||||
|
|
||||||
|
bool QtLockedFile::lock(LockMode mode, bool block) |
||||||
|
{ |
||||||
|
if (!isOpen()) { |
||||||
|
qWarning("QtLockedFile::lock(): file is not opened"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (mode == NoLock) |
||||||
|
return unlock(); |
||||||
|
|
||||||
|
if (mode == m_lock_mode) |
||||||
|
return true; |
||||||
|
|
||||||
|
if (m_lock_mode != NoLock) |
||||||
|
unlock(); |
||||||
|
|
||||||
|
struct flock fl; |
||||||
|
fl.l_whence = SEEK_SET; |
||||||
|
fl.l_start = 0; |
||||||
|
fl.l_len = 0; |
||||||
|
fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; |
||||||
|
int cmd = block ? F_SETLKW : F_SETLK; |
||||||
|
int ret = fcntl(handle(), cmd, &fl); |
||||||
|
|
||||||
|
if (ret == -1) { |
||||||
|
if (errno != EINTR && errno != EAGAIN) |
||||||
|
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
m_lock_mode = mode; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool QtLockedFile::unlock() |
||||||
|
{ |
||||||
|
if (!isOpen()) { |
||||||
|
qWarning("QtLockedFile::unlock(): file is not opened"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (!isLocked()) |
||||||
|
return true; |
||||||
|
|
||||||
|
struct flock fl; |
||||||
|
fl.l_whence = SEEK_SET; |
||||||
|
fl.l_start = 0; |
||||||
|
fl.l_len = 0; |
||||||
|
fl.l_type = F_UNLCK; |
||||||
|
int ret = fcntl(handle(), F_SETLKW, &fl); |
||||||
|
|
||||||
|
if (ret == -1) { |
||||||
|
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
m_lock_mode = NoLock; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
QtLockedFile::~QtLockedFile() |
||||||
|
{ |
||||||
|
if (isOpen()) |
||||||
|
unlock(); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,213 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#include "qtlockedfile.h" |
||||||
|
#include <qt_windows.h> |
||||||
|
#include <QtCore/QFileInfo> |
||||||
|
|
||||||
|
#define MUTEX_PREFIX "QtLockedFile mutex " |
||||||
|
// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
|
||||||
|
#define MAX_READERS MAXIMUM_WAIT_OBJECTS |
||||||
|
|
||||||
|
Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) |
||||||
|
{ |
||||||
|
if (mutexname.isEmpty()) { |
||||||
|
QFileInfo fi(*this); |
||||||
|
mutexname = QString::fromLatin1(MUTEX_PREFIX) |
||||||
|
+ fi.absoluteFilePath().toLower(); |
||||||
|
} |
||||||
|
QString mname(mutexname); |
||||||
|
if (idx >= 0) |
||||||
|
mname += QString::number(idx); |
||||||
|
|
||||||
|
Qt::HANDLE mutex; |
||||||
|
if (doCreate) { |
||||||
|
QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, |
||||||
|
{ mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); |
||||||
|
if (!mutex) { |
||||||
|
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, |
||||||
|
{ mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); |
||||||
|
if (!mutex) { |
||||||
|
if (GetLastError() != ERROR_FILE_NOT_FOUND) |
||||||
|
qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
||||||
|
return mutex; |
||||||
|
} |
||||||
|
|
||||||
|
bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) |
||||||
|
{ |
||||||
|
Q_ASSERT(mutex); |
||||||
|
DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); |
||||||
|
switch (res) { |
||||||
|
case WAIT_OBJECT_0: |
||||||
|
case WAIT_ABANDONED: |
||||||
|
return true; |
||||||
|
break; |
||||||
|
case WAIT_TIMEOUT: |
||||||
|
break; |
||||||
|
default: |
||||||
|
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool QtLockedFile::lock(LockMode mode, bool block) |
||||||
|
{ |
||||||
|
if (!isOpen()) { |
||||||
|
qWarning("QtLockedFile::lock(): file is not opened"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (mode == NoLock) |
||||||
|
return unlock(); |
||||||
|
|
||||||
|
if (mode == m_lock_mode) |
||||||
|
return true; |
||||||
|
|
||||||
|
if (m_lock_mode != NoLock) |
||||||
|
unlock(); |
||||||
|
|
||||||
|
if (!wmutex && !(wmutex = getMutexHandle(-1, true))) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (!waitMutex(wmutex, block)) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (mode == ReadLock) { |
||||||
|
int idx = 0; |
||||||
|
for (; idx < MAX_READERS; idx++) { |
||||||
|
rmutex = getMutexHandle(idx, false); |
||||||
|
if (!rmutex || waitMutex(rmutex, false)) |
||||||
|
break; |
||||||
|
CloseHandle(rmutex); |
||||||
|
} |
||||||
|
bool ok = true; |
||||||
|
if (idx >= MAX_READERS) { |
||||||
|
qWarning("QtLockedFile::lock(): too many readers"); |
||||||
|
rmutex = 0; |
||||||
|
ok = false; |
||||||
|
} |
||||||
|
else if (!rmutex) { |
||||||
|
rmutex = getMutexHandle(idx, true); |
||||||
|
if (!rmutex || !waitMutex(rmutex, false)) |
||||||
|
ok = false; |
||||||
|
} |
||||||
|
if (!ok && rmutex) { |
||||||
|
CloseHandle(rmutex); |
||||||
|
rmutex = 0; |
||||||
|
} |
||||||
|
ReleaseMutex(wmutex); |
||||||
|
if (!ok) |
||||||
|
return false; |
||||||
|
} |
||||||
|
else { |
||||||
|
Q_ASSERT(rmutexes.isEmpty()); |
||||||
|
for (int i = 0; i < MAX_READERS; i++) { |
||||||
|
Qt::HANDLE mutex = getMutexHandle(i, false); |
||||||
|
if (mutex) |
||||||
|
rmutexes.append(mutex); |
||||||
|
} |
||||||
|
if (rmutexes.size()) { |
||||||
|
DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), |
||||||
|
TRUE, block ? INFINITE : 0); |
||||||
|
if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { |
||||||
|
if (res != WAIT_TIMEOUT) |
||||||
|
qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); |
||||||
|
m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
|
||||||
|
unlock(); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
m_lock_mode = mode; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool QtLockedFile::unlock() |
||||||
|
{ |
||||||
|
if (!isOpen()) { |
||||||
|
qWarning("QtLockedFile::unlock(): file is not opened"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (!isLocked()) |
||||||
|
return true; |
||||||
|
|
||||||
|
if (m_lock_mode == ReadLock) { |
||||||
|
ReleaseMutex(rmutex); |
||||||
|
CloseHandle(rmutex); |
||||||
|
rmutex = 0; |
||||||
|
} |
||||||
|
else { |
||||||
|
foreach(Qt::HANDLE mutex, rmutexes) { |
||||||
|
ReleaseMutex(mutex); |
||||||
|
CloseHandle(mutex); |
||||||
|
} |
||||||
|
rmutexes.clear(); |
||||||
|
ReleaseMutex(wmutex); |
||||||
|
} |
||||||
|
|
||||||
|
m_lock_mode = QtLockedFile::NoLock; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
QtLockedFile::~QtLockedFile() |
||||||
|
{ |
||||||
|
if (isOpen()) |
||||||
|
unlock(); |
||||||
|
if (wmutex) |
||||||
|
CloseHandle(wmutex); |
||||||
|
} |
@ -0,0 +1,351 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
|
||||||
|
#include "qtsingleapplication.h" |
||||||
|
#include "qtlocalpeer.h" |
||||||
|
#include <QtGui/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() or sendMessage() to |
||||||
|
find out if another instance of this application is already |
||||||
|
running. Startup parameters (e.g. the name of the file the user |
||||||
|
wanted this new instance to open) can be passed to the running |
||||||
|
instance in the sendMessage() function. |
||||||
|
|
||||||
|
If isRunning() or sendMessage() returns false, it means that no |
||||||
|
other instance is running, and this instance has assumed the role |
||||||
|
as the running instance. 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 application receives messages from |
||||||
|
another instance of the same application. |
||||||
|
|
||||||
|
If isRunning() or sendMessage() returns true, another instance is |
||||||
|
already running, and the application should terminate or enter |
||||||
|
client mode. |
||||||
|
|
||||||
|
If 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. |
||||||
|
|
||||||
|
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 0; |
||||||
|
|
||||||
|
MyMainWidget mmw; |
||||||
|
|
||||||
|
app.setActivationWindow(&mmw); |
||||||
|
|
||||||
|
mmw.show(); |
||||||
|
return app.exec(); |
||||||
|
} |
||||||
|
\endcode |
||||||
|
|
||||||
|
Once this QtSingleApplication instance is destroyed(for example, |
||||||
|
when the user quits), 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); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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 |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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 |
||||||
|
*/ |
@ -0,0 +1,105 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
|
||||||
|
#include <QtGui/QApplication> |
||||||
|
|
||||||
|
class QtLocalPeer; |
||||||
|
|
||||||
|
#if defined(Q_WS_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); |
||||||
|
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 |
||||||
|
|
||||||
|
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; |
||||||
|
}; |
@ -0,0 +1,16 @@ |
|||||||
|
include(../common.pri) |
||||||
|
INCLUDEPATH += $$PWD |
||||||
|
DEPENDPATH += $$PWD |
||||||
|
QT *= network |
||||||
|
|
||||||
|
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 |
||||||
|
} |
@ -0,0 +1,155 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
|
||||||
|
#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() |
||||||
|
*/ |
@ -0,0 +1,73 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** All rights reserved. |
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com) |
||||||
|
** |
||||||
|
** This file is part of a Qt Solutions component. |
||||||
|
** |
||||||
|
** Commercial Usage |
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in |
||||||
|
** accordance with the Qt Solutions Commercial License Agreement provided |
||||||
|
** with the Software or, alternatively, in accordance with the terms |
||||||
|
** contained in a written agreement between you and Nokia. |
||||||
|
** |
||||||
|
** GNU Lesser General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser |
||||||
|
** General Public License version 2.1 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements |
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
** |
||||||
|
** In addition, as a special exception, Nokia gives you certain |
||||||
|
** additional rights. These rights are described in the Nokia Qt LGPL |
||||||
|
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this |
||||||
|
** package. |
||||||
|
** |
||||||
|
** GNU General Public License Usage |
||||||
|
** Alternatively, this file may be used under the terms of the GNU |
||||||
|
** General Public License version 3.0 as published by the Free Software |
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the |
||||||
|
** packaging of this file. Please review the following information to |
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be |
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
** |
||||||
|
** Please note Third Party Software included with Qt Solutions may impose |
||||||
|
** additional restrictions and it is the user's responsibility to ensure |
||||||
|
** that they have met the licensing requirements of the GPL, LGPL, or Qt |
||||||
|
** Solutions Commercial license and the relevant license of the Third |
||||||
|
** Party Software they are using. |
||||||
|
** |
||||||
|
** If you are unsure which license is appropriate for your use, please |
||||||
|
** contact Nokia at qt-info@nokia.com. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
|
||||||
|
#include <QtCore/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; |
||||||
|
}; |
@ -0,0 +1,10 @@ |
|||||||
|
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