Christophe Dumez
15 years ago
24 changed files with 1713 additions and 156 deletions
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
#include "qtlockedfile.h" |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
#include "qtsingleapplication.h" |
@ -0,0 +1,203 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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