Passing custom events over single instance IPC
This commit is contained in:
parent
ee4f152349
commit
64c960fdb3
|
@ -983,8 +983,9 @@ DOS_API int DOS_CALL dos_qdeclarative_qmlregistersingletontype(const QmlRegister
|
||||||
|
|
||||||
/// \brief Create a new SingleInstance class
|
/// \brief Create a new SingleInstance class
|
||||||
/// \param uniqueName The UTF-8 string for QLocalServer name
|
/// \param uniqueName The UTF-8 string for QLocalServer name
|
||||||
|
/// \param eventStr A custom string to be passed to the already running instance if detected
|
||||||
/// \note The returned SingleInstance should be freed using the dos_singleinstance_delete() function
|
/// \note The returned SingleInstance should be freed using the dos_singleinstance_delete() function
|
||||||
DOS_API DosSingleInstance *DOS_CALL dos_singleinstance_create(const char *uniqueName);
|
DOS_API DosSingleInstance *DOS_CALL dos_singleinstance_create(const char *uniqueName, const char *eventStr);
|
||||||
|
|
||||||
/// \brief Returns bool indicating whether this is the first instance or not
|
/// \brief Returns bool indicating whether this is the first instance or not
|
||||||
/// \returns true if this is the first instance
|
/// \returns true if this is the first instance
|
||||||
|
|
|
@ -10,13 +10,19 @@ class SingleInstance : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SingleInstance(const QString &uniqueName, QObject *parent = nullptr);
|
// uniqueName - the name of named pipe
|
||||||
|
// eventStr - optional event to send if another instance is detected
|
||||||
|
explicit SingleInstance(const QString &uniqueName, const QString &eventStr, QObject *parent = nullptr);
|
||||||
~SingleInstance() override;
|
~SingleInstance() override;
|
||||||
|
|
||||||
bool isFirstInstance() const;
|
bool isFirstInstance() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void secondInstanceDetected();
|
void secondInstanceDetected();
|
||||||
|
void eventReceived(const QString &eventStr);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleNewConnection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLocalServer *m_localServer;
|
QLocalServer *m_localServer;
|
||||||
|
|
|
@ -1333,9 +1333,9 @@ char *dos_qurl_replaceHostAndAddPath(char* url, char* newScheme, char* newHost,
|
||||||
return convert_to_cstring(newQurl.toString());
|
return convert_to_cstring(newQurl.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
DosSingleInstance *dos_singleinstance_create(const char *uniqueName)
|
DosSingleInstance *dos_singleinstance_create(const char *uniqueName, const char *eventStr)
|
||||||
{
|
{
|
||||||
return new SingleInstance(QString::fromUtf8(uniqueName));
|
return new SingleInstance(QString::fromUtf8(uniqueName), QString::fromUtf8(eventStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void dos_singleinstance_delete(DosSingleInstance *vptr)
|
void dos_singleinstance_delete(DosSingleInstance *vptr)
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
#include <QLocalServer>
|
#include <QLocalServer>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
|
|
||||||
SingleInstance::SingleInstance(const QString &uniqueName, QObject *parent)
|
namespace {
|
||||||
|
const int ReadWriteTimeoutMs = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleInstance::SingleInstance(const QString &uniqueName, const QString &eventStr, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_localServer(new QLocalServer(this))
|
, m_localServer(new QLocalServer(this))
|
||||||
{
|
{
|
||||||
|
@ -19,7 +23,7 @@ SingleInstance::SingleInstance(const QString &uniqueName, QObject *parent)
|
||||||
// the first instance start will be delayed by this timeout (ms) to ensure there are no other instances.
|
// the first instance start will be delayed by this timeout (ms) to ensure there are no other instances.
|
||||||
// note: this is an ad-hoc timeout value selected based on prior experience.
|
// note: this is an ad-hoc timeout value selected based on prior experience.
|
||||||
if (!localSocket.waitForConnected(100)) {
|
if (!localSocket.waitForConnected(100)) {
|
||||||
connect(m_localServer, &QLocalServer::newConnection, this, &SingleInstance::secondInstanceDetected);
|
connect(m_localServer, &QLocalServer::newConnection, this, &SingleInstance::handleNewConnection);
|
||||||
// on *nix a crashed process will leave /tmp/xyz file preventing to start a new server.
|
// on *nix a crashed process will leave /tmp/xyz file preventing to start a new server.
|
||||||
// therefore, if we were unable to connect, then we assume the server died and we need to clean up.
|
// therefore, if we were unable to connect, then we assume the server died and we need to clean up.
|
||||||
// p.s. on Windows, this function does nothing.
|
// p.s. on Windows, this function does nothing.
|
||||||
|
@ -27,6 +31,9 @@ SingleInstance::SingleInstance(const QString &uniqueName, QObject *parent)
|
||||||
if (!m_localServer->listen(socketName)) {
|
if (!m_localServer->listen(socketName)) {
|
||||||
qWarning() << "QLocalServer::listen(" << socketName << ") failed";
|
qWarning() << "QLocalServer::listen(" << socketName << ") failed";
|
||||||
}
|
}
|
||||||
|
} else if (!eventStr.isEmpty()) {
|
||||||
|
localSocket.write(eventStr.toUtf8() + '\n');
|
||||||
|
localSocket.waitForBytesWritten(ReadWriteTimeoutMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,3 +48,16 @@ bool SingleInstance::isFirstInstance() const
|
||||||
{
|
{
|
||||||
return m_localServer->isListening();
|
return m_localServer->isListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SingleInstance::handleNewConnection()
|
||||||
|
{
|
||||||
|
emit secondInstanceDetected();
|
||||||
|
|
||||||
|
auto socket = m_localServer->nextPendingConnection();
|
||||||
|
if (socket->waitForReadyRead(ReadWriteTimeoutMs) && socket->canReadLine()) {
|
||||||
|
auto event = socket->readLine();
|
||||||
|
emit eventReceived(QString::fromUtf8(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
socket->deleteLater();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue