1 // The MIT License (MIT) 2 // 3 // Copyright (c) Itay Grudev 2015 - 2020 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 23 // 24 // W A R N I N G !!! 25 // ----------------- 26 // 27 // This is a modified version of SingleApplication, 28 // The original version is at: 29 // 30 // https://github.com/itay-grudev/SingleApplication 31 // 32 // 33 34 #ifndef SINGLECOREAPPLICATION_H 35 #define SINGLECOREAPPLICATION_H 36 37 #include <QtGlobal> 38 #include <QCoreApplication> 39 #include <QFlags> 40 #include <QByteArray> 41 42 class SingleCoreApplicationPrivate; 43 44 /** 45 * @brief The SingleCoreApplication class handles multiple instances of the same Application 46 * @see QCoreApplication 47 */ 48 class SingleCoreApplication : public QCoreApplication { 49 Q_OBJECT 50 51 typedef QCoreApplication app_t; 52 53 public: 54 /** 55 * @brief Mode of operation of SingleCoreApplication. 56 * Whether the block should be user-wide or system-wide and whether the 57 * primary instance should be notified when a secondary instance had been 58 * started. 59 * @note Operating system can restrict the shared memory blocks to the same 60 * user, in which case the User/System modes will have no effect and the 61 * block will be user wide. 62 * @enum 63 */ 64 enum Mode { 65 User = 1 << 0, 66 System = 1 << 1, 67 SecondaryNotification = 1 << 2, 68 ExcludeAppVersion = 1 << 3, 69 ExcludeAppPath = 1 << 4 70 }; 71 Q_DECLARE_FLAGS(Options, Mode) 72 73 /** 74 * @brief Intitializes a SingleCoreApplication instance with argc command line 75 * arguments in argv 76 * @arg {int &} argc - Number of arguments in argv 77 * @arg {const char *[]} argv - Supplied command line arguments 78 * @arg {bool} allowSecondary - Whether to start the instance as secondary 79 * if there is already a primary instance. 80 * @arg {Mode} mode - Whether for the SingleCoreApplication block to be applied 81 * User wide or System wide. 82 * @arg {int} timeout - Timeout to wait in milliseconds. 83 * @note argc and argv may be changed as Qt removes arguments that it 84 * recognizes 85 * @note Mode::SecondaryNotification only works if set on both the primary 86 * instance and the secondary instance. 87 * @note The timeout is just a hint for the maximum time of blocking 88 * operations. It does not guarantee that the SingleCoreApplication 89 * initialisation will be completed in given time, though is a good hint. 90 * Usually 4*timeout would be the worst case (fail) scenario. 91 */ 92 explicit SingleCoreApplication(int &argc, char *argv[], const bool allowSecondary = false, const Options options = Mode::User, const int timeout = 1000); 93 ~SingleCoreApplication() override; 94 95 /** 96 * @brief Returns if the instance is the primary instance 97 * @returns {bool} 98 */ 99 bool isPrimary(); 100 101 /** 102 * @brief Returns if the instance is a secondary instance 103 * @returns {bool} 104 */ 105 bool isSecondary(); 106 107 /** 108 * @brief Returns a unique identifier for the current instance 109 * @returns {qint32} 110 */ 111 quint32 instanceId(); 112 113 /** 114 * @brief Returns the process ID (PID) of the primary instance 115 * @returns {qint64} 116 */ 117 qint64 primaryPid(); 118 119 /** 120 * @brief Returns the username of the user running the primary instance 121 * @returns {QString} 122 */ 123 QString primaryUser(); 124 125 /** 126 * @brief Returns the username of the current user 127 * @returns {QString} 128 */ 129 QString currentUser(); 130 131 /** 132 * @brief Sends a message to the primary instance. Returns true on success. 133 * @param {int} timeout - Timeout for connecting 134 * @returns {bool} 135 * @note sendMessage() will return false if invoked from the primary 136 * instance. 137 */ 138 bool sendMessage(const QByteArray &message, const int timeout = 1000); 139 140 signals: 141 void instanceStarted(); 142 void receivedMessage(quint32 instanceId, QByteArray message); 143 144 private: 145 SingleCoreApplicationPrivate *d_ptr; 146 Q_DECLARE_PRIVATE(SingleCoreApplication) 147 void abortSafely(); 148 }; 149 150 Q_DECLARE_OPERATORS_FOR_FLAGS(SingleCoreApplication::Options) 151 152 #endif // SINGLECOREAPPLICATION_H 153