// For license of this file, see /LICENSE.md. #include "miscellaneous/singleapplication.h" #include "definitions/definitions.h" #include #include #include SingleApplication::SingleApplication(const QString& id, int& argc, char** argv) : QApplication(argc, argv), m_id(id), m_server(new QLocalServer(this)) {} void SingleApplication::finish() { if (m_server->isListening()) { m_server->close(); } } bool SingleApplication::isOtherInstanceRunning(const QString& message) { QLocalSocket sck; sck.connectToServer(m_id); if (sck.waitForConnected(200)) { if (!message.isEmpty()) { QDataStream out(&sck); out.setVersion(QDataStream::Version::Qt_5_5); out << quint32(message.size()); out << message; sck.flush(); sck.waitForBytesWritten(200); } sck.disconnectFromServer(); sck.abort(); return true; } auto i_am_first = m_server->listen(m_id); if (i_am_first) { connect(m_server, &QLocalServer::newConnection, this, &SingleApplication::processMessageFromOtherInstance); } return !i_am_first; } bool SingleApplication::sendMessage(const QString& message) { return isOtherInstanceRunning(message); } void SingleApplication::processMessageFromOtherInstance() { auto* sck = m_server->nextPendingConnection(); if (sck == nullptr) { return; } quint32 block_size = 0; QEventLoop loop; QDataStream in(sck); in.setVersion(QDataStream::Version::Qt_5_5); connect(sck, &QLocalSocket::disconnected, sck, &QLocalSocket::deleteLater); connect(sck, &QLocalSocket::readyRead, this, [this, sck, &loop, &in, &block_size]() { if (block_size == 0) { if (sck->bytesAvailable() < int(sizeof(quint32))) { return; } in >> block_size; } if (sck->bytesAvailable() < block_size || in.atEnd()) { return; } QString dat; in >> dat; emit messageReceived(dat); loop.exit(); }); sck->flush(); loop.exec(); }