File indexing completed on 2024-05-19 05:52:41
0001 // The MIT License (MIT) 0002 // 0003 // Copyright (c) Itay Grudev 2015 - 2018 0004 // 0005 // Permission is hereby granted, free of charge, to any person obtaining a copy 0006 // of this software and associated documentation files (the "Software"), to deal 0007 // in the Software without restriction, including without limitation the rights 0008 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0009 // copies of the Software, and to permit persons to whom the Software is 0010 // furnished to do so, subject to the following conditions: 0011 // 0012 // The above copyright notice and this permission notice shall be included in 0013 // all copies or substantial portions of the Software. 0014 // 0015 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0016 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0017 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0018 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0019 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 0020 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 0021 // THE SOFTWARE. 0022 0023 #pragma once 0024 0025 #include <QtCore/QtGlobal> 0026 #include <QtNetwork/QLocalSocket> 0027 0028 #ifndef QAPPLICATION_CLASS 0029 #define QAPPLICATION_CLASS QCoreApplication 0030 #endif 0031 0032 #include QT_STRINGIFY(QAPPLICATION_CLASS) 0033 0034 class SingleApplicationPrivate; 0035 0036 /** 0037 * @brief The SingleApplication class handles multiple instances of the same 0038 * Application 0039 * @see QCoreApplication 0040 */ 0041 class SingleApplication : public QAPPLICATION_CLASS 0042 { 0043 Q_OBJECT 0044 0045 using app_t = QAPPLICATION_CLASS; 0046 0047 public: 0048 /** 0049 * @brief Mode of operation of SingleApplication. 0050 * Whether the block should be user-wide or system-wide and whether the 0051 * primary instance should be notified when a secondary instance had been 0052 * started. 0053 * @note Operating system can restrict the shared memory blocks to the same 0054 * user, in which case the User/System modes will have no effect and the 0055 * block will be user wide. 0056 * @enum 0057 */ 0058 enum Mode { 0059 User = 1 << 0, 0060 System = 1 << 1, 0061 SecondaryNotification = 1 << 2, 0062 ExcludeAppVersion = 1 << 3, 0063 ExcludeAppPath = 1 << 4 0064 }; 0065 Q_DECLARE_FLAGS(Options, Mode) 0066 0067 /** 0068 * @brief Intitializes a SingleApplication instance with argc command line 0069 * arguments in argv 0070 * @arg {int &} argc - Number of arguments in argv 0071 * @arg {const char *[]} argv - Supplied command line arguments 0072 * @arg {bool} allowSecondary - Whether to start the instance as secondary 0073 * if there is already a primary instance. 0074 * @arg {Mode} mode - Whether for the SingleApplication block to be applied 0075 * User wide or System wide. 0076 * @arg {int} timeout - Timeout to wait in milliseconds. 0077 * @note argc and argv may be changed as Qt removes arguments that it 0078 * recognizes 0079 * @note Mode::SecondaryNotification only works if set on both the primary 0080 * instance and the secondary instance. 0081 * @note The timeout is just a hint for the maximum time of blocking 0082 * operations. It does not guarantee that the SingleApplication 0083 * initialisation will be completed in given time, though is a good hint. 0084 * Usually 4*timeout would be the worst case (fail) scenario. 0085 * @see See the corresponding QAPPLICATION_CLASS constructor for reference 0086 */ 0087 explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000, const QString &userData = {} ); 0088 ~SingleApplication() override; 0089 0090 /** 0091 * @brief Returns if the instance is the primary instance 0092 * @returns {bool} 0093 */ 0094 bool isPrimary() const; 0095 0096 /** 0097 * @brief Returns if the instance is a secondary instance 0098 * @returns {bool} 0099 */ 0100 bool isSecondary() const; 0101 0102 /** 0103 * @brief Returns a unique identifier for the current instance 0104 * @returns {qint32} 0105 */ 0106 quint32 instanceId() const; 0107 0108 /** 0109 * @brief Returns the process ID (PID) of the primary instance 0110 * @returns {qint64} 0111 */ 0112 qint64 primaryPid() const; 0113 0114 /** 0115 * @brief Returns the username of the user running the primary instance 0116 * @returns {QString} 0117 */ 0118 QString primaryUser() const; 0119 0120 /** 0121 * @brief Returns the username of the current user 0122 * @returns {QString} 0123 */ 0124 QString currentUser() const; 0125 0126 /** 0127 * @brief Mode of operation of sendMessage. 0128 * @enum 0129 */ 0130 enum SendMode { 0131 NonBlocking, /** Do not wait for the primary instance termination and return immediately */ 0132 BlockUntilPrimaryExit, /** Wait until the primary instance is terminated */ 0133 }; 0134 0135 /** 0136 * @brief Sends a message to the primary instance. Returns true on success. 0137 * @param {int} timeout - Timeout for connecting 0138 * @param {SendMode} sendMode - Mode of operation. 0139 * @returns {bool} 0140 * @note sendMessage() will return false if invoked from the primary 0141 * instance. 0142 */ 0143 bool sendMessage( const QByteArray &message, int timeout = 100, SendMode sendMode = NonBlocking ); 0144 0145 /** 0146 * @brief Get the set user data. 0147 * @returns {QStringList} 0148 */ 0149 QStringList userData() const; 0150 0151 Q_SIGNALS: 0152 void instanceStarted(); 0153 void receivedMessage( quint32 instanceId, QByteArray message ); 0154 0155 private: 0156 SingleApplicationPrivate *d_ptr; 0157 Q_DECLARE_PRIVATE(SingleApplication) 0158 void abortSafely(); 0159 }; 0160 0161 Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options) 0162