Line data Source code
1 : // SPDX-FileCopyrightText: 2016 Anne Jan Brouwer
2 : // SPDX-License-Identifier: GPL-3.0-or-later
3 : #include "singleapplication.h"
4 : #include <QLocalSocket>
5 : #include <utility>
6 : #ifdef QT_DEBUG
7 : #include "debughelper.h"
8 : #endif
9 :
10 : /**
11 : * @brief SingleApplication::SingleApplication this replaces the QApplication
12 : * allowing for local socket based communications.
13 : * @param argc
14 : * @param argv
15 : * @param uniqueKey
16 : */
17 0 : SingleApplication::SingleApplication(int &argc, char *argv[], QString uniqueKey)
18 0 : : QApplication(argc, argv), _uniqueKey(std::move(uniqueKey)) {
19 0 : sharedMemory.setKey(_uniqueKey);
20 0 : if (sharedMemory.attach()) {
21 0 : _isRunning = true;
22 : } else {
23 0 : _isRunning = false;
24 : // create shared memory.
25 0 : if (!sharedMemory.create(1)) {
26 : #ifdef QT_DEBUG
27 : dbg() << "Unable to create single instance.";
28 : #endif
29 : return;
30 : }
31 : // create local server and listen to incomming messages from other
32 : // instances.
33 0 : localServer.reset(new QLocalServer(this));
34 0 : connect(localServer.data(), &QLocalServer::newConnection, this,
35 0 : &SingleApplication::receiveMessage);
36 0 : localServer->listen(_uniqueKey);
37 : }
38 0 : }
39 :
40 : // public slots.
41 :
42 : /**
43 : * @brief SingleApplication::receiveMessage we have received (a command line)
44 : * message.
45 : */
46 0 : void SingleApplication::receiveMessage() {
47 0 : QLocalSocket *localSocket = localServer->nextPendingConnection();
48 0 : if (!localSocket->waitForReadyRead(timeout)) {
49 : #ifdef QT_DEBUG
50 : dbg() << localSocket->errorString().toLatin1();
51 : #endif
52 0 : return;
53 : }
54 0 : QByteArray byteArray = localSocket->readAll();
55 0 : QString message = QString::fromUtf8(byteArray.constData());
56 0 : emit messageAvailable(message);
57 0 : localSocket->disconnectFromServer();
58 : }
59 :
60 : // public functions.
61 : /**
62 : * @brief SingleApplication::isRunning is there already a QtPass instance
63 : * running, to check wether to be server or client.
64 : * @return
65 : */
66 0 : auto SingleApplication::isRunning() -> bool { return _isRunning; }
67 :
68 : /**
69 : * @brief SingleApplication::sendMessage send a message (from commandline) to an
70 : * already running QtPass instance.
71 : * @param message
72 : * @return
73 : */
74 0 : auto SingleApplication::sendMessage(const QString &message) -> bool {
75 0 : if (!_isRunning) {
76 : return false;
77 : }
78 0 : QLocalSocket localSocket(this);
79 0 : localSocket.connectToServer(_uniqueKey, QIODevice::WriteOnly);
80 0 : if (!localSocket.waitForConnected(timeout)) {
81 : #ifdef QT_DEBUG
82 : dbg() << localSocket.errorString().toLatin1();
83 : #endif
84 : return false;
85 : }
86 : QByteArray payload = message.toUtf8();
87 0 : if (payload.isEmpty()) {
88 0 : payload = QByteArray(1, '\0');
89 : }
90 0 : localSocket.write(payload);
91 0 : if (!localSocket.waitForBytesWritten(timeout)) {
92 : #ifdef QT_DEBUG
93 : dbg() << localSocket.errorString().toLatin1();
94 : #endif
95 : return false;
96 : }
97 0 : localSocket.disconnectFromServer();
98 : return true;
99 0 : }
|