diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-06-16 22:30:45 +0200 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-06-25 11:34:17 +0200 |
commit | 6a7d28d1b5564db6c45460de680282e45751d11a (patch) | |
tree | 9c1f321075969f2e63f22d90957e2e6832b42f8c /third_party | |
parent | Show some spaces in the community sidebar (diff) | |
download | nheko-6a7d28d1b5564db6c45460de680282e45751d11a.tar.xz |
update SingleApplication
Diffstat (limited to 'third_party')
29 files changed, 1050 insertions, 63 deletions
diff --git a/third_party/SingleApplication-3.3.0/.github/FUNDING.yml b/third_party/SingleApplication-3.3.0/.github/FUNDING.yml new file mode 100644 index 00000000..3ca4d97a --- /dev/null +++ b/third_party/SingleApplication-3.3.0/.github/FUNDING.yml @@ -0,0 +1 @@ +github: itay-grudev diff --git a/third_party/SingleApplication-3.3.0/.github/workflows/build-cmake.yml b/third_party/SingleApplication-3.3.0/.github/workflows/build-cmake.yml new file mode 100644 index 00000000..6344b504 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/.github/workflows/build-cmake.yml @@ -0,0 +1,56 @@ +name: "CI: Build Test" + +on: [push, pull_request] + +jobs: + build: + + strategy: + matrix: + qt_version: [5.12.6, 5.13.2, 5.14.0, 5.15.0, 6.0.0] + platform: [ubuntu-20.04, windows-latest, macos-latest] + include: + - qt_version: 6.0.0 + additional_arguments: -D QT_DEFAULT_MAJOR_VERSION=6 + - platform: ubuntu-20.04 + CXXFLAGS: -Wall -Wextra -pedantic -Werror + - platform: macos-latest + CXXFLAGS: -Wall -Wextra -pedantic -Werror + - platform: windows-latest + CXXFLAGS: /W4 /WX + + runs-on: ${{ matrix.platform }} + env: + CXXFLAGS: ${{ matrix.CXXFLAGS }} + + steps: + - uses: actions/checkout@v2.3.4 + + - name: Install Qt + uses: jurplel/install-qt-action@v2.11.1 + with: + version: ${{ matrix.qt_version }} + + - name: cmake + run: cmake . ${{ matrix.additional_arguments }} + + - name: cmake build + run: cmake --build . + + - name: Build example - basic (cmake) + working-directory: examples/basic/ + run: | + cmake . ${{ matrix.additional_arguments }} + cmake --build . + + - name: Build example - calculator (cmake) + working-directory: examples/calculator/ + run: | + cmake . ${{ matrix.additional_arguments }} + cmake --build . + + - name: Build example - sending_arguments (cmake) + working-directory: examples/sending_arguments/ + run: | + cmake . ${{ matrix.additional_arguments }} + cmake --build . diff --git a/third_party/SingleApplication-3.2.0-dc8042b/.gitignore b/third_party/SingleApplication-3.3.0/.gitignore index 35533fe8..35533fe8 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/.gitignore +++ b/third_party/SingleApplication-3.3.0/.gitignore diff --git a/third_party/SingleApplication-3.2.0-dc8042b/CHANGELOG.md b/third_party/SingleApplication-3.3.0/CHANGELOG.md index e2ba290e..51669b90 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/CHANGELOG.md +++ b/third_party/SingleApplication-3.3.0/CHANGELOG.md @@ -3,6 +3,12 @@ Changelog If by accident I have forgotten to credit someone in the CHANGELOG, email me and I will fix it. + +__3.3.0__ +--------- + +* Fixed message fragmentation issue causing crashes and incorrectly and inconsistently received messages. - _Nils Jeisecke_ + __3.2.0__ --------- diff --git a/third_party/SingleApplication-3.2.0-dc8042b/CMakeLists.txt b/third_party/SingleApplication-3.3.0/CMakeLists.txt index ae1b1439..ae1b1439 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/CMakeLists.txt +++ b/third_party/SingleApplication-3.3.0/CMakeLists.txt diff --git a/third_party/SingleApplication-3.2.0-dc8042b/LICENSE b/third_party/SingleApplication-3.3.0/LICENSE index a82e5a68..a82e5a68 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/LICENSE +++ b/third_party/SingleApplication-3.3.0/LICENSE diff --git a/third_party/SingleApplication-3.2.0-dc8042b/README.md b/third_party/SingleApplication-3.3.0/README.md index 457ab339..457ab339 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/README.md +++ b/third_party/SingleApplication-3.3.0/README.md diff --git a/third_party/SingleApplication-3.2.0-dc8042b/SingleApplication b/third_party/SingleApplication-3.3.0/SingleApplication index 8ead1a42..8ead1a42 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/SingleApplication +++ b/third_party/SingleApplication-3.3.0/SingleApplication diff --git a/third_party/SingleApplication-3.2.0-dc8042b/Windows.md b/third_party/SingleApplication-3.3.0/Windows.md index 13c52da0..13c52da0 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/Windows.md +++ b/third_party/SingleApplication-3.3.0/Windows.md diff --git a/third_party/SingleApplication-3.3.0/examples/basic/CMakeLists.txt b/third_party/SingleApplication-3.3.0/examples/basic/CMakeLists.txt new file mode 100644 index 00000000..c1429230 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/basic/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.7.0) + +project(basic LANGUAGES CXX) + +# SingleApplication base class +set(QAPPLICATION_CLASS QCoreApplication) +add_subdirectory(../.. SingleApplication) + +add_executable(basic main.cpp) + +target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication) + diff --git a/third_party/SingleApplication-3.3.0/examples/basic/basic.pro b/third_party/SingleApplication-3.3.0/examples/basic/basic.pro new file mode 100755 index 00000000..b7af16cf --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/basic/basic.pro @@ -0,0 +1,5 @@ +# Single Application implementation +include(../../singleapplication.pri) +DEFINES += QAPPLICATION_CLASS=QCoreApplication + +SOURCES += main.cpp diff --git a/third_party/SingleApplication-3.3.0/examples/basic/main.cpp b/third_party/SingleApplication-3.3.0/examples/basic/main.cpp new file mode 100755 index 00000000..b2092c6d --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/basic/main.cpp @@ -0,0 +1,10 @@ +#include <singleapplication.h> + +int main(int argc, char *argv[]) +{ + SingleApplication app( argc, argv ); + + qWarning() << "Started a new instance"; + + return app.exec(); +} diff --git a/third_party/SingleApplication-3.3.0/examples/calculator/CMakeLists.txt b/third_party/SingleApplication-3.3.0/examples/calculator/CMakeLists.txt new file mode 100644 index 00000000..82305f04 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/calculator/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.7.0) + +project(calculator LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +# SingleApplication base class +set(QAPPLICATION_CLASS QApplication) +add_subdirectory(../.. SingleApplication) + +find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core REQUIRED) + +add_executable(${PROJECT_NAME} + button.h + calculator.h + button.cpp + calculator.cpp + main.cpp +) + +target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication) diff --git a/third_party/SingleApplication-3.3.0/examples/calculator/button.cpp b/third_party/SingleApplication-3.3.0/examples/calculator/button.cpp new file mode 100644 index 00000000..d6cca0a0 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/calculator/button.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtWidgets> + +#include "button.h" + +//! [0] +Button::Button(const QString &text, QWidget *parent) + : QToolButton(parent) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + setText(text); +} +//! [0] + +//! [1] +QSize Button::sizeHint() const +//! [1] //! [2] +{ + QSize size = QToolButton::sizeHint(); + size.rheight() += 20; + size.rwidth() = qMax(size.width(), size.height()); + return size; +} +//! [2] diff --git a/third_party/SingleApplication-3.3.0/examples/calculator/button.h b/third_party/SingleApplication-3.3.0/examples/calculator/button.h new file mode 100644 index 00000000..2c014c7b --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/calculator/button.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BUTTON_H +#define BUTTON_H + +#include <QToolButton> + +//! [0] +class Button : public QToolButton +{ + Q_OBJECT + +public: + explicit Button(const QString &text, QWidget *parent = 0); + + QSize sizeHint() const Q_DECL_OVERRIDE; +}; +//! [0] + +#endif diff --git a/third_party/SingleApplication-3.3.0/examples/calculator/calculator.cpp b/third_party/SingleApplication-3.3.0/examples/calculator/calculator.cpp new file mode 100644 index 00000000..3d34c2a7 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/calculator/calculator.cpp @@ -0,0 +1,406 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtWidgets> + +#include <cmath> + +#include "button.h" +#include "calculator.h" + +//! [0] +Calculator::Calculator(QWidget *parent) + : QWidget(parent) +{ + sumInMemory = 0.0; + sumSoFar = 0.0; + factorSoFar = 0.0; + waitingForOperand = true; +//! [0] + +//! [1] + display = new QLineEdit("0"); +//! [1] //! [2] + display->setReadOnly(true); + display->setAlignment(Qt::AlignRight); + display->setMaxLength(15); + + QFont font = display->font(); + font.setPointSize(font.pointSize() + 8); + display->setFont(font); +//! [2] + +//! [4] + for (int i = 0; i < NumDigitButtons; ++i) { + digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked())); + } + + Button *pointButton = createButton(".", SLOT(pointClicked())); + Button *changeSignButton = createButton("\302\261", SLOT(changeSignClicked())); + + Button *backspaceButton = createButton("Backspace", SLOT(backspaceClicked())); + Button *clearButton = createButton("Clear", SLOT(clear())); + Button *clearAllButton = createButton("Clear All", SLOT(clearAll())); + + Button *clearMemoryButton = createButton("MC", SLOT(clearMemory())); + Button *readMemoryButton = createButton("MR", SLOT(readMemory())); + Button *setMemoryButton = createButton("MS", SLOT(setMemory())); + Button *addToMemoryButton = createButton("M+", SLOT(addToMemory())); + + Button *divisionButton = createButton("\303\267", SLOT(multiplicativeOperatorClicked())); + Button *timesButton = createButton("\303\227", SLOT(multiplicativeOperatorClicked())); + Button *minusButton = createButton("-", SLOT(additiveOperatorClicked())); + Button *plusButton = createButton("+", SLOT(additiveOperatorClicked())); + + Button *squareRootButton = createButton("Sqrt", SLOT(unaryOperatorClicked())); + Button *powerButton = createButton("x\302\262", SLOT(unaryOperatorClicked())); + Button *reciprocalButton = createButton("1/x", SLOT(unaryOperatorClicked())); + Button *equalButton = createButton("=", SLOT(equalClicked())); +//! [4] + +//! [5] + QGridLayout *mainLayout = new QGridLayout; +//! [5] //! [6] + mainLayout->setSizeConstraint(QLayout::SetFixedSize); + mainLayout->addWidget(display, 0, 0, 1, 6); + mainLayout->addWidget(backspaceButton, 1, 0, 1, 2); + mainLayout->addWidget(clearButton, 1, 2, 1, 2); + mainLayout->addWidget(clearAllButton, 1, 4, 1, 2); + + mainLayout->addWidget(clearMemoryButton, 2, 0); + mainLayout->addWidget(readMemoryButton, 3, 0); + mainLayout->addWidget(setMemoryButton, 4, 0); + mainLayout->addWidget(addToMemoryButton, 5, 0); + + for (int i = 1; i < NumDigitButtons; ++i) { + int row = ((9 - i) / 3) + 2; + int column = ((i - 1) % 3) + 1; + mainLayout->addWidget(digitButtons[i], row, column); + } + + mainLayout->addWidget(digitButtons[0], 5, 1); + mainLayout->addWidget(pointButton, 5, 2); + mainLayout->addWidget(changeSignButton, 5, 3); + + mainLayout->addWidget(divisionButton, 2, 4); + mainLayout->addWidget(timesButton, 3, 4); + mainLayout->addWidget(minusButton, 4, 4); + mainLayout->addWidget(plusButton, 5, 4); + + mainLayout->addWidget(squareRootButton, 2, 5); + mainLayout->addWidget(powerButton, 3, 5); + mainLayout->addWidget(reciprocalButton, 4, 5); + mainLayout->addWidget(equalButton, 5, 5); + setLayout(mainLayout); + + setWindowTitle("Calculator"); +} +//! [6] + +//! [7] +void Calculator::digitClicked() +{ + Button *clickedButton = qobject_cast<Button *>(sender()); + int digitValue = clickedButton->text().toInt(); + if (display->text() == "0" && digitValue == 0.0) + return; + + if (waitingForOperand) { + display->clear(); + waitingForOperand = false; + } + display->setText(display->text() + QString::number(digitValue)); +} +//! [7] + +//! [8] +void Calculator::unaryOperatorClicked() +//! [8] //! [9] +{ + Button *clickedButton = qobject_cast<Button *>(sender()); + QString clickedOperator = clickedButton->text(); + double operand = display->text().toDouble(); + double result = 0.0; + + if (clickedOperator == "Sqrt") { + if (operand < 0.0) { + abortOperation(); + return; + } + result = std::sqrt(operand); + } else if (clickedOperator == "x\302\262") { + result = std::pow(operand, 2.0); + } else if (clickedOperator == "1/x") { + if (operand == 0.0) { + abortOperation(); + return; + } + result = 1.0 / operand; + } + display->setText(QString::number(result)); + waitingForOperand = true; +} +//! [9] + +//! [10] +void Calculator::additiveOperatorClicked() +//! [10] //! [11] +{ + Button *clickedButton = qobject_cast<Button *>(sender()); + QString clickedOperator = clickedButton->text(); + double operand = display->text().toDouble(); + +//! [11] //! [12] + if (!pendingMultiplicativeOperator.isEmpty()) { +//! [12] //! [13] + if (!calculate(operand, pendingMultiplicativeOperator)) { + abortOperation(); + return; + } + display->setText(QString::number(factorSoFar)); + operand = factorSoFar; + factorSoFar = 0.0; + pendingMultiplicativeOperator.clear(); + } + +//! [13] //! [14] + if (!pendingAdditiveOperator.isEmpty()) { +//! [14] //! [15] + if (!calculate(operand, pendingAdditiveOperator)) { + abortOperation(); + return; + } + display->setText(QString::number(sumSoFar)); + } else { + sumSoFar = operand; + } + +//! [15] //! [16] + pendingAdditiveOperator = clickedOperator; +//! [16] //! [17] + waitingForOperand = true; +} +//! [17] + +//! [18] +void Calculator::multiplicativeOperatorClicked() +{ + Button *clickedButton = qobject_cast<Button *>(sender()); + QString clickedOperator = clickedButton->text(); + double operand = display->text().toDouble(); + + if (!pendingMultiplicativeOperator.isEmpty()) { + if (!calculate(operand, pendingMultiplicativeOperator)) { + abortOperation(); + return; + } + display->setText(QString::number(factorSoFar)); + } else { + factorSoFar = operand; + } + + pendingMultiplicativeOperator = clickedOperator; + waitingForOperand = true; +} +//! [18] + +//! [20] +void Calculator::equalClicked() +{ + double operand = display->text().toDouble(); + + if (!pendingMultiplicativeOperator.isEmpty()) { + if (!calculate(operand, pendingMultiplicativeOperator)) { + abortOperation(); + return; + } + operand = factorSoFar; + factorSoFar = 0.0; + pendingMultiplicativeOperator.clear(); + } + if (!pendingAdditiveOperator.isEmpty()) { + if (!calculate(operand, pendingAdditiveOperator)) { + abortOperation(); + return; + } + pendingAdditiveOperator.clear(); + } else { + sumSoFar = operand; + } + + display->setText(QString::number(sumSoFar)); + sumSoFar = 0.0; + waitingForOperand = true; +} +//! [20] + +//! [22] +void Calculator::pointClicked() +{ + if (waitingForOperand) + display->setText("0"); + if (!display->text().contains('.')) + display->setText(display->text() + "."); + waitingForOperand = false; +} +//! [22] + +//! [24] +void Calculator::changeSignClicked() +{ + QString text = display->text(); + double value = text.toDouble(); + + if (value > 0.0) { + text.prepend("-"); + } else if (value < 0.0) { + text.remove(0, 1); + } + display->setText(text); +} +//! [24] + +//! [26] +void Calculator::backspaceClicked() +{ + if (waitingForOperand) + return; + + QString text = display->text(); + text.chop(1); + if (text.isEmpty()) { + text = "0"; + waitingForOperand = true; + } + display->setText(text); +} +//! [26] + +//! [28] +void Calculator::clear() +{ + if (waitingForOperand) + return; + + display->setText("0"); + waitingForOperand = true; +} +//! [28] + +//! [30] +void Calculator::clearAll() +{ + sumSoFar = 0.0; + factorSoFar = 0.0; + pendingAdditiveOperator.clear(); + pendingMultiplicativeOperator.clear(); + display->setText("0"); + waitingForOperand = true; +} +//! [30] + +//! [32] +void Calculator::clearMemory() +{ + sumInMemory = 0.0; +} + +void Calculator::readMemory() +{ + display->setText(QString::number(sumInMemory)); + waitingForOperand = true; +} + +void Calculator::setMemory() +{ + equalClicked(); + sumInMemory = display->text().toDouble(); +} + +void Calculator::addToMemory() +{ + equalClicked(); + sumInMemory += display->text().toDouble(); +} +//! [32] +//! [34] +Button *Calculator::createButton(const QString &text, const char *member) +{ + Button *button = new Button(text); + connect(button, SIGNAL(clicked()), this, member); + return button; +} +//! [34] + +//! [36] +void Calculator::abortOperation() +{ + clearAll(); + display->setText("####"); +} +//! [36] + +//! [38] +bool Calculator::calculate(double rightOperand, const QString &pendingOperator) +{ + if (pendingOperator == "+") { + sumSoFar += rightOperand; + } else if (pendingOperator == "-") { + sumSoFar -= rightOperand; + } else if (pendingOperator == "\303\227") { + factorSoFar *= rightOperand; + } else if (pendingOperator == "\303\267") { + if (rightOperand == 0.0) + return false; + factorSoFar /= rightOperand; + } + return true; +} +//! [38] diff --git a/third_party/SingleApplication-3.3.0/examples/calculator/calculator.h b/third_party/SingleApplication-3.3.0/examples/calculator/calculator.h new file mode 100644 index 00000000..250a2f3e --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/calculator/calculator.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CALCULATOR_H +#define CALCULATOR_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QLineEdit; +QT_END_NAMESPACE +class Button; + +//! [0] +class Calculator : public QWidget +{ + Q_OBJECT + +public: + Calculator(QWidget *parent = 0); + +private slots: + void digitClicked(); + void unaryOperatorClicked(); + void additiveOperatorClicked(); + void multiplicativeOperatorClicked(); + void equalClicked(); + void pointClicked(); + void changeSignClicked(); + void backspaceClicked(); + void clear(); + void clearAll(); + void clearMemory(); + void readMemory(); + void setMemory(); + void addToMemory(); +//! [0] + +//! [1] +private: +//! [1] //! [2] + Button *createButton(const QString &text, const char *member); + void abortOperation(); + bool calculate(double rightOperand, const QString &pendingOperator); +//! [2] + +//! [3] + double sumInMemory; +//! [3] //! [4] + double sumSoFar; +//! [4] //! [5] + double factorSoFar; +//! [5] //! [6] + QString pendingAdditiveOperator; +//! [6] //! [7] + QString pendingMultiplicativeOperator; +//! [7] //! [8] + bool waitingForOperand; +//! [8] + +//! [9] + QLineEdit *display; +//! [9] //! [10] + + enum { NumDigitButtons = 10 }; + Button *digitButtons[NumDigitButtons]; +}; +//! [10] + +#endif diff --git a/third_party/SingleApplication-3.3.0/examples/calculator/calculator.pro b/third_party/SingleApplication-3.3.0/examples/calculator/calculator.pro new file mode 100644 index 00000000..8f132609 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/calculator/calculator.pro @@ -0,0 +1,11 @@ +QT += widgets + +HEADERS = button.h \ + calculator.h +SOURCES = button.cpp \ + calculator.cpp \ + main.cpp + +# Single Application implementation +include(../../singleapplication.pri) +DEFINES += QAPPLICATION_CLASS=QApplication diff --git a/third_party/SingleApplication-3.3.0/examples/calculator/main.cpp b/third_party/SingleApplication-3.3.0/examples/calculator/main.cpp new file mode 100644 index 00000000..d45438f4 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/calculator/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include <singleapplication.h> + +#include "calculator.h" + +int main(int argc, char *argv[]) +{ + SingleApplication app(argc, argv); + + Calculator calc; + + QObject::connect( &app, &SingleApplication::instanceStarted, [ &calc ]() { + calc.raise(); + calc.activateWindow(); + }); + + calc.show(); + + return app.exec(); +} diff --git a/third_party/SingleApplication-3.3.0/examples/sending_arguments/CMakeLists.txt b/third_party/SingleApplication-3.3.0/examples/sending_arguments/CMakeLists.txt new file mode 100644 index 00000000..2cc55975 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/sending_arguments/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.7.0) + +project(sending_arguments LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +# SingleApplication base class +set(QAPPLICATION_CLASS QCoreApplication) +add_subdirectory(../.. SingleApplication) + +find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core REQUIRED) + +add_executable(${PROJECT_NAME} + main.cpp + messagereceiver.cpp + messagereceiver.h + main.cpp +) + +target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication) diff --git a/third_party/SingleApplication-3.3.0/examples/sending_arguments/main.cpp b/third_party/SingleApplication-3.3.0/examples/sending_arguments/main.cpp new file mode 100755 index 00000000..a9d34dd9 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/sending_arguments/main.cpp @@ -0,0 +1,28 @@ +#include <singleapplication.h> +#include "messagereceiver.h" + +int main(int argc, char *argv[]) +{ + // Allow secondary instances + SingleApplication app( argc, argv, true ); + + MessageReceiver msgReceiver; + + // If this is a secondary instance + if( app.isSecondary() ) { + app.sendMessage( app.arguments().join(' ').toUtf8() ); + qDebug() << "App already running."; + qDebug() << "Primary instance PID: " << app.primaryPid(); + qDebug() << "Primary instance user: " << app.primaryUser(); + return 0; + } else { + QObject::connect( + &app, + &SingleApplication::receivedMessage, + &msgReceiver, + &MessageReceiver::receivedMessage + ); + } + + return app.exec(); +} diff --git a/third_party/SingleApplication-3.3.0/examples/sending_arguments/messagereceiver.cpp b/third_party/SingleApplication-3.3.0/examples/sending_arguments/messagereceiver.cpp new file mode 100644 index 00000000..0560b072 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/sending_arguments/messagereceiver.cpp @@ -0,0 +1,12 @@ +#include <QDebug> +#include "messagereceiver.h" + +MessageReceiver::MessageReceiver(QObject *parent) : QObject(parent) +{ +} + +void MessageReceiver::receivedMessage(int instanceId, QByteArray message) +{ + qDebug() << "Received message from instance: " << instanceId; + qDebug() << "Message Text: " << message; +} diff --git a/third_party/SingleApplication-3.3.0/examples/sending_arguments/messagereceiver.h b/third_party/SingleApplication-3.3.0/examples/sending_arguments/messagereceiver.h new file mode 100644 index 00000000..50a970c8 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/sending_arguments/messagereceiver.h @@ -0,0 +1,15 @@ +#ifndef MESSAGERECEIVER_H +#define MESSAGERECEIVER_H + +#include <QObject> + +class MessageReceiver : public QObject +{ + Q_OBJECT +public: + explicit MessageReceiver(QObject *parent = 0); +public slots: + void receivedMessage( int instanceId, QByteArray message ); +}; + +#endif // MESSAGERECEIVER_H diff --git a/third_party/SingleApplication-3.3.0/examples/sending_arguments/sending_arguments.pro b/third_party/SingleApplication-3.3.0/examples/sending_arguments/sending_arguments.pro new file mode 100755 index 00000000..897636a9 --- /dev/null +++ b/third_party/SingleApplication-3.3.0/examples/sending_arguments/sending_arguments.pro @@ -0,0 +1,9 @@ +# Single Application implementation +include(../../singleapplication.pri) +DEFINES += QAPPLICATION_CLASS=QCoreApplication + +SOURCES += main.cpp \ + messagereceiver.cpp + +HEADERS += \ + messagereceiver.h diff --git a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication.cpp b/third_party/SingleApplication-3.3.0/singleapplication.cpp index 276ceee9..09e264ef 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication.cpp +++ b/third_party/SingleApplication-3.3.0/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, QString userData ) +SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout, const QString &userData ) : app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) ) { Q_D( SingleApplication ); @@ -172,9 +172,9 @@ SingleApplication::~SingleApplication() * Checks if the current application instance is primary. * @return Returns true if the instance is primary, false otherwise. */ -bool SingleApplication::isPrimary() +bool SingleApplication::isPrimary() const { - Q_D( SingleApplication ); + Q_D( const SingleApplication ); return d->server != nullptr; } @@ -182,9 +182,9 @@ bool SingleApplication::isPrimary() * Checks if the current application instance is secondary. * @return Returns true if the instance is secondary, false otherwise. */ -bool SingleApplication::isSecondary() +bool SingleApplication::isSecondary() const { - Q_D( SingleApplication ); + Q_D( const SingleApplication ); return d->server == nullptr; } @@ -194,9 +194,9 @@ bool SingleApplication::isSecondary() * only incremented afterwards. * @return Returns a unique instance id. */ -quint32 SingleApplication::instanceId() +quint32 SingleApplication::instanceId() const { - Q_D( SingleApplication ); + Q_D( const SingleApplication ); return d->instanceNumber; } @@ -206,9 +206,9 @@ quint32 SingleApplication::instanceId() * specific APIs. * @return Returns the primary instance PID. */ -qint64 SingleApplication::primaryPid() +qint64 SingleApplication::primaryPid() const { - Q_D( SingleApplication ); + Q_D( const SingleApplication ); return d->primaryPid(); } @@ -216,9 +216,9 @@ qint64 SingleApplication::primaryPid() * Returns the username the primary instance is running as. * @return Returns the username the primary instance is running as. */ -QString SingleApplication::primaryUser() +QString SingleApplication::primaryUser() const { - Q_D( SingleApplication ); + Q_D( const SingleApplication ); return d->primaryUser(); } @@ -226,7 +226,7 @@ QString SingleApplication::primaryUser() * Returns the username the current instance is running as. * @return Returns the username the current instance is running as. */ -QString SingleApplication::currentUser() +QString SingleApplication::currentUser() const { return SingleApplicationPrivate::getUsername(); } @@ -248,10 +248,7 @@ bool SingleApplication::sendMessage( const QByteArray &message, int timeout ) if( ! d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect ) ) return false; - d->socket->write( message ); - bool dataWritten = d->socket->waitForBytesWritten( timeout ); - d->socket->flush(); - return dataWritten; + return d->writeConfirmedMessage( timeout, message ); } /** @@ -267,8 +264,8 @@ void SingleApplication::abortSafely() ::exit( EXIT_FAILURE ); } -QStringList SingleApplication::userData() +QStringList SingleApplication::userData() const { - Q_D( SingleApplication ); + Q_D( const SingleApplication ); return d->appData(); } diff --git a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication.h b/third_party/SingleApplication-3.3.0/singleapplication.h index d39a6614..91cabf93 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication.h +++ b/third_party/SingleApplication-3.3.0/singleapplication.h @@ -85,44 +85,44 @@ 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, QString userData = QString() ); + explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000, const QString &userData = {} ); ~SingleApplication() override; /** * @brief Returns if the instance is the primary instance * @returns {bool} */ - bool isPrimary(); + bool isPrimary() const; /** * @brief Returns if the instance is a secondary instance * @returns {bool} */ - bool isSecondary(); + bool isSecondary() const; /** * @brief Returns a unique identifier for the current instance * @returns {qint32} */ - quint32 instanceId(); + quint32 instanceId() const; /** * @brief Returns the process ID (PID) of the primary instance * @returns {qint64} */ - qint64 primaryPid(); + qint64 primaryPid() const; /** * @brief Returns the username of the user running the primary instance * @returns {QString} */ - QString primaryUser(); + QString primaryUser() const; /** * @brief Returns the username of the current user * @returns {QString} */ - QString currentUser(); + QString currentUser() const; /** * @brief Sends a message to the primary instance. Returns true on success. @@ -137,7 +137,7 @@ public: * @brief Get the set user data. * @returns {QStringList} */ - QStringList userData(); + QStringList userData() const; Q_SIGNALS: void instanceStarted(); diff --git a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication.pri b/third_party/SingleApplication-3.3.0/singleapplication.pri index ae81f599..ae81f599 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication.pri +++ b/third_party/SingleApplication-3.3.0/singleapplication.pri diff --git a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication_p.cpp b/third_party/SingleApplication-3.3.0/singleapplication_p.cpp index 1ab58c23..13397282 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication_p.cpp +++ b/third_party/SingleApplication-3.3.0/singleapplication_p.cpp @@ -263,20 +263,46 @@ bool SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType conne #endif writeStream << checksum; - // The header indicates the message length that follows + return writeConfirmedMessage( static_cast<int>(msecs - time.elapsed()), initMsg ); +} + +void SingleApplicationPrivate::writeAck( QLocalSocket *sock ) { + sock->putChar('\n'); +} + +bool SingleApplicationPrivate::writeConfirmedMessage (int msecs, const QByteArray &msg) +{ + QElapsedTimer time; + time.start(); + + // Frame 1: The header indicates the message length that follows QByteArray header; QDataStream headerStream(&header, QIODevice::WriteOnly); #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) headerStream.setVersion(QDataStream::Qt_5_6); #endif - headerStream << static_cast <quint64>( initMsg.length() ); + headerStream << static_cast <quint64>( msg.length() ); - socket->write( header ); - socket->write( initMsg ); - bool result = socket->waitForBytesWritten( static_cast<int>(msecs - time.elapsed()) ); + if( ! writeConfirmedFrame( static_cast<int>(msecs - time.elapsed()), header )) + return false; + + // Frame 2: The message + return writeConfirmedFrame( static_cast<int>(msecs - time.elapsed()), msg ); +} + +bool SingleApplicationPrivate::writeConfirmedFrame( int msecs, const QByteArray &msg ) +{ + socket->write( msg ); socket->flush(); - return result; + + bool result = socket->waitForReadyRead( msecs ); // await ack byte + if (result) { + socket->read( 1 ); + return true; + } + + return false; } quint16 SingleApplicationPrivate::blockChecksum() const @@ -321,32 +347,36 @@ void SingleApplicationPrivate::slotConnectionEstablished() QLocalSocket *nextConnSocket = server->nextPendingConnection(); connectionMap.insert(nextConnSocket, ConnectionInfo()); - QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, + QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, this, [nextConnSocket, this](){ auto &info = connectionMap[nextConnSocket]; - Q_EMIT this->slotClientConnectionClosed( nextConnSocket, info.instanceId ); + this->slotClientConnectionClosed( nextConnSocket, info.instanceId ); } ); - QObject::connect(nextConnSocket, &QLocalSocket::disconnected, + QObject::connect(nextConnSocket, &QLocalSocket::disconnected, nextConnSocket, &QLocalSocket::deleteLater); + + QObject::connect(nextConnSocket, &QLocalSocket::destroyed, this, [nextConnSocket, this](){ connectionMap.remove(nextConnSocket); - nextConnSocket->deleteLater(); } ); - QObject::connect(nextConnSocket, &QLocalSocket::readyRead, + QObject::connect(nextConnSocket, &QLocalSocket::readyRead, this, [nextConnSocket, this](){ auto &info = connectionMap[nextConnSocket]; switch(info.stage){ - case StageHeader: - readInitMessageHeader(nextConnSocket); + case StageInitHeader: + readMessageHeader( nextConnSocket, StageInitBody ); break; - case StageBody: + case StageInitBody: readInitMessageBody(nextConnSocket); break; - case StageConnected: - Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId ); + case StageConnectedHeader: + readMessageHeader( nextConnSocket, StageConnectedBody ); + break; + case StageConnectedBody: + this->slotDataAvailable( nextConnSocket, info.instanceId ); break; default: break; @@ -355,7 +385,7 @@ void SingleApplicationPrivate::slotConnectionEstablished() ); } -void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock ) +void SingleApplicationPrivate::readMessageHeader( QLocalSocket *sock, SingleApplicationPrivate::ConnectionStage nextStage ) { if (!connectionMap.contains( sock )){ return; @@ -375,29 +405,35 @@ void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock ) quint64 msgLen = 0; headerStream >> msgLen; ConnectionInfo &info = connectionMap[sock]; - info.stage = StageBody; + info.stage = nextStage; info.msgLen = msgLen; - if ( sock->bytesAvailable() >= (qint64) msgLen ){ - readInitMessageBody( sock ); - } + writeAck( sock ); } -void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock ) +bool SingleApplicationPrivate::isFrameComplete( QLocalSocket *sock ) { - Q_Q(SingleApplication); - if (!connectionMap.contains( sock )){ - return; + return false; } ConnectionInfo &info = connectionMap[sock]; if( sock->bytesAvailable() < ( qint64 )info.msgLen ){ - return; + return false; } + return true; +} + +void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock ) +{ + Q_Q(SingleApplication); + + if( !isFrameComplete( sock ) ) + return; + // Read the message body - QByteArray msgBytes = sock->read(info.msgLen); + QByteArray msgBytes = sock->readAll(); QDataStream readStream(msgBytes); #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) @@ -437,8 +473,9 @@ void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock ) return; } + ConnectionInfo &info = connectionMap[sock]; info.instanceId = instanceId; - info.stage = StageConnected; + info.stage = StageConnectedHeader; if( connectionType == NewInstance || ( connectionType == SecondaryInstance && @@ -447,21 +484,28 @@ void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock ) Q_EMIT q->instanceStarted(); } - if (sock->bytesAvailable() > 0){ - Q_EMIT this->slotDataAvailable( sock, instanceId ); - } + writeAck( sock ); } void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId ) { Q_Q(SingleApplication); + + if ( !isFrameComplete( dataSocket ) ) + return; + Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() ); + + writeAck( dataSocket ); + + ConnectionInfo &info = connectionMap[dataSocket]; + info.stage = StageConnectedHeader; } void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId ) { if( closedSocket->bytesAvailable() > 0 ) - Q_EMIT slotDataAvailable( closedSocket, instanceId ); + slotDataAvailable( closedSocket, instanceId ); } void SingleApplicationPrivate::randomSleep() @@ -470,7 +514,7 @@ void SingleApplicationPrivate::randomSleep() QThread::msleep( QRandomGenerator::global()->bounded( 8u, 18u )); #else qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max() ); - QThread::msleep( 8 + static_cast <unsigned long>( static_cast <float>( qrand() ) / RAND_MAX * 10 )); + QThread::msleep( qrand() % 11 + 8); #endif } diff --git a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication_p.h b/third_party/SingleApplication-3.3.0/singleapplication_p.h index c49a46dd..58507cf3 100644 --- a/third_party/SingleApplication-3.2.0-dc8042b/singleapplication_p.h +++ b/third_party/SingleApplication-3.3.0/singleapplication_p.h @@ -61,9 +61,10 @@ public: Reconnect = 3 }; enum ConnectionStage : quint8 { - StageHeader = 0, - StageBody = 1, - StageConnected = 2, + StageInitHeader = 0, + StageInitBody = 1, + StageConnectedHeader = 2, + StageConnectedBody = 3, }; Q_DECLARE_PUBLIC(SingleApplication) @@ -79,8 +80,12 @@ public: quint16 blockChecksum() const; qint64 primaryPid() const; QString primaryUser() const; - void readInitMessageHeader(QLocalSocket *socket); + bool isFrameComplete(QLocalSocket *sock); + void readMessageHeader(QLocalSocket *socket, ConnectionStage nextStage); void readInitMessageBody(QLocalSocket *socket); + void writeAck(QLocalSocket *sock); + bool writeConfirmedFrame(int msecs, const QByteArray &msg); + bool writeConfirmedMessage(int msecs, const QByteArray &msg); static void randomSleep(); void addAppData(const QString &data); QStringList appData() const; |