From 321418fcf8633009657d992092cc994680402ff6 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Fri, 9 Aug 2024 14:03:48 +0100 Subject: [PATCH] Improve handling of Qt-related warnings and errors (#7431) * Load .env from app dir * Use `OutputDebugStringA` on Windows * Improved string manipulation in logger and better use of OutputDebugStringA * Use noquote for path * Apply TLS setting after activation * Restart after activation * Move skip debug message to correct place * Only print settings path on create, not shown * Merge common and global libs * Reduce code duplication around constants, version, etc * Simplify sprintf code * Use snprintf * Add error test menu * Coverage for dotenv * Coverage for Logger * Add missing include * Add init when no Git SHA * Update ChangeLog * Add spellings * Set debugging on for release build * Remove unused variable * Remove bad comment * Fixed copyright date * Remove import * Move URL const back to GUI * Remove dead code and duplication * Fixed/ignored lint warnings --- ChangeLog | 1 + cspell.json | 7 ++ src/cmd/synergy-core/CMakeLists.txt | 1 - src/cmd/synergyc/CMakeLists.txt | 1 - src/cmd/synergyd/CMakeLists.txt | 2 - src/cmd/synergys/CMakeLists.txt | 1 - src/cmd/syntool/CMakeLists.txt | 1 - src/gui/CMakeLists.txt | 1 - src/gui/src/AboutDialog.cpp | 23 ++----- src/gui/src/AboutDialog.h | 3 +- src/gui/src/ActivationDialog.cpp | 4 +- src/gui/src/MainWindow.cpp | 68 ++++++++++++++----- src/gui/src/MainWindow.h | 8 ++- src/gui/src/MainWindowBase.ui | 24 ++++--- src/gui/src/SetupWizardBlocker.cpp | 3 +- src/gui/src/main.cpp | 19 ++++-- src/lib/CMakeLists.txt | 2 - src/lib/arch/win32/ArchMiscWindows.cpp | 2 +- src/lib/base/CMakeLists.txt | 2 +- src/lib/base/Log.cpp | 4 +- src/lib/common/CMakeLists.txt | 24 ------- src/lib/common/Version.cpp | 29 -------- src/lib/common/Version.h | 39 ----------- .../{global/Ipc.cpp => common/constants.h} | 22 +++--- .../{gui/version.cpp => common/copyright.h} | 33 +++++---- src/lib/{global/Ipc.h => common/ipc.h} | 16 ++--- src/lib/{gui => common}/version.h | 19 ++++-- src/lib/global/CMakeLists.txt | 26 ------- src/lib/gui/CMakeLists.txt | 1 - src/lib/gui/Logger.cpp | 55 ++++++++++++--- src/lib/gui/Logger.h | 2 +- src/lib/gui/TrayIcon.cpp | 2 +- src/lib/gui/config/ConfigScopes.cpp | 8 +-- src/lib/gui/config/ConfigScopes.h | 1 + src/lib/gui/constants.h | 8 +-- src/lib/gui/core/ClientConnection.cpp | 10 +-- src/lib/gui/dotenv.cpp | 34 ++++++++-- src/lib/gui/dotenv.h | 9 ++- src/lib/gui/ipc/IpcReader.cpp | 2 +- src/lib/gui/ipc/QIpcClient.cpp | 2 +- src/lib/gui/messages.cpp | 5 +- src/lib/gui/proxy/QSettingsProxy.h | 1 + src/lib/ipc/CMakeLists.txt | 1 - src/lib/ipc/IpcClient.cpp | 2 +- src/lib/ipc/IpcClientProxy.cpp | 2 +- src/lib/ipc/IpcClientProxy.h | 2 +- src/lib/ipc/IpcLogOutputter.cpp | 2 +- src/lib/ipc/IpcLogOutputter.h | 2 +- src/lib/ipc/IpcMessage.cpp | 2 +- src/lib/ipc/IpcMessage.h | 2 +- src/lib/ipc/IpcServer.cpp | 2 +- src/lib/ipc/IpcServer.h | 2 +- src/lib/ipc/IpcServerProxy.cpp | 2 +- src/lib/platform/MSWindowsWatchdog.cpp | 2 +- src/lib/server/CMakeLists.txt | 2 +- src/lib/synergy/App.cpp | 35 ++++------ src/lib/synergy/ClientApp.cpp | 2 +- src/lib/synergy/ClientTaskBarReceiver.cpp | 12 ++-- src/lib/synergy/DaemonApp.cpp | 2 +- src/lib/synergy/ServerApp.cpp | 2 +- src/lib/synergy/ServerTaskBarReceiver.cpp | 10 +-- src/lib/synergy/ToolApp.cpp | 2 - src/lib/synergy/win32/AppUtilWindows.cpp | 2 +- src/test/CMakeLists.txt | 2 - src/test/integtests/gui/dotenv_tests.cpp | 12 +++- src/test/integtests/ipc/IpcTests.cpp | 2 +- src/test/unittests/gui/LoggerTests.cpp | 58 ++++++++++++++++ 67 files changed, 372 insertions(+), 319 deletions(-) delete mode 100644 src/lib/common/CMakeLists.txt delete mode 100644 src/lib/common/Version.cpp delete mode 100644 src/lib/common/Version.h rename src/lib/{global/Ipc.cpp => common/constants.h} (65%) rename src/lib/{gui/version.cpp => common/copyright.h} (53%) rename src/lib/{global/Ipc.h => common/ipc.h} (83%) rename src/lib/{gui => common}/version.h (69%) delete mode 100644 src/lib/global/CMakeLists.txt create mode 100644 src/test/unittests/gui/LoggerTests.cpp diff --git a/ChangeLog b/ChangeLog index 025f8dd74..5eda12676 100644 --- a/ChangeLog +++ b/ChangeLog @@ -74,6 +74,7 @@ Enhancements: - #7428 Refactor settings dialog to simplify enable/disable logic - #7429 Parse date numbers as long instead of int - #7430 Improve setting enable logic and test coverage +- #7431 Improve handling of Qt-related warnings and errors # 1.14.6 diff --git a/cspell.json b/cspell.json index d1b4f36aa..b127be51f 100644 --- a/cspell.json +++ b/cspell.json @@ -9,6 +9,7 @@ "Breen", "codesign", "codesigning", + "Compat", "contribs", "Daun", "distros", @@ -19,6 +20,9 @@ "gdrive", "Hadzhylov", "Hetu", + "hotspots", + "ifdef", + "integtests", "keychain", "Keychains", "Kutytska", @@ -37,6 +41,8 @@ "Pixmap", "Poschta", "Priddy", + "pyproject", + "qputenv", "Regen", "runas", "Sbârnea", @@ -46,6 +52,7 @@ "synergyc", "synergyd", "synergys", + "Valgrind", "Volker", "winget" ], diff --git a/src/cmd/synergy-core/CMakeLists.txt b/src/cmd/synergy-core/CMakeLists.txt index b99ca1aae..caf53c8ea 100644 --- a/src/cmd/synergy-core/CMakeLists.txt +++ b/src/cmd/synergy-core/CMakeLists.txt @@ -28,7 +28,6 @@ target_link_libraries( arch base client - common io mt net diff --git a/src/cmd/synergyc/CMakeLists.txt b/src/cmd/synergyc/CMakeLists.txt index 45c60fb0e..f728adcc1 100644 --- a/src/cmd/synergyc/CMakeLists.txt +++ b/src/cmd/synergyc/CMakeLists.txt @@ -54,7 +54,6 @@ target_link_libraries( arch base client - common io mt net diff --git a/src/cmd/synergyd/CMakeLists.txt b/src/cmd/synergyd/CMakeLists.txt index 8a391988f..8e92f5939 100644 --- a/src/cmd/synergyd/CMakeLists.txt +++ b/src/cmd/synergyd/CMakeLists.txt @@ -29,14 +29,12 @@ target_link_libraries( ${target} arch base - common io ipc mt net platform synlib - global license ${libs}) diff --git a/src/cmd/synergys/CMakeLists.txt b/src/cmd/synergys/CMakeLists.txt index 021c6c486..5e3908c3c 100644 --- a/src/cmd/synergys/CMakeLists.txt +++ b/src/cmd/synergys/CMakeLists.txt @@ -54,7 +54,6 @@ target_link_libraries( arch base client - common io mt net diff --git a/src/cmd/syntool/CMakeLists.txt b/src/cmd/syntool/CMakeLists.txt index b59d0787e..701db0c62 100644 --- a/src/cmd/syntool/CMakeLists.txt +++ b/src/cmd/syntool/CMakeLists.txt @@ -30,7 +30,6 @@ target_link_libraries( arch base client - common io ipc mt diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index f795fa28e..b59266661 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -51,7 +51,6 @@ include_directories(${CMAKE_BINARY_DIR}/src/lib/gui/gui_autogen/include) target_link_libraries( ${target} gui - global license Qt6::Core Qt6::Widgets diff --git a/src/gui/src/AboutDialog.cpp b/src/gui/src/AboutDialog.cpp index c523ffde1..bc3c727f6 100644 --- a/src/gui/src/AboutDialog.cpp +++ b/src/gui/src/AboutDialog.cpp @@ -17,6 +17,7 @@ */ #include "AboutDialog.h" +#include "common/copyright.h" #include @@ -24,7 +25,7 @@ #include "gui/OSXHelpers.h" #endif -#include "gui/version.h" +#include "common/version.h" AboutDialog::AboutDialog(MainWindow *parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), @@ -34,7 +35,8 @@ AboutDialog::AboutDialog(MainWindow *parent) this->setFixedSize(this->size()); - m_pLabelSynergyVersion->setText(synergy::gui::version()); + QString version = QString::fromStdString(synergy::version()); + m_pLabelSynergyVersion->setText(version); QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified(); QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy"); @@ -43,8 +45,8 @@ AboutDialog::AboutDialog(MainWindow *parent) } int AboutDialog::exec() { - m_pDevelopersLabel->setText(getImportantDevelopers()); - m_pCopyrightLabel->setText(getCopyright()); + m_pDevelopersLabel->setText(importantDevelopers()); + m_pCopyrightLabel->setText(QString::fromStdString(synergy::copyright())); updateLogo(); return QDialog::exec(); @@ -61,7 +63,7 @@ void AboutDialog::updateLogo() const { #endif } -QString AboutDialog::getImportantDevelopers() const { +QString AboutDialog::importantDevelopers() const { QStringList awesomePeople; // Chris is the ultimate creator, and the one who started it all in 2001. @@ -104,14 +106,3 @@ QString AboutDialog::getImportantDevelopers() const { return awesomePeople.join(", ") + "."; } - -QString AboutDialog::getCopyright() const { - QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified(); - QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy"); - - QString copyright("Copyright © 2012-%%YEAR%% Symless Ltd.\n" - "Copyright © 2009-2012 Nick Bolton\n" - "Copyright © 2002-2009 Chris Schoeneman"); - return copyright.replace( - QString("%%YEAR%%"), QString::number(buildDate.year())); -} diff --git a/src/gui/src/AboutDialog.h b/src/gui/src/AboutDialog.h index 78a52f46d..27d26987f 100644 --- a/src/gui/src/AboutDialog.h +++ b/src/gui/src/AboutDialog.h @@ -37,6 +37,5 @@ private: VersionChecker m_versionChecker; void updateLogo() const; - virtual QString getCopyright() const; - virtual QString getImportantDevelopers() const; + virtual QString importantDevelopers() const; }; diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index 6dc36b827..3dc55e88b 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -75,13 +75,13 @@ ActivationDialog::~ActivationDialog() { delete m_ui; } void ActivationDialog::reject() { // don't show the cancel confirmation dialog if they've already registered, - // since it's not revent to customers who are changing their serial key. + // since it's not relevant to customers who are changing their serial key. if (m_licenseHandler.productEdition() != Edition::kUnregistered) { QDialog::reject(); return; } - // the accept button should be labeled "Exit" on the cancel dialoig. + // the accept button should be labeled "Exit" on the cancel dialog. CancelActivationDialog cancelActivationDialog(this); if (cancelActivationDialog.exec() == QDialog::Accepted) { QApplication::exit(); diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 96e5af512..3abeb4fd2 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -31,6 +31,7 @@ #include "gui/license/LicenseHandler.h" #include "gui/license/license_notices.h" #include "gui/messages.h" +#include "gui/string_utils.h" #include "gui/styles.h" #include "gui/tls/TlsFingerprint.h" #include "license/License.h" @@ -258,14 +259,6 @@ void MainWindow::connectSlots() { m_pActionRestore, &QAction::triggered, // [this]() { showAndActivate(); }); - connect( - m_pActionStartCore, &QAction::triggered, this, - &MainWindow::onActionStartCoreTriggered); - - connect( - m_pActionStopCore, &QAction::triggered, this, - &MainWindow::onActionStopCoreTriggered); - connect(m_pActionQuit, &QAction::triggered, qApp, &QCoreApplication::quit); connect( @@ -310,6 +303,9 @@ void MainWindow::onCreated() { updateScreenName(); applyConfig(); restoreWindow(); + + qDebug().noquote() << "active settings path:" + << m_ConfigScopes.activeFilePath(); } void MainWindow::onShown() { @@ -366,16 +362,6 @@ void MainWindow::onVersionCheckerUpdateFound(const QString &version) { m_pLabelUpdate->setText(text); } -void MainWindow::onActionStartCoreTriggered() { - m_ClientConnection.setShowMessage(); - m_CoreProcess.start(); -} - -void MainWindow::onActionStopCoreTriggered() { - qDebug("stopping core process"); - m_CoreProcess.stop(); -} - void MainWindow::onAppConfigScreenNameChanged() { updateScreenName(); } void MainWindow::onAppConfigInvertConnection() { applyConfig(); } @@ -396,6 +382,24 @@ void MainWindow::onCoreProcessError(CoreProcess::Error error) { } } +void MainWindow::on_m_pActionStartCore_triggered() { + m_ClientConnection.setShowMessage(); + m_CoreProcess.start(); +} + +void MainWindow::on_m_pActionStopCore_triggered() { + qDebug("stopping core process"); + m_CoreProcess.stop(); +} + +void MainWindow::on_m_pActionTestFatalError_triggered() const { + qFatal("test fatal error"); +} + +void MainWindow::on_m_pActionTestCriticalError_triggered() const { + qCritical("test critical error"); +} + bool MainWindow::on_m_pActionSave_triggered() { QString fileName = QFileDialog::getSaveFileName(this, QString("Save configuration as...")); @@ -596,6 +600,22 @@ void MainWindow::createMenuBar() { m_pMenuHelp->addAction(m_pActionAbout); m_pMenuHelp->addAction(m_pActionHelp); +#ifndef NDEBUG + // always enable test menu in debug mode. + const auto enableTestMenu = true; +#else + // only enable test menu in release build if env var is true. + const auto enableTestMenu = + strToTrue(qEnvironmentVariable("SYNERGY_TEST_MENU")); +#endif + + if (enableTestMenu) { + auto testMenu = new QMenu("Test", m_pMenuBar); + m_pMenuBar->addMenu(testMenu); + testMenu->addAction(m_pActionTestFatalError); + testMenu->addAction(m_pActionTestCriticalError); + } + setMenuBar(m_pMenuBar); } @@ -1041,6 +1061,11 @@ int MainWindow::showActivationDialog() { if (result == QDialog::Accepted) { m_AppConfig.setActivationHasRun(true); + + // customers who are activating a pro license are usually doing so because + // they want tls. so, if it's available, turn it on after activating. + m_AppConfig.setTlsEnabled(m_LicenseHandler.license().isTlsAvailable()); + m_ConfigScopes.save(); } @@ -1051,6 +1076,13 @@ int MainWindow::showActivationDialog() { m_PendingClientNames.clear(); } + + // restart core process after activation in case switching on tls. + // this saves customer from having to figure out they need to click apply. + if (m_CoreProcess.isStarted()) { + m_CoreProcess.restart(); + } + return result; } diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index d275d0156..355e1b3d8 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -27,7 +27,7 @@ #include "ActivationDialog.h" #include "ServerConfig.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "gui/TrayIcon.h" #include "gui/VersionChecker.h" #include "gui/config/AppConfig.h" @@ -108,8 +108,6 @@ private slots: void onLicenseHandlerInvalidLicense(); void onVersionCheckerUpdateFound(const QString &version); void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason); - void onActionStartCoreTriggered(); - void onActionStopCoreTriggered(); void onWindowSaveTimerTimeout(); void onServerConnectionConfigureClient(const QString &clientName); @@ -129,6 +127,10 @@ private slots: void on_m_pActionHelp_triggered() const; void on_m_pActionSettings_triggered(); void on_m_pActionActivate_triggered(); + void on_m_pActionStartCore_triggered(); + void on_m_pActionStopCore_triggered(); + void on_m_pActionTestFatalError_triggered() const; + void on_m_pActionTestCriticalError_triggered() const; void on_m_pLineEditHostname_returnPressed(); void on_m_pLineEditClientIp_returnPressed(); void on_m_pLineEditHostname_textChanged(const QString &text); diff --git a/src/gui/src/MainWindowBase.ui b/src/gui/src/MainWindowBase.ui index 01116ab7e..8083d5235 100644 --- a/src/gui/src/MainWindowBase.ui +++ b/src/gui/src/MainWindowBase.ui @@ -599,14 +599,6 @@ Ctrl+T - - - S&how Status - - - Ctrl+H - - &Hide @@ -659,6 +651,22 @@ Activate + + + Test fatal error + + + QAction::TextHeuristicRole + + + + + Test critical error + + + QAction::TextHeuristicRole + + diff --git a/src/gui/src/SetupWizardBlocker.cpp b/src/gui/src/SetupWizardBlocker.cpp index eee36a6bc..51e2acfee 100644 --- a/src/gui/src/SetupWizardBlocker.cpp +++ b/src/gui/src/SetupWizardBlocker.cpp @@ -48,8 +48,7 @@ SetupWizardBlocker::SetupWizardBlocker(BlockerType type) { } void SetupWizardBlocker::onlineSupport() { - QDesktopServices::openUrl( - QUrl("https://symless.com/synergy/help?source=gui")); + QDesktopServices::openUrl(QUrl(synergy::gui::kUrlHelp)); cancel(); } diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 4c7493820..2d71e8a8b 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -20,13 +20,13 @@ #include "QSynergyApplication.h" #include "SetupWizard.h" #include "SetupWizardBlocker.h" +#include "common/constants.h" +#include "common/version.h" #include "gui/Logger.h" #include "gui/config/AppConfig.h" #include "gui/config/ConfigScopes.h" -#include "gui/constants.h" #include "gui/dotenv.h" #include "gui/messages.h" -#include "gui/version.h" #include #include @@ -61,18 +61,23 @@ int main(int argc, char *argv[]) { ::setenv("QT_BEARER_POLL_TIMEOUT", "-1", 1); #endif - QCoreApplication::setOrganizationName(kAppName); QCoreApplication::setApplicationName(kAppName); - QCoreApplication::setOrganizationDomain(kAppDomain); + + // HACK: set org name to app name for backwards compatibility. + QCoreApplication::setOrganizationName(kAppName); + + // HACK: set org domain to url for backwards compatibility. + QCoreApplication::setOrganizationDomain(kUrlWebsite); QSynergyApplication app(argc, argv); + qInstallMessageHandler(synergy::gui::messages::messageHandler); + QString version = QString::fromStdString(synergy::version()); + qInfo("Synergy v%s", qPrintable(version)); - dotenv(".env"); + dotenv(); Logger::instance().loadEnvVars(); - qInfo("Synergy v%s", synergy::gui::version().toUtf8().constData()); - #if defined(Q_OS_MAC) if (app.applicationDirPath().startsWith("/Volumes/")) { diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index a5c5981bc..844735d8b 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -17,7 +17,6 @@ add_subdirectory(arch) add_subdirectory(base) add_subdirectory(client) -add_subdirectory(common) add_subdirectory(io) add_subdirectory(ipc) add_subdirectory(mt) @@ -25,6 +24,5 @@ add_subdirectory(net) add_subdirectory(platform) add_subdirectory(server) add_subdirectory(synergy) -add_subdirectory(global) add_subdirectory(license) add_subdirectory(gui) diff --git a/src/lib/arch/win32/ArchMiscWindows.cpp b/src/lib/arch/win32/ArchMiscWindows.cpp index 0871921d1..ce14c4339 100644 --- a/src/lib/arch/win32/ArchMiscWindows.cpp +++ b/src/lib/arch/win32/ArchMiscWindows.cpp @@ -19,7 +19,7 @@ #include "arch/win32/ArchMiscWindows.h" #include "arch/win32/ArchDaemonWindows.h" #include "base/Log.h" -#include "common/Version.h" +#include "common/constants.h" #include #pragma warning(disable : 4099) diff --git a/src/lib/base/CMakeLists.txt b/src/lib/base/CMakeLists.txt index a84258745..fb57ef1af 100644 --- a/src/lib/base/CMakeLists.txt +++ b/src/lib/base/CMakeLists.txt @@ -24,5 +24,5 @@ endif() add_library(base STATIC ${sources}) if(UNIX) - target_link_libraries(base common) + target_link_libraries(base) endif() diff --git a/src/lib/base/Log.cpp b/src/lib/base/Log.cpp index 9a6b540ee..822b4aedf 100644 --- a/src/lib/base/Log.cpp +++ b/src/lib/base/Log.cpp @@ -19,7 +19,7 @@ #include "base/Log.h" #include "arch/Arch.h" #include "base/log_outputters.h" -#include "common/Version.h" +#include "common/constants.h" #include #include @@ -223,7 +223,7 @@ void Log::insert(ILogOutputter *outputter, bool alwaysAtHead) { m_outputters.push_front(outputter); } - outputter->open(kAppVersion); + outputter->open(kAppName); // Issue 41 // don't show log unless user requests it, as some users find this diff --git a/src/lib/common/CMakeLists.txt b/src/lib/common/CMakeLists.txt deleted file mode 100644 index 6c08ef760..000000000 --- a/src/lib/common/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# Synergy -- mouse and keyboard sharing utility -# Copyright (C) 2012-2024 Symless Ltd. -# Copyright (C) 2009-2012 Nick Bolton -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file LICENSE that should have accompanied this file. -# -# This package is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -file(GLOB headers "*.h") -file(GLOB sources "*.cpp") - -if(ADD_HEADERS_TO_SOURCES) - list(APPEND sources ${headers}) -endif() - -add_library(common STATIC ${sources}) diff --git a/src/lib/common/Version.cpp b/src/lib/common/Version.cpp deleted file mode 100644 index 1233fe20c..000000000 --- a/src/lib/common/Version.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2024 Symless Ltd. - * Copyright (C) 2009-2012 Nick Bolton - * Copyright (C) 2002-2009 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "common/Version.h" - -const char *kApplication = "Synergy"; -const char *kCopyright = "Copyright (C) 2012-%s Symless Ltd.\n" - "Copyright (C) 2009-2012 Nick Bolton\n" - "Copyright (C) 2002-2009 Chris Schoeneman"; -const char *kContact = "Email: engineering@symless.com"; -const char *kWebsite = "https://symless.com/"; -const char *kVersion = SYNERGY_VERSION; -const char *kAppVersion = "Synergy " SYNERGY_VERSION; diff --git a/src/lib/common/Version.h b/src/lib/common/Version.h deleted file mode 100644 index 11409f654..000000000 --- a/src/lib/common/Version.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "common/common.h" - -// set version macro if not set yet -#if !defined(SYNERGY_VERSION) -#error Version was not set (should be passed to compiler). -#endif - -// important strings -extern const char *kApplication; -extern const char *kCopyright; -extern const char *kContact; -extern const char *kWebsite; - -// build version. follows linux kernel style: an even minor number implies -// a release version, odd implies development version. -extern const char *kVersion; - -// application version -extern const char *kAppVersion; diff --git a/src/lib/global/Ipc.cpp b/src/lib/common/constants.h similarity index 65% rename from src/lib/global/Ipc.cpp rename to src/lib/common/constants.h index 74179ffc2..0378cb693 100644 --- a/src/lib/global/Ipc.cpp +++ b/src/lib/common/constants.h @@ -1,6 +1,7 @@ /* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2012 Symless Ltd. + * Copyright (C) 2002 Chris Schoeneman * * This package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,14 +16,17 @@ * along with this program. If not, see . */ -#include "Ipc.h" +#pragma once -const char *const kIpcHost = "127.0.0.1"; -const int kIpcPort = 24801; +#if !defined(SYNERGY_VERSION) +#error version was not passed to the compiler +#endif -const char *const kIpcMsgHello = "IHEL%1i"; -const char *const kIpcMsgHelloBack = "IHEL"; -const char *const kIpcMsgLogLine = "ILOG%s"; -const char *const kIpcMsgCommand = "ICMD%s%1i"; -const char *const kIpcMsgShutdown = "ISDN"; -const char *const kIpcMsgSetting = "SSET%s%s"; +const auto kAppName = "Synergy"; +const auto kVersion = SYNERGY_VERSION; + +#ifdef GIT_SHA_SHORT +const auto kVersionGitSha = GIT_SHA_SHORT; +#else +const auto kVersionGitSha = ""; +#endif diff --git a/src/lib/gui/version.cpp b/src/lib/common/copyright.h similarity index 53% rename from src/lib/gui/version.cpp rename to src/lib/common/copyright.h index b0dd9af13..f084d10b4 100644 --- a/src/lib/gui/version.cpp +++ b/src/lib/common/copyright.h @@ -15,24 +15,27 @@ * along with this program. If not, see . */ -#include "version.h" +#pragma once -const QString kVersion = SYNERGY_VERSION; +#include +#include +#include -#ifdef GIT_SHA_SHORT -const QString kVersionGitSha = GIT_SHA_SHORT; -#else -const QString kVersionGitSha; -#endif +namespace synergy { -namespace synergy::gui { +const auto kCopyrightFormat = // + "Copyright (C) 2012-%s Symless Ltd.\n" + "Copyright (C) 2009-2012 Nick Bolton\n" + "Copyright (C) 2002-2009 Chris Schoeneman"; -QString version() { - QString result(kVersion); - if (!kVersionGitSha.isEmpty()) { - result.append(QString(" (%1)").arg(kVersionGitSha)); - } - return result; +inline std::string copyright() { + const std::string date = __DATE__; + const auto year = date.substr(date.size() - 4); + const auto kBufferLength = 256; + std::vector buffer(kBufferLength); + std::snprintf( // NOSONAR + buffer.data(), kBufferLength, kCopyrightFormat, year.c_str()); + return std::string(buffer.data()); } -} // namespace synergy::gui +} // namespace synergy diff --git a/src/lib/global/Ipc.h b/src/lib/common/ipc.h similarity index 83% rename from src/lib/global/Ipc.h rename to src/lib/common/ipc.h index 46b8a2eec..90df86a51 100644 --- a/src/lib/global/Ipc.h +++ b/src/lib/common/ipc.h @@ -30,31 +30,31 @@ enum class IpcMessageType : UInt8 { enum class IpcClientType { Unknown, GUI, Node }; -extern const char *const kIpcHost; -extern const int kIpcPort; +const auto kIpcHost = "127.0.0.1"; +const auto kIpcPort = 24801; // handshake: node/gui -> daemon // $1 = type, the client identifies it's self as gui or node (synergyc/s). -extern const char *const kIpcMsgHello; +const auto kIpcMsgHello = "IHEL%1i"; // handshake: daemon -> node/gui // the daemon responds to the handshake. -extern const char *const kIpcMsgHelloBack; +const auto kIpcMsgHelloBack = "IHEL"; // log line: daemon -> gui // $1 = aggregate log lines collected from synergys/c or the daemon itself. -extern const char *const kIpcMsgLogLine; +const auto kIpcMsgLogLine = "ILOG%s"; // command: gui -> daemon // $1 = command; the command for the daemon to launch, typically the full // path to synergys/c. $2 = true when process must be elevated on ms windows. -extern const char *const kIpcMsgCommand; +const auto kIpcMsgCommand = "ICMD%s%1i"; // shutdown: daemon -> node // the daemon tells synergys/c to shut down gracefully. -extern const char *const kIpcMsgShutdown; +const auto kIpcMsgShutdown = "ISDN"; // set setting: gui -> daemon // $1 = setting name // $2 = setting value -extern const char *const kIpcMsgSetting; +const auto kIpcMsgSetting = "SSET%s%s"; diff --git a/src/lib/gui/version.h b/src/lib/common/version.h similarity index 69% rename from src/lib/gui/version.h rename to src/lib/common/version.h index 0cd51257f..e4dc2bdaf 100644 --- a/src/lib/gui/version.h +++ b/src/lib/common/version.h @@ -17,10 +17,21 @@ #pragma once -#include +#include "constants.h" -namespace synergy::gui { +#include -QString version(); +namespace synergy { -} // namespace synergy::gui +inline std::string version() { + std::string result = kVersion; + std::string gitSha = kVersionGitSha; + if (!gitSha.empty()) { + result.append(" ("); + result.append(gitSha); + result.append(")"); + } + return result; +} + +} // namespace synergy diff --git a/src/lib/global/CMakeLists.txt b/src/lib/global/CMakeLists.txt deleted file mode 100644 index 909e421eb..000000000 --- a/src/lib/global/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Synergy -- mouse and keyboard sharing utility -# Copyright (C) 2012-2024 Symless Ltd. -# Copyright (C) 2009-2012 Nick Bolton -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file LICENSE that should have accompanied this file. -# -# This package is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -file(GLOB headers "*.h") -file(GLOB sources "*.cpp") - -if(ADD_HEADERS_TO_SOURCES) - list(APPEND sources ${headers}) -endif() - -add_library(global STATIC ${sources}) - -target_link_libraries(global) diff --git a/src/lib/gui/CMakeLists.txt b/src/lib/gui/CMakeLists.txt index 47f712198..3cbbbde6c 100644 --- a/src/lib/gui/CMakeLists.txt +++ b/src/lib/gui/CMakeLists.txt @@ -36,7 +36,6 @@ endif() add_library(${target} STATIC ${sources} ${ui_files}) target_link_libraries( ${target} - global license Qt6::Core Qt6::Widgets diff --git a/src/lib/gui/Logger.cpp b/src/lib/gui/Logger.cpp index b90764c3d..87792de6c 100644 --- a/src/lib/gui/Logger.cpp +++ b/src/lib/gui/Logger.cpp @@ -24,24 +24,58 @@ #include #include +#if defined(Q_OS_WIN) +#include +#endif + namespace synergy::gui { +const auto kForceDebugMessages = QStringList{ + "Synergy", // TEST + "No functional TLS backend was found", + "No TLS backend is available", + "QSslSocket::connectToHostEncrypted: TLS initialization failed", + "Retrying to obtain clipboard.", + "Unable to obtain clipboard."}; + Logger Logger::s_instance; +QString fileLine(const QMessageLogContext &context) { + if (!context.file) { + return ""; + } + return QString("%1:%2").arg(context.file).arg(context.line); +} + QString printLine( FILE *out, const QString &type, const QString &message, const QString &fileLine = "") { + auto datetime = QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm:ss"); auto logLine = QString("[%1] %2: %3").arg(datetime).arg(type).arg(message); + QTextStream stream(&logLine); if (!fileLine.isEmpty()) { - logLine += "\n\t" + fileLine; + stream << Qt::endl << "\t" + fileLine; } - auto logLineUtf = logLine.toUtf8(); - auto logLine_c = logLineUtf.constData(); - fprintf(out, "%s\n", logLine_c); + QString logLineReturn = logLine; + QTextStream streamReturn(&logLineReturn); + streamReturn << Qt::endl; + + auto logLineReturn_c = qPrintable(logLineReturn); + +#if defined(Q_OS_WIN) + // Debug output is viewable using either VS Code, Visual Studio, DebugView, or + // DbgView++ (only one can be used at once). It's important to send output to + // the debug output API, because it's difficult to view stdout and stderr from + // a Windows GUI app. + OutputDebugStringA(logLineReturn_c); +#else + fprintf(out, "%s", logLineReturn_c); fflush(out); +#endif + return logLine; } @@ -64,11 +98,17 @@ void Logger::logVerbose(const QString &message) const { } void Logger::handleMessage( - QtMsgType type, const QMessageLogContext &context, const QString &message) { + const QtMsgType type, const QMessageLogContext &context, + const QString &message) { + + auto mutatedType = type; + if (kForceDebugMessages.contains(message)) { + mutatedType = QtDebugMsg; + } QString typeString; auto out = stdout; - switch (type) { + switch (mutatedType) { case QtDebugMsg: typeString = "DEBUG"; if (!m_debug) { @@ -92,8 +132,7 @@ void Logger::handleMessage( break; } - const auto fileLine = QString("%1:%2").arg(context.file).arg(context.line); - const auto logLine = printLine(out, typeString, message, fileLine); + const auto logLine = printLine(out, typeString, message, fileLine(context)); emit newLine(logLine); } diff --git a/src/lib/gui/Logger.h b/src/lib/gui/Logger.h index 156980e6a..bf6d5312b 100644 --- a/src/lib/gui/Logger.h +++ b/src/lib/gui/Logger.h @@ -35,7 +35,7 @@ public: void loadEnvVars(); void handleMessage( - QtMsgType type, const QMessageLogContext &context, + const QtMsgType type, const QMessageLogContext &context, const QString &message); void logVerbose(const QString &message) const; diff --git a/src/lib/gui/TrayIcon.cpp b/src/lib/gui/TrayIcon.cpp index 99faedc3f..fbbb26374 100644 --- a/src/lib/gui/TrayIcon.cpp +++ b/src/lib/gui/TrayIcon.cpp @@ -17,7 +17,7 @@ #include "TrayIcon.h" -#include "constants.h" +#include "common/constants.h" namespace synergy::gui { diff --git a/src/lib/gui/config/ConfigScopes.cpp b/src/lib/gui/config/ConfigScopes.cpp index facfb06cd..71a7e15c0 100644 --- a/src/lib/gui/config/ConfigScopes.cpp +++ b/src/lib/gui/config/ConfigScopes.cpp @@ -96,8 +96,6 @@ ConfigScopes::ConfigScopes() { m_pUserSettings = std::make_unique(); m_userSettingsProxy.set(*m_pUserSettings); - qDebug() << "user settings path:" << m_pUserSettings->fileName(); - QSettings::setPath( QSettings::Format::IniFormat, QSettings::Scope::SystemScope, getSystemSettingPath()); @@ -109,8 +107,6 @@ ConfigScopes::ConfigScopes() { appName); m_systemSettingsProxy.set(*m_pSystemSettings); - qDebug() << "system settings path:" << m_pSystemSettings->fileName(); - #if defined(Q_OS_WIN) loadWindowsLegacy(*m_pSystemSettings); #endif @@ -164,6 +160,10 @@ const QSettingsProxy &ConfigScopes::activeSettings() const { } } +QString ConfigScopes::activeFilePath() const { + return activeSettings().fileName(); +} + QVariant ConfigScopes::getFromScope( const QString &name, const QVariant &defaultValue, Scope scope) const { switch (scope) { diff --git a/src/lib/gui/config/ConfigScopes.h b/src/lib/gui/config/ConfigScopes.h index 85668a0b2..47ea1544a 100644 --- a/src/lib/gui/config/ConfigScopes.h +++ b/src/lib/gui/config/ConfigScopes.h @@ -51,6 +51,7 @@ public: Scope activeScope() const override; QSettingsProxy &activeSettings() override; const QSettingsProxy &activeSettings() const override; + QString activeFilePath() const; signals: void ready(); diff --git a/src/lib/gui/constants.h b/src/lib/gui/constants.h index 7e8da3f59..ff7689a15 100644 --- a/src/lib/gui/constants.h +++ b/src/lib/gui/constants.h @@ -21,12 +21,6 @@ namespace synergy::gui { -const auto kAppName = "Synergy"; - -// TODO: change to `com.symless`. we'll need to gracefully import old settings, -// since qt uses this on some platforms when saving settings. -const auto kAppDomain = "https://symless.com"; - const int kDebugLogLevel = 1; #ifdef SYNERGY_PRODUCT_NAME @@ -54,8 +48,8 @@ const auto kLinkBuy = R"(Buy now)"; const auto kLinkRenew = R"(Renew now)"; const auto kLinkDownload = R"(Download now)"; -const auto kUrlSourceQuery = "source=gui"; const auto kUrlWebsite = "https://symless.com"; +const auto kUrlSourceQuery = "source=gui"; const auto kUrlGitHub = "https://github.com/symless/synergy-core"; const auto kUrlGnomeTrayFix = "https://extensions.gnome.org/extension/2890/tray-icons-reloaded/"; diff --git a/src/lib/gui/core/ClientConnection.cpp b/src/lib/gui/core/ClientConnection.cpp index 050227297..942bb93f7 100644 --- a/src/lib/gui/core/ClientConnection.cpp +++ b/src/lib/gui/core/ClientConnection.cpp @@ -39,12 +39,14 @@ void ClientConnection::Deps::showError( // void ClientConnection::handleLogLine(const QString &logLine) { - if (!m_showMessage) { - qDebug("message already shown, skipping"); - return; - } if (logLine.contains("failed to connect to server")) { + + if (!m_showMessage) { + qDebug("message already shown, skipping"); + return; + } + m_showMessage = false; // ignore the message if it's about the server refusing by name as diff --git a/src/lib/gui/dotenv.cpp b/src/lib/gui/dotenv.cpp index 66becf958..be7b2ec11 100644 --- a/src/lib/gui/dotenv.cpp +++ b/src/lib/gui/dotenv.cpp @@ -17,7 +17,9 @@ #include "dotenv.h" +#include #include +#include #include #include #include @@ -28,6 +30,11 @@ namespace synergy::gui { QPair getPair(const QString &line); +bool open(QFile &file, const QString &filePath) { + file.setFileName(filePath); + return file.open(QIODevice::ReadOnly | QIODevice::Text); +} + /** * @brief A _very_ basic Qt .env file parser. * @@ -38,14 +45,29 @@ QPair getPair(const QString &line); * If this function is not sufficient, replace it with a library such as: * https://github.com/adeharo9/cpp-dotenv */ -void dotenv(const QString &filePath) { - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug("no .env file in current dir"); - return; +void dotenv(const QString &filename) { + QString filePath = filename; + QFile file; + if (!open(file, filePath)) { + QFileInfo fileInfo(filePath); + qInfo( + "no %s file in dir: %s", qPrintable(filename), + qPrintable(fileInfo.absolutePath())); + + // if nothing in current dir, then try app dir. this makes it a bit easier + // for engineers in the field to have an easily predictable location for the + // .env file. + QDir dir(QCoreApplication::applicationDirPath()); + filePath = dir.filePath(filename); + if (!open(file, filePath)) { + qInfo( + "no %s file in app dir: %s", qPrintable(filename), + qPrintable(dir.absolutePath())); + return; + } } - qDebug("loading env vars from: %s", filePath.toUtf8().constData()); + qInfo("loading env vars from: %s", qPrintable(filePath)); QTextStream in(&file); while (!in.atEnd()) { diff --git a/src/lib/gui/dotenv.h b/src/lib/gui/dotenv.h index 8fa4ee083..b55a30295 100644 --- a/src/lib/gui/dotenv.h +++ b/src/lib/gui/dotenv.h @@ -21,10 +21,13 @@ namespace synergy::gui { +const QString kDefaultEnvFilename = ".env"; + /** - * @param filePath Path to the .env file. - * @param envVars Somewhere to save strings for the lifetime of the app. + * @brief Loads environment variables from a .env file. + * + * First checks current dir for .env, then looks in the app dir. */ -void dotenv(const QString &filePath); +void dotenv(const QString &filename = kDefaultEnvFilename); } // namespace synergy::gui diff --git a/src/lib/gui/ipc/IpcReader.cpp b/src/lib/gui/ipc/IpcReader.cpp index fa42a7497..f1f7018f9 100644 --- a/src/lib/gui/ipc/IpcReader.cpp +++ b/src/lib/gui/ipc/IpcReader.cpp @@ -19,7 +19,7 @@ #include "Logger.h" #include "byte_utils.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include #include diff --git a/src/lib/gui/ipc/QIpcClient.cpp b/src/lib/gui/ipc/QIpcClient.cpp index 0fc3c905e..2ce1285f7 100644 --- a/src/lib/gui/ipc/QIpcClient.cpp +++ b/src/lib/gui/ipc/QIpcClient.cpp @@ -19,7 +19,7 @@ #include "IpcReader.h" #include "byte_utils.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include #include diff --git a/src/lib/gui/messages.cpp b/src/lib/gui/messages.cpp index e97d87890..037cadb19 100644 --- a/src/lib/gui/messages.cpp +++ b/src/lib/gui/messages.cpp @@ -18,6 +18,7 @@ #include "messages.h" #include "Logger.h" +#include "common/version.h" #include "constants.h" #include "styles.h" @@ -64,7 +65,9 @@ void showErrorDialog( .arg(kUrlBugReport, kColorSecondary); } - text += QString("
%3\n\n%4
").arg(message, contextString); + const QString version = QString::fromStdString(synergy::version()); + text += + QString("
v%1\n%2\n%3
").arg(version, message, contextString); if (type == QtFatalMsg) { // create a blocking message box for fatal errors, as we want to wait diff --git a/src/lib/gui/proxy/QSettingsProxy.h b/src/lib/gui/proxy/QSettingsProxy.h index 398025f05..82422dc11 100644 --- a/src/lib/gui/proxy/QSettingsProxy.h +++ b/src/lib/gui/proxy/QSettingsProxy.h @@ -37,6 +37,7 @@ public: virtual void remove(const QString &key); virtual bool isWritable() const; virtual bool contains(const QString &key) const; + virtual QString fileName() const { return m_pSettings->fileName(); } void set(QSettings &settings) { m_pSettings = &settings; } QSettings &get() const { return *m_pSettings; } diff --git a/src/lib/ipc/CMakeLists.txt b/src/lib/ipc/CMakeLists.txt index 9ca26df86..7bbf08ce1 100644 --- a/src/lib/ipc/CMakeLists.txt +++ b/src/lib/ipc/CMakeLists.txt @@ -28,7 +28,6 @@ if(UNIX) ipc arch base - common mt io net diff --git a/src/lib/ipc/IpcClient.cpp b/src/lib/ipc/IpcClient.cpp index 1cf83634b..f463330ba 100644 --- a/src/lib/ipc/IpcClient.cpp +++ b/src/lib/ipc/IpcClient.cpp @@ -17,7 +17,7 @@ #include "ipc/IpcClient.h" #include "base/TMethodEventJob.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "ipc/IpcMessage.h" #include "ipc/IpcServerProxy.h" diff --git a/src/lib/ipc/IpcClientProxy.cpp b/src/lib/ipc/IpcClientProxy.cpp index 3ee3843d8..7d48684c9 100644 --- a/src/lib/ipc/IpcClientProxy.cpp +++ b/src/lib/ipc/IpcClientProxy.cpp @@ -19,7 +19,7 @@ #include "base/Log.h" #include "base/TMethodEventJob.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "io/IStream.h" #include "ipc/IpcMessage.h" #include "ipc/IpcSettingMessage.h" diff --git a/src/lib/ipc/IpcClientProxy.h b/src/lib/ipc/IpcClientProxy.h index a41fda093..b0260b203 100644 --- a/src/lib/ipc/IpcClientProxy.h +++ b/src/lib/ipc/IpcClientProxy.h @@ -21,7 +21,7 @@ #include "arch/IArchMultithread.h" #include "base/Event.h" #include "base/EventTypes.h" -#include "global/Ipc.h" +#include "common/ipc.h" namespace synergy { class IStream; diff --git a/src/lib/ipc/IpcLogOutputter.cpp b/src/lib/ipc/IpcLogOutputter.cpp index bc322e972..81f5536d3 100644 --- a/src/lib/ipc/IpcLogOutputter.cpp +++ b/src/lib/ipc/IpcLogOutputter.cpp @@ -24,7 +24,7 @@ #include "base/EventQueue.h" #include "base/TMethodEventJob.h" #include "base/TMethodJob.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "ipc/IpcClientProxy.h" #include "ipc/IpcMessage.h" #include "ipc/IpcServer.h" diff --git a/src/lib/ipc/IpcLogOutputter.h b/src/lib/ipc/IpcLogOutputter.h index 06deeee66..1bac53206 100644 --- a/src/lib/ipc/IpcLogOutputter.h +++ b/src/lib/ipc/IpcLogOutputter.h @@ -21,7 +21,7 @@ #include "arch/Arch.h" #include "arch/IArchMultithread.h" #include "base/ILogOutputter.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include diff --git a/src/lib/ipc/IpcMessage.cpp b/src/lib/ipc/IpcMessage.cpp index dc51f3518..e953f8a47 100644 --- a/src/lib/ipc/IpcMessage.cpp +++ b/src/lib/ipc/IpcMessage.cpp @@ -17,7 +17,7 @@ */ #include "ipc/IpcMessage.h" -#include "global/Ipc.h" +#include "common/ipc.h" IpcMessage::IpcMessage(IpcMessageType type) : m_type(type) {} diff --git a/src/lib/ipc/IpcMessage.h b/src/lib/ipc/IpcMessage.h index dcd417043..587791061 100644 --- a/src/lib/ipc/IpcMessage.h +++ b/src/lib/ipc/IpcMessage.h @@ -19,7 +19,7 @@ #include "base/Event.h" #include "base/String.h" -#include "global/Ipc.h" +#include "common/ipc.h" class IpcMessage : public EventData { public: diff --git a/src/lib/ipc/IpcServer.cpp b/src/lib/ipc/IpcServer.cpp index bf1dc87d4..544b2ddae 100644 --- a/src/lib/ipc/IpcServer.cpp +++ b/src/lib/ipc/IpcServer.cpp @@ -22,7 +22,7 @@ #include "base/IEventQueue.h" #include "base/Log.h" #include "base/TMethodEventJob.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "io/IStream.h" #include "ipc/IpcClientProxy.h" #include "ipc/IpcMessage.h" diff --git a/src/lib/ipc/IpcServer.h b/src/lib/ipc/IpcServer.h index c21998599..356caf30d 100644 --- a/src/lib/ipc/IpcServer.h +++ b/src/lib/ipc/IpcServer.h @@ -20,7 +20,7 @@ #include "arch/Arch.h" #include "base/EventTypes.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "net/NetworkAddress.h" #include "net/TCPListenSocket.h" diff --git a/src/lib/ipc/IpcServerProxy.cpp b/src/lib/ipc/IpcServerProxy.cpp index 2e34f5879..1c889ae44 100644 --- a/src/lib/ipc/IpcServerProxy.cpp +++ b/src/lib/ipc/IpcServerProxy.cpp @@ -20,7 +20,7 @@ #include "base/Log.h" #include "base/TMethodEventJob.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "io/IStream.h" #include "ipc/IpcMessage.h" #include "synergy/ProtocolUtil.h" diff --git a/src/lib/platform/MSWindowsWatchdog.cpp b/src/lib/platform/MSWindowsWatchdog.cpp index dc5409e5e..6e3d7e1dc 100644 --- a/src/lib/platform/MSWindowsWatchdog.cpp +++ b/src/lib/platform/MSWindowsWatchdog.cpp @@ -23,7 +23,7 @@ #include "base/Log.h" #include "base/TMethodJob.h" #include "base/log_outputters.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "ipc/IpcLogOutputter.h" #include "ipc/IpcMessage.h" #include "ipc/IpcServer.h" diff --git a/src/lib/server/CMakeLists.txt b/src/lib/server/CMakeLists.txt index a17e5d9e2..d25b95d64 100644 --- a/src/lib/server/CMakeLists.txt +++ b/src/lib/server/CMakeLists.txt @@ -23,7 +23,7 @@ endif() add_library(server STATIC ${sources}) -target_link_libraries(server global license) +target_link_libraries(server license) if(UNIX) target_link_libraries(server synlib) diff --git a/src/lib/synergy/App.cpp b/src/lib/synergy/App.cpp index 64df222bf..e30bd6d72 100644 --- a/src/lib/synergy/App.cpp +++ b/src/lib/synergy/App.cpp @@ -26,8 +26,10 @@ #include "base/TMethodEventJob.h" #include "base/XBase.h" #include "base/log_outputters.h" -#include "common/Version.h" -#include "global/Ipc.h" +#include "common/constants.h" +#include "common/copyright.h" +#include "common/ipc.h" +#include "common/version.h" #include "ipc/IpcMessage.h" #include "ipc/IpcServerProxy.h" #include "synergy/ArgsBase.h" @@ -44,6 +46,7 @@ #include #include #include +#include #if WINAPI_CARBON #include @@ -82,27 +85,17 @@ App::~App() { } void App::version() { - const std::string date = __DATE__; - std::string year = date.substr(date.size() - 4); + const auto version = synergy::version(); + const auto copyright = synergy::copyright(); - const size_t kBufferSize = 500; - const size_t kCopyrightSize = 200; - char copyrightBuffer[kCopyrightSize]; - snprintf(copyrightBuffer, kCopyrightSize, kCopyright, year.c_str()); + const auto kBufferLength = 1024; + std::vector buffer(kBufferLength); + std::snprintf( // NOSONAR + buffer.data(), kBufferLength, "%s v%s, protocol v%d.%d\n%s", // + argsBase().m_pname, version.c_str(), kProtocolMajorVersion, + kProtocolMinorVersion, copyright.c_str()); - std::stringstream version; - version << kVersion; -#ifdef GIT_SHA_SHORT - version << " (" << GIT_SHA_SHORT << ")"; -#endif - - char buffer[kBufferSize]; - snprintf( - buffer, kBufferSize, "%s %s, protocol version %d.%d\n%s", - argsBase().m_pname, version.str().c_str(), kProtocolMajorVersion, - kProtocolMinorVersion, copyrightBuffer); - - std::cout << buffer << std::endl; + std::cout << std::string(buffer.data()) << std::endl; } int App::run(int argc, char **argv) { diff --git a/src/lib/synergy/ClientApp.cpp b/src/lib/synergy/ClientApp.cpp index 8d64cc909..a7d9ddf8e 100644 --- a/src/lib/synergy/ClientApp.cpp +++ b/src/lib/synergy/ClientApp.cpp @@ -29,7 +29,7 @@ #include "base/TMethodJob.h" #include "base/log_outputters.h" #include "client/Client.h" -#include "common/Version.h" +#include "common/constants.h" #include "mt/Thread.h" #include "net/InverseSockets/InverseSocketFactory.h" #include "net/NetworkAddress.h" diff --git a/src/lib/synergy/ClientTaskBarReceiver.cpp b/src/lib/synergy/ClientTaskBarReceiver.cpp index dc77cf8fd..48c390588 100644 --- a/src/lib/synergy/ClientTaskBarReceiver.cpp +++ b/src/lib/synergy/ClientTaskBarReceiver.cpp @@ -21,7 +21,7 @@ #include "base/IEventQueue.h" #include "base/String.h" #include "client/Client.h" -#include "common/Version.h" +#include "common/constants.h" #include "mt/Lock.h" // @@ -94,23 +94,23 @@ void ClientTaskBarReceiver::unlock() const { std::string ClientTaskBarReceiver::getToolTip() const { switch (m_state) { case kNotRunning: - return synergy::string::sprintf("%s: Not running", kAppVersion); + return synergy::string::sprintf("%s: Not running", kAppName); case kNotWorking: return synergy::string::sprintf( - "%s: %s", kAppVersion, m_errorMessage.c_str()); + "%s: %s", kAppName, m_errorMessage.c_str()); case kNotConnected: return synergy::string::sprintf( - "%s: Not connected: %s", kAppVersion, m_errorMessage.c_str()); + "%s: Not connected: %s", kAppName, m_errorMessage.c_str()); case kConnecting: return synergy::string::sprintf( - "%s: Connecting to %s...", kAppVersion, m_server.c_str()); + "%s: Connecting to %s...", kAppName, m_server.c_str()); case kConnected: return synergy::string::sprintf( - "%s: Connected to %s", kAppVersion, m_server.c_str()); + "%s: Connected to %s", kAppName, m_server.c_str()); default: return ""; diff --git a/src/lib/synergy/DaemonApp.cpp b/src/lib/synergy/DaemonApp.cpp index cceefaf16..055badabb 100644 --- a/src/lib/synergy/DaemonApp.cpp +++ b/src/lib/synergy/DaemonApp.cpp @@ -25,7 +25,7 @@ #include "base/Log.h" #include "base/TMethodEventJob.h" #include "base/log_outputters.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "ipc/IpcClientProxy.h" #include "ipc/IpcLogOutputter.h" #include "ipc/IpcMessage.h" diff --git a/src/lib/synergy/ServerApp.cpp b/src/lib/synergy/ServerApp.cpp index 6eec869bf..760e60ced 100644 --- a/src/lib/synergy/ServerApp.cpp +++ b/src/lib/synergy/ServerApp.cpp @@ -27,7 +27,7 @@ #include "base/TMethodEventJob.h" #include "base/TMethodJob.h" #include "base/log_outputters.h" -#include "common/Version.h" +#include "common/constants.h" #include "net/InverseSockets/InverseSocketFactory.h" #include "net/SocketMultiplexer.h" #include "net/TCPSocketFactory.h" diff --git a/src/lib/synergy/ServerTaskBarReceiver.cpp b/src/lib/synergy/ServerTaskBarReceiver.cpp index a2f366183..ade50630c 100644 --- a/src/lib/synergy/ServerTaskBarReceiver.cpp +++ b/src/lib/synergy/ServerTaskBarReceiver.cpp @@ -20,7 +20,7 @@ #include "arch/Arch.h" #include "base/IEventQueue.h" #include "base/String.h" -#include "common/Version.h" +#include "common/constants.h" #include "mt/Lock.h" #include "server/Server.h" @@ -97,17 +97,17 @@ void ServerTaskBarReceiver::unlock() const { std::string ServerTaskBarReceiver::getToolTip() const { switch (m_state) { case kNotRunning: - return synergy::string::sprintf("%s: Not running", kAppVersion); + return synergy::string::sprintf("%s: Not running", kAppName); case kNotWorking: return synergy::string::sprintf( - "%s: %s", kAppVersion, m_errorMessage.c_str()); + "%s: %s", kAppName, m_errorMessage.c_str()); case kNotConnected: - return synergy::string::sprintf("%s: Waiting for clients", kAppVersion); + return synergy::string::sprintf("%s: Waiting for clients", kAppName); case kConnected: - return synergy::string::sprintf("%s: Connected", kAppVersion); + return synergy::string::sprintf("%s: Connected", kAppName); default: return ""; diff --git a/src/lib/synergy/ToolApp.cpp b/src/lib/synergy/ToolApp.cpp index d6d9ddea4..d56f379dd 100644 --- a/src/lib/synergy/ToolApp.cpp +++ b/src/lib/synergy/ToolApp.cpp @@ -28,8 +28,6 @@ #include "platform/MSWindowsSession.h" #endif -#define JSON_URL "https://symless.com/account/json/" - enum { kErrorOk, kErrorArgs, kErrorException, kErrorUnknown }; UInt32 ToolApp::run(int argc, char **argv) { diff --git a/src/lib/synergy/win32/AppUtilWindows.cpp b/src/lib/synergy/win32/AppUtilWindows.cpp index 4dfde1aaf..2821404c4 100644 --- a/src/lib/synergy/win32/AppUtilWindows.cpp +++ b/src/lib/synergy/win32/AppUtilWindows.cpp @@ -25,7 +25,7 @@ #include "base/IEventQueue.h" #include "base/Log.h" #include "base/log_outputters.h" -#include "common/Version.h" +#include "common/constants.h" #include "platform/MSWindowsScreen.h" #include "synergy/App.h" #include "synergy/ArgsBase.h" diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 045ff2344..40e012f62 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -148,12 +148,10 @@ macro(config_test_deps) set(test_libs gtest gmock - global arch base client server - common io net platform diff --git a/src/test/integtests/gui/dotenv_tests.cpp b/src/test/integtests/gui/dotenv_tests.cpp index fd70854ed..8db1515c1 100644 --- a/src/test/integtests/gui/dotenv_tests.cpp +++ b/src/test/integtests/gui/dotenv_tests.cpp @@ -22,8 +22,16 @@ #include +TEST(dotenv_tests, dotenv_fileDoesNotExist_doesNotLoadEnvVar) { + const QString envFile = "tmp/test/.env"; + + synergy::gui::dotenv(envFile); + + const QString actualValue = qEnvironmentVariable("TEST_ENV_VAR"); + EXPECT_TRUE(actualValue.isEmpty()); +} + TEST(dotenv_tests, dotenv_envFileWithEntry_loadsEnvVar) { - // Arrange const QString envFile = "tmp/test/.env"; QFile file(envFile); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -42,7 +50,7 @@ TEST(dotenv_tests, dotenv_envFileWithEntry_loadsEnvVar) { synergy::gui::dotenv(envFile); - const QString actualValue = qgetenv(key.toUtf8().constData()); + const QString actualValue = qEnvironmentVariable(qPrintable(key)); EXPECT_EQ("test value", actualValue.toStdString()); QFile::remove(envFile); diff --git a/src/test/integtests/ipc/IpcTests.cpp b/src/test/integtests/ipc/IpcTests.cpp index 10b4c71ac..a2f86a5a6 100644 --- a/src/test/integtests/ipc/IpcTests.cpp +++ b/src/test/integtests/ipc/IpcTests.cpp @@ -27,7 +27,7 @@ #include "base/String.h" #include "base/TMethodEventJob.h" #include "base/TMethodJob.h" -#include "global/Ipc.h" +#include "common/ipc.h" #include "ipc/IpcClient.h" #include "ipc/IpcClientProxy.h" #include "ipc/IpcMessage.h" diff --git a/src/test/unittests/gui/LoggerTests.cpp b/src/test/unittests/gui/LoggerTests.cpp new file mode 100644 index 000000000..a572e5c86 --- /dev/null +++ b/src/test/unittests/gui/LoggerTests.cpp @@ -0,0 +1,58 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2024 Symless Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "gui/Logger.h" + +#include "gmock/gmock.h" +#include + +using namespace testing; +using namespace synergy::gui; + +TEST(LoggerTests, handleMessage_withDebugEnvVarOn_emitsNewLine) { + Logger logger; + std::string newLineEmitted; + QObject::connect( + &logger, &Logger::newLine, // + [&newLineEmitted](const QString &line) { + newLineEmitted = line.toStdString(); + }); + qputenv("SYNERGY_GUI_DEBUG", "true"); + logger.loadEnvVars(); + + logger.handleMessage(QtDebugMsg, QMessageLogContext(), "test"); + + EXPECT_THAT(newLineEmitted, HasSubstr("test")); + + qputenv("SYNERGY_GUI_DEBUG", ""); +} + +TEST(LoggerTests, handleMessage_withDebugEnvVarOff_doesNotEmitNewLine) { + Logger logger; + bool newLineEmitted = false; + QObject::connect( + &logger, &Logger::newLine, // + [&newLineEmitted](const QString &line) { newLineEmitted = true; }); + qputenv("SYNERGY_GUI_DEBUG", "false"); + logger.loadEnvVars(); + + logger.handleMessage(QtDebugMsg, QMessageLogContext(), "test"); + + EXPECT_FALSE(newLineEmitted); + + qputenv("SYNERGY_GUI_DEBUG", ""); +}