From f236032cf988950c12ebd8ff5e3cd3f9778ea55a Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Thu, 10 Dec 2020 19:18:00 -0500 Subject: [PATCH] Allow adding unique userdata to instances --- README.md | 4 ++-- singleapplication.cpp | 12 +++++++++++- singleapplication.h | 8 +++++++- singleapplication_p.cpp | 19 ++++++++++++++++--- singleapplication_p.h | 3 +++ 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d20756f..457ab33 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ API ### Members ```cpp -SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 ) +SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100, QString userData = QString() ) ``` Depending on whether `allowSecondary` is set, this constructor may terminate @@ -163,7 +163,7 @@ can be specified to set whether the SingleApplication block should work user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be used to notify the primary instance whenever a secondary instance had been started (disabled by default). `timeout` specifies the maximum time in -milliseconds to wait for blocking operations. +milliseconds to wait for blocking operations. Setting `userData` provides additional data that will isolate this instance from other instances that do not have the same (or any) user data set. *__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it recognizes.* diff --git a/singleapplication.cpp b/singleapplication.cpp index a4f842e..276ceee 100644 --- a/singleapplication.cpp +++ b/singleapplication.cpp @@ -36,7 +36,7 @@ * @param options Optional flags to toggle specific behaviour * @param timeout Maximum time blocking functions are allowed during app load */ -SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout ) +SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout, QString userData ) : app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) ) { Q_D( SingleApplication ); @@ -51,6 +51,10 @@ SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSeconda // Store the current mode of the program d->options = options; + // Add any unique user data + if ( ! userData.isEmpty() ) + d->addAppData( userData ); + // Generating an application ID used for identifying the shared memory // block and QLocalServer d->genBlockServerName(); @@ -262,3 +266,9 @@ void SingleApplication::abortSafely() delete d; ::exit( EXIT_FAILURE ); } + +QStringList SingleApplication::userData() +{ + Q_D( SingleApplication ); + return d->appData(); +} diff --git a/singleapplication.h b/singleapplication.h index cba6a91..d39a661 100644 --- a/singleapplication.h +++ b/singleapplication.h @@ -85,7 +85,7 @@ public: * Usually 4*timeout would be the worst case (fail) scenario. * @see See the corresponding QAPPLICATION_CLASS constructor for reference */ - explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 ); + explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000, QString userData = QString() ); ~SingleApplication() override; /** @@ -133,6 +133,12 @@ public: */ bool sendMessage( const QByteArray &message, int timeout = 100 ); + /** + * @brief Get the set user data. + * @returns {QStringList} + */ + QStringList userData(); + Q_SIGNALS: void instanceStarted(); void receivedMessage( quint32 instanceId, QByteArray message ); diff --git a/singleapplication_p.cpp b/singleapplication_p.cpp index 65859c7..1ab58c2 100644 --- a/singleapplication_p.cpp +++ b/singleapplication_p.cpp @@ -136,6 +136,9 @@ void SingleApplicationPrivate::genBlockServerName() appData.addData( SingleApplication::app_t::organizationName().toUtf8() ); appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() ); + if ( ! appDataList.isEmpty() ) + appData.addData( appDataList.join( "" ).toUtf8() ); + if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){ appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() ); } @@ -186,9 +189,9 @@ void SingleApplicationPrivate::startPrimary() // Restrict access to the socket according to the // SingleApplication::Mode::User flag on User level or no restrictions if( options & SingleApplication::Mode::User ){ - server->setSocketOptions( QLocalServer::UserAccessOption ); + server->setSocketOptions( QLocalServer::UserAccessOption ); } else { - server->setSocketOptions( QLocalServer::WorldAccessOption ); + server->setSocketOptions( QLocalServer::WorldAccessOption ); } server->listen( blockServerName ); @@ -225,7 +228,7 @@ bool SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType conne if( socket->state() != QLocalSocket::ConnectedState ){ while( true ){ - randomSleep(); + randomSleep(); if( socket->state() != QLocalSocket::ConnectingState ) socket->connectToServer( blockServerName ); @@ -470,3 +473,13 @@ void SingleApplicationPrivate::randomSleep() QThread::msleep( 8 + static_cast ( static_cast ( qrand() ) / RAND_MAX * 10 )); #endif } + +void SingleApplicationPrivate::addAppData(const QString &data) +{ + appDataList.push_back(data); +} + +QStringList SingleApplicationPrivate::appData() const +{ + return appDataList; +} diff --git a/singleapplication_p.h b/singleapplication_p.h index d0703e3..c49a46d 100644 --- a/singleapplication_p.h +++ b/singleapplication_p.h @@ -82,6 +82,8 @@ public: void readInitMessageHeader(QLocalSocket *socket); void readInitMessageBody(QLocalSocket *socket); static void randomSleep(); + void addAppData(const QString &data); + QStringList appData() const; SingleApplication *q_ptr; QSharedMemory *memory; @@ -91,6 +93,7 @@ public: QString blockServerName; SingleApplication::Options options; QMap connectionMap; + QStringList appDataList; public Q_SLOTS: void slotConnectionEstablished();