diff --git a/src/lib/arch/IArchLog.h b/src/lib/arch/IArchLog.h index fd70d96e4..8fbee8632 100644 --- a/src/lib/arch/IArchLog.h +++ b/src/lib/arch/IArchLog.h @@ -1,6 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -41,6 +41,6 @@ public: /*! Writes the given string to the log with the given level. */ - virtual void writeLog(LogLevel, const QString &) = 0; + virtual void writeLog(LogLevel::Level, const QString &) = 0; //@} }; diff --git a/src/lib/arch/unix/ArchLogUnix.cpp b/src/lib/arch/unix/ArchLogUnix.cpp index 744a78b01..d6d5a8ea2 100644 --- a/src/lib/arch/unix/ArchLogUnix.cpp +++ b/src/lib/arch/unix/ArchLogUnix.cpp @@ -1,5 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -23,12 +24,12 @@ void ArchLogUnix::closeLog() closelog(); } -void ArchLogUnix::writeLog(LogLevel level, const QString &msg) +void ArchLogUnix::writeLog(LogLevel::Level level, const QString &msg) { // convert level int priority; switch (level) { - using enum LogLevel; + using enum LogLevel::Level; case Error: priority = LOG_ERR; break; diff --git a/src/lib/arch/unix/ArchLogUnix.h b/src/lib/arch/unix/ArchLogUnix.h index f870861db..12856e2b7 100644 --- a/src/lib/arch/unix/ArchLogUnix.h +++ b/src/lib/arch/unix/ArchLogUnix.h @@ -1,5 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -21,5 +22,5 @@ public: // IArchLog overrides void openLog(const QString &name) override; void closeLog() override; - void writeLog(LogLevel, const QString &) override; + void writeLog(LogLevel::Level, const QString &) override; }; diff --git a/src/lib/arch/win32/ArchLogWindows.cpp b/src/lib/arch/win32/ArchLogWindows.cpp index cbef391fd..4462e42a1 100644 --- a/src/lib/arch/win32/ArchLogWindows.cpp +++ b/src/lib/arch/win32/ArchLogWindows.cpp @@ -1,5 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -33,17 +34,17 @@ void ArchLogWindows::closeLog() } } -void ArchLogWindows::writeLog(LogLevel level, const QString &msg) +void ArchLogWindows::writeLog(LogLevel::Level level, const QString &msg) { if (m_eventLog != nullptr) { // convert priority WORD type; switch (level) { - case LogLevel::Error: + case LogLevel::Level::Error: type = EVENTLOG_ERROR_TYPE; break; - case LogLevel::Warning: + case LogLevel::Level::Warning: type = EVENTLOG_WARNING_TYPE; break; diff --git a/src/lib/arch/win32/ArchLogWindows.h b/src/lib/arch/win32/ArchLogWindows.h index ff2c226d5..0ba49e906 100644 --- a/src/lib/arch/win32/ArchLogWindows.h +++ b/src/lib/arch/win32/ArchLogWindows.h @@ -1,5 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -24,7 +25,7 @@ public: // IArchLog overrides void openLog(const QString &name) override; void closeLog() override; - void writeLog(LogLevel, const QString &) override; + void writeLog(LogLevel::Level, const QString &) override; private: HANDLE m_eventLog; diff --git a/src/lib/base/ILogOutputter.h b/src/lib/base/ILogOutputter.h index 9e3fda0e2..086e185bd 100644 --- a/src/lib/base/ILogOutputter.h +++ b/src/lib/base/ILogOutputter.h @@ -1,6 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -46,7 +46,7 @@ public: message to all outputters in the outputter chain, otherwise it continues. Most implementations should return true. */ - virtual bool write(LogLevel level, const QString &message) = 0; + virtual bool write(LogLevel::Level level, const QString &message) = 0; //@} }; diff --git a/src/lib/base/Log.cpp b/src/lib/base/Log.cpp index 66cdac530..7a0818edf 100644 --- a/src/lib/base/Log.cpp +++ b/src/lib/base/Log.cpp @@ -1,5 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -36,14 +37,14 @@ static const int g_numPriority = 6; // for visual studio, then NDEBUG will be set (even if your VS solution // config is Debug). #ifndef NDEBUG -static const LogLevel g_defaultMaxPriority = LogLevel::Debug; +static const auto g_defaultMaxPriority = LogLevel::Level::Debug; #else -static const LogLevel g_defaultMaxPriority = LogLevel::Info; +static const auto g_defaultMaxPriority = LogLevel::Level::Info; #endif namespace { -LogLevel getPriority(const char *&fmt) +LogLevel::Level getPriority(const char *&fmt) { if (strnlen(fmt, SIZE_MAX) < kPriorityPrefixLength) { throw std::invalid_argument("invalid format string, too short"); @@ -53,10 +54,10 @@ LogLevel getPriority(const char *&fmt) throw std::invalid_argument("invalid format string, missing priority"); } - return static_cast(fmt[2] - '0'); + return static_cast(fmt[2] - '0'); } -std::vector makeMessage(const char *filename, int lineNumber, const char *message, LogLevel priority) +std::vector makeMessage(const char *filename, int lineNumber, const char *message, LogLevel::Level priority) { // base size includes null terminator, colon, space, etc. @@ -150,7 +151,7 @@ const char *Log::getFilterName() const return getFilterName(getFilter()); } -const char *Log::getFilterName(LogLevel level) const +const char *Log::getFilterName(LogLevel::Level level) const { const auto levelIndex = static_cast(level); if (levelIndex < 0) { @@ -164,7 +165,7 @@ void Log::print(const char *file, int line, const char *fmt, ...) const int initBufferSize = 1024; const int bufferResizeScale = 2; - LogLevel priority = getPriority(fmt); + const auto priority = getPriority(fmt); fmt += kPriorityPrefixLength; if (priority > getFilter()) { @@ -188,7 +189,7 @@ void Log::print(const char *file, int line, const char *fmt, ...) } } - if (priority == LogLevel::Print) { + if (priority == LogLevel::Level::Print) { output(priority, buffer.data()); } else { auto message = makeMessage(file, line, buffer.data(), priority); @@ -235,26 +236,26 @@ bool Log::setFilter(const QString &maxPriority) for (int i = 0; i < g_numPriority; ++i) { if (maxPriority == QString(g_priority[i])) { - setFilter(static_cast(i)); + setFilter(static_cast(i)); return true; } } return false; } -void Log::setFilter(LogLevel maxPriority) +void Log::setFilter(LogLevel::Level maxPriority) { std::scoped_lock lock{m_mutex}; m_maxPriority = maxPriority; } -LogLevel Log::getFilter() const +LogLevel::Level Log::getFilter() const { std::scoped_lock lock{m_mutex}; return m_maxPriority; } -void Log::output(LogLevel priority, const char *msg) +void Log::output(LogLevel::Level priority, const char *msg) { assert(static_cast(priority) >= -2 && static_cast(priority) < g_numPriority); assert(msg != nullptr); diff --git a/src/lib/base/Log.h b/src/lib/base/Log.h index 38573faae..af85be4a2 100644 --- a/src/lib/base/Log.h +++ b/src/lib/base/Log.h @@ -1,5 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers. * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -88,7 +89,7 @@ public: bool setFilter(const QString &name); //! Set the minimum priority filter (by ordinal). - void setFilter(LogLevel); + void setFilter(LogLevel::Level); //@} //! @name accessors @@ -103,28 +104,28 @@ public: void print(const char *file, int line, const char *format, ...); //! Get the minimum priority level. - LogLevel getFilter() const; + LogLevel::Level getFilter() const; //! Get the filter name of the current filter level. const char *getFilterName() const; //! Get the filter name of a specified filter level. - const char *getFilterName(LogLevel level) const; + const char *getFilterName(LogLevel::Level level) const; //! Get the singleton instance of the log static Log *getInstance(); //! Get the console filter level (messages above this are not sent to //! console). - LogLevel getConsoleMaxLevel() const + LogLevel::Level getConsoleMaxLevel() const { - return LogLevel::Verbose; + return LogLevel::Level::Verbose; } //@} private: - void output(LogLevel priority, const char *msg); + void output(LogLevel::Level priority, const char *msg); private: using OutputterList = std::list; @@ -134,7 +135,7 @@ private: mutable std::mutex m_mutex; OutputterList m_outputters; OutputterList m_alwaysOutputters; - LogLevel m_maxPriority; + LogLevel::Level m_maxPriority; }; /*! diff --git a/src/lib/base/LogOutputters.cpp b/src/lib/base/LogOutputters.cpp index 82dd351ef..6ef7ec97e 100644 --- a/src/lib/base/LogOutputters.cpp +++ b/src/lib/base/LogOutputters.cpp @@ -1,6 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -31,7 +31,7 @@ void StopLogOutputter::close() // do nothing } -bool StopLogOutputter::write(LogLevel, const QString &) +bool StopLogOutputter::write(LogLevel::Level, const QString &) { return false; } @@ -50,9 +50,10 @@ void ConsoleLogOutputter::close() // do nothing } -bool ConsoleLogOutputter::write(LogLevel level, const QString &msg) +bool ConsoleLogOutputter::write(LogLevel::Level level, const QString &msg) { - if ((level >= LogLevel::Fatal) && (level <= LogLevel::Warning)) + using enum LogLevel::Level; + if ((level >= Fatal) && (level <= Warning)) std::cerr << qPrintable(msg) << std::endl; else std::cout << qPrintable(msg) << std::endl; @@ -79,7 +80,7 @@ void SystemLogOutputter::close() ARCH->closeLog(); } -bool SystemLogOutputter::write(LogLevel level, const QString &msg) +bool SystemLogOutputter::write(LogLevel::Level level, const QString &msg) { ARCH->writeLog(level, msg); return true; @@ -126,7 +127,7 @@ void FileLogOutputter::setLogFilename(const QString &logFile) m_fileName = logFile; } -bool FileLogOutputter::write(LogLevel, const QString &message) +bool FileLogOutputter::write(LogLevel::Level, const QString &message) { QFile file(m_fileName); if (!file.open(QFile::WriteOnly | QFile::Append)) diff --git a/src/lib/base/LogOutputters.h b/src/lib/base/LogOutputters.h index 5c82d50da..30b10048b 100644 --- a/src/lib/base/LogOutputters.h +++ b/src/lib/base/LogOutputters.h @@ -1,6 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -26,7 +26,7 @@ public: // ILogOutputter overrides void open(const QString &title) override; void close() override; - bool write(LogLevel level, const QString &message) override; + bool write(LogLevel::Level level, const QString &message) override; }; //! Write log to console @@ -43,7 +43,7 @@ public: // ILogOutputter overrides void open(const QString &title) override; void close() override; - bool write(LogLevel level, const QString &message) override; + bool write(LogLevel::Level level, const QString &message) override; void flush() const; }; @@ -62,7 +62,7 @@ public: // ILogOutputter overrides void open(const QString &title) override; void close() override; - bool write(LogLevel level, const QString &message) override; + bool write(LogLevel::Level level, const QString &message) override; void setLogFilename(const QString &title); @@ -83,7 +83,7 @@ public: // ILogOutputter overrides void open(const QString &title) override; void close() override; - bool write(LogLevel level, const QString &message) override; + bool write(LogLevel::Level level, const QString &message) override; }; //! Write log to system log only diff --git a/src/lib/common/LogLevel.h b/src/lib/common/LogLevel.h index ebe310ee0..a6e790a85 100644 --- a/src/lib/common/LogLevel.h +++ b/src/lib/common/LogLevel.h @@ -1,23 +1,101 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ #pragma once +#include +#include -//! Log levels -/*! -The logging priority levels in order of highest to lowest priority. -*/ -enum class LogLevel +class LogLevel : private QObject { - Print = -1, //!< For print only (no file or time) - Fatal, //!< For fatal errors - Error, //!< For serious errors - Warning, //!< For minor errors and warnings - Info, //!< For informational messages - Debug, //!< For important debugging messages - Verbose //!< For verbose debugging messages + Q_OBJECT + //! Log levels + /*! + The logging priority levels in order of highest to lowest priority. + */ +public: + enum class Level + { + Print = -1, //!< For print only (no file or time) + Fatal, //!< For fatal errors + Error, //!< For serious errors + Warning, //!< For minor errors and warnings + Info, //!< For informational messages + Debug, //!< For important debugging messages + Verbose //!< For verbose debugging messages + }; + Q_ENUM(Level) + + static QString toOption(const LogLevel::Level &level) + { + return toOption(static_cast(level)); + } + + static QString toOption(const int &level) + { + if (level < 0 || level > m_levelOptions.size()) + return ""; + return m_levelOptions.at(level); + } + + static LogLevel::Level fromOption(const QString &level) + { + const auto index = m_levelOptions.indexOf(level, 0, Qt::CaseInsensitive); + if (index < 0 || index >= m_levelOptions.count()) + return LogLevel::Level::Info; + return LogLevel::Level(index); + } + + static QString toString(const LogLevel::Level &level) + { + return toString(static_cast(level)); + } + + static QString toString(const int &level) + { + if (level < 0 || level > m_levelNames.size()) + return ""; + return tr(m_levelNames.at(level).toUtf8()); + } + + static QStringList logLevelOptions() + { + return m_levelOptions; + } + + static QStringList logLevelNames() + { + return m_levelNames; + } + +private: + // clang-format off + /** + * @brief m_levelOptions, Valid values for the log level options, Never translated + */ + inline static const QStringList m_levelOptions { + QStringLiteral("FATAL") + , QStringLiteral("ERROR") + , QStringLiteral("WARNING") + , QStringLiteral("INFO") + , QStringLiteral("DEBUG") + , QStringLiteral("VERBOSE") + }; + + /** + * @brief m_levelNames, Strings used to present level names to the user, Expected to be translated + */ + inline static const QStringList m_levelNames = { + QT_TR_NOOP("Fatal") + , QT_TR_NOOP("Error") + , QT_TR_NOOP("Warning") + , QT_TR_NOOP("Info") + , QT_TR_NOOP("Debug") + , QT_TR_NOOP("Verbose") + }; + // clang-format on }; diff --git a/src/lib/common/Settings.cpp b/src/lib/common/Settings.cpp index aec4024e9..d35b4d38a 100644 --- a/src/lib/common/Settings.cpp +++ b/src/lib/common/Settings.cpp @@ -6,6 +6,7 @@ #include "Settings.h" +#include "LogLevel.h" #include "NetworkProtocol.h" #include "UrlConstants.h" @@ -95,6 +96,10 @@ Settings::Settings(QObject *parent) : QObject(parent) void Settings::upgradeSettings() { + const auto logValue = m_settings->value(Settings::Log::Level).toString(); + if (!LogLevel::logLevelOptions().contains(logValue, Qt::CaseInsensitive)) + m_settings->setValue(Settings::Log::Level, defaultValue(Settings::Log::Level)); + for (const auto [oldKey, newKey] : m_upgradedMap.asKeyValueRange()) { if (m_settings->contains(oldKey) && !m_settings->contains(newKey)) { m_settings->setValue(newKey, m_settings->value(oldKey)); @@ -156,13 +161,6 @@ QString Settings::cleanComputerName(const QString &name) return cleanName; } -int Settings::logLevelToInt(const QString &level) -{ - if (level.isEmpty() || !m_logLevels.contains(level, Qt::CaseInsensitive)) - return 4; - return static_cast(m_logLevels.indexOf(level, 0, Qt::CaseInsensitive)); -} - QVariant Settings::defaultValue(const QString &key) { if (m_defaultFalseValues.contains(key)) @@ -181,7 +179,7 @@ QVariant Settings::defaultValue(const QString &key) return QStringLiteral("%1/%2.log").arg(QDir::homePath(), kAppId); if (key == Log::Level) - return 4; // INFO + return QVariant::fromValue(LogLevel::Level::Info).toString(); if (key == Daemon::Elevate) return !Settings::isPortableMode(); @@ -215,11 +213,6 @@ QVariant Settings::defaultValue(const QString &key) return QVariant(); } -QString Settings::logLevelText() -{ - return Settings::m_logLevels.at(Settings::value(Log::Level).toInt()); -} - QSettingsProxy &Settings::proxy() { return *instance()->m_settingsProxy; @@ -291,6 +284,11 @@ QString Settings::tlsTrustedClientsDb() return QFileInfo(QStringLiteral("%1/trusted-clients").arg(instance()->tlsDir())).absoluteFilePath(); } +QString Settings::logLevelText() +{ + return Settings::value(Log::Level).toString(); +} + void Settings::setValue(const QString &key, const QVariant &value) { const bool useState = Settings::m_stateKeys.contains(key) && !instance()->isPortableMode(); diff --git a/src/lib/common/Settings.h b/src/lib/common/Settings.h index 4000f8fac..5d0aca963 100644 --- a/src/lib/common/Settings.h +++ b/src/lib/common/Settings.h @@ -151,7 +151,6 @@ public: static QSettingsProxy &proxy(); static void save(bool emitSaving = true); static QStringList validKeys(); - static int logLevelToInt(const QString &level); static QString portableSettingsFile(); Q_SIGNALS: @@ -190,15 +189,6 @@ private: std::shared_ptr m_settingsProxy; // clang-format off - inline static const QStringList m_logLevels = { - QStringLiteral("FATAL") - , QStringLiteral("ERROR") - , QStringLiteral("WARNING") - , QStringLiteral("INFO") - , QStringLiteral("DEBUG") - , QStringLiteral("TRACE") - }; - inline static const QStringList m_validKeys = { Settings::Client::DynamicConnectionRetry , Settings::Client::InvertYScroll diff --git a/src/lib/gui/dialogs/SettingsDialog.cpp b/src/lib/gui/dialogs/SettingsDialog.cpp index b491630c1..4518e5899 100644 --- a/src/lib/gui/dialogs/SettingsDialog.cpp +++ b/src/lib/gui/dialogs/SettingsDialog.cpp @@ -7,6 +7,7 @@ */ #include "SettingsDialog.h" +#include "common/LogLevel.h" #include "common/PlatformInfo.h" #include "ui_SettingsDialog.h" @@ -216,7 +217,9 @@ void SettingsDialog::accept() { Settings::setValue(Settings::Core::Port, ui->sbPort->value()); Settings::setValue(Settings::Core::Interface, ui->comboInterface->currentData()); - Settings::setValue(Settings::Log::Level, ui->comboLogLevel->currentIndex()); + Settings::setValue( + Settings::Log::Level, LogLevel::toOption(static_cast(ui->comboLogLevel->currentIndex())) + ); Settings::setValue(Settings::Log::ToFile, ui->groupLogToFile->isChecked()); Settings::setValue(Settings::Log::File, ui->lineLogFilename->text()); Settings::setValue(Settings::Daemon::Elevate, ui->cbElevateDaemon->isChecked()); @@ -251,7 +254,7 @@ void SettingsDialog::accept() void SettingsDialog::loadFromConfig() { ui->sbPort->setValue(Settings::value(Settings::Core::Port).toInt()); - ui->comboLogLevel->setCurrentIndex(Settings::value(Settings::Log::Level).toInt()); + ui->comboLogLevel->setCurrentIndex(static_cast(LogLevel::fromOption(Settings::logLevelText()))); ui->groupLogToFile->setChecked(Settings::value(Settings::Log::ToFile).toBool()); ui->lineLogFilename->setText(Settings::value(Settings::Log::File).toString()); ui->cbPreventSleep->setChecked(Settings::value(Settings::Core::PreventSleep).toBool()); @@ -284,7 +287,9 @@ void SettingsDialog::loadFromConfig() ui->rbCloseToTray->setChecked(closeToTray); ui->rbExitOnClose->setChecked(!closeToTray); - ui->lblDebugWarning->setVisible(Settings::value(Settings::Log::Level).toInt() > 3); + ui->lblDebugWarning->setVisible( + Settings::value(Settings::Log::Level).toInt() > static_cast(LogLevel::Level::Info) + ); ui->comboInterface->setCurrentText(Settings::value(Settings::Core::Interface).toString()); if (ui->comboInterface->currentIndex() <= 0) { @@ -409,7 +414,7 @@ void SettingsDialog::updateRequestedKeySize() const void SettingsDialog::logLevelChanged() { - ui->lblDebugWarning->setVisible(ui->comboLogLevel->currentIndex() > 3); + ui->lblDebugWarning->setVisible(ui->comboLogLevel->currentIndex() > static_cast(LogLevel::Level::Info)); } bool SettingsDialog::isModified() const @@ -419,7 +424,7 @@ bool SettingsDialog::isModified() const bool modified = (ui->sbPort->value() != Settings::value(Settings::Core::Port).toInt()) || - (ui->comboLogLevel->currentIndex() != Settings::value(Settings::Log::Level).toInt()) || + (ui->comboLogLevel->currentIndex() != static_cast(LogLevel::fromOption(Settings::logLevelText()))) || (ui->groupLogToFile->isChecked() != Settings::value(Settings::Log::ToFile).toBool()) || (ui->lineLogFilename->text() != Settings::value(Settings::Log::File).toString()) || (ui->rbAutoHide->isChecked() != Settings::value(Settings::Gui::Autohide).toBool()) || @@ -450,10 +455,12 @@ bool SettingsDialog::isModified() const bool SettingsDialog::isDefault() const { const auto processMode = Settings::defaultValue(Settings::Core::ProcessMode).value(); + const auto logLevelIndex = + static_cast(LogLevel::fromOption(Settings::defaultValue(Settings::Log::Level).toString())); return ( (ui->sbPort->value() == Settings::defaultValue(Settings::Core::Port).toInt()) && - (ui->comboLogLevel->currentIndex() == Settings::defaultValue(Settings::Log::Level).toInt()) && + (ui->comboLogLevel->currentIndex() == logLevelIndex) && (ui->groupLogToFile->isChecked() == Settings::defaultValue(Settings::Log::ToFile).toBool()) && (ui->lineLogFilename->text() == Settings::defaultValue(Settings::Log::File).toString()) && (ui->rbAutoHide->isChecked() == Settings::defaultValue(Settings::Gui::Autohide).toBool()) && @@ -482,7 +489,9 @@ bool SettingsDialog::isDefault() const void SettingsDialog::resetToDefault() { ui->sbPort->setValue(Settings::defaultValue(Settings::Core::Port).toInt()); - ui->comboLogLevel->setCurrentIndex(Settings::defaultValue(Settings::Log::Level).toInt()); + ui->comboLogLevel->setCurrentIndex( + static_cast(LogLevel::fromOption(Settings::defaultValue(Settings::Log::Level).toString())) + ); ui->groupLogToFile->setChecked(Settings::defaultValue(Settings::Log::ToFile).toBool()); ui->lineLogFilename->setText(Settings::defaultValue(Settings::Log::File).toString()); ui->cbPreventSleep->setChecked(Settings::defaultValue(Settings::Core::PreventSleep).toBool()); diff --git a/src/lib/net/SslLogger.cpp b/src/lib/net/SslLogger.cpp index aedbefeab..8ba94d7e3 100644 --- a/src/lib/net/SslLogger.cpp +++ b/src/lib/net/SslLogger.cpp @@ -66,7 +66,7 @@ void logRemoteSecureCipherInfo(const SSL *ssl) void SslLogger::logSecureLibInfo() { - if (CLOG->getFilter() >= LogLevel::Debug) { + if (CLOG->getFilter() >= LogLevel::Level::Debug) { LOG_DEBUG("openssl version: %s", SSLeay_version(SSLEAY_VERSION)); LOG_VERBOSE("openssl flags: %s", SSLeay_version(SSLEAY_CFLAGS)); LOG_VERBOSE("openssl built on: %s", SSLeay_version(SSLEAY_BUILT_ON)); @@ -77,7 +77,7 @@ void SslLogger::logSecureLibInfo() void SslLogger::logSecureCipherInfo(const SSL *ssl) { - if (ssl && CLOG->getFilter() >= LogLevel::Verbose) { + if (ssl && CLOG->getFilter() >= LogLevel::Level::Verbose) { logLocalSecureCipherInfo(ssl); logRemoteSecureCipherInfo(ssl); } diff --git a/src/lib/platform/MSWindowsDebugOutputter.cpp b/src/lib/platform/MSWindowsDebugOutputter.cpp index 4e901df0d..401c49d9a 100644 --- a/src/lib/platform/MSWindowsDebugOutputter.cpp +++ b/src/lib/platform/MSWindowsDebugOutputter.cpp @@ -22,7 +22,7 @@ void MSWindowsDebugOutputter::close() // do nothing } -bool MSWindowsDebugOutputter::write(LogLevel level, const QString &msg) +bool MSWindowsDebugOutputter::write(LogLevel::Level level, const QString &msg) { std::wstring out = msg.toStdWString() + L"\n"; OutputDebugString(out.c_str()); diff --git a/src/lib/platform/MSWindowsDebugOutputter.h b/src/lib/platform/MSWindowsDebugOutputter.h index 671006937..a4532bba8 100644 --- a/src/lib/platform/MSWindowsDebugOutputter.h +++ b/src/lib/platform/MSWindowsDebugOutputter.h @@ -23,6 +23,6 @@ public: // ILogOutputter overrides void open(const QString &title) override; void close() override; - bool write(LogLevel level, const QString &message) override; + bool write(LogLevel::Level level, const QString &message) override; void flush(); }; diff --git a/src/lib/platform/MSWindowsWatchdog.cpp b/src/lib/platform/MSWindowsWatchdog.cpp index bb8c98e3f..b7b9ad876 100644 --- a/src/lib/platform/MSWindowsWatchdog.cpp +++ b/src/lib/platform/MSWindowsWatchdog.cpp @@ -355,7 +355,7 @@ void MSWindowsWatchdog::outputLoop(const void *) // The file log outputter adds its own newlines, so trim the decoded string to avoid double newlines. const auto trimmed = decoded.trimmed(); - m_fileLogOutputter.write(LogLevel::Print, trimmed); + m_fileLogOutputter.write(LogLevel::Level::Print, trimmed); if (m_foreground) { // Doesn't add it's own newlines, so use the original ones from the process output. diff --git a/src/lib/platform/XWindowsClipboard.cpp b/src/lib/platform/XWindowsClipboard.cpp index 567a72d86..2bde9aa27 100644 --- a/src/lib/platform/XWindowsClipboard.cpp +++ b/src/lib/platform/XWindowsClipboard.cpp @@ -5,10 +5,11 @@ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ -#include "platform/XWindowsClipboard.h" - #include "arch/Arch.h" #include "base/Log.h" + +#include "platform/XWindowsClipboard.h" + #include "base/Stopwatch.h" #include "platform/XWindowsClipboardBMPConverter.h" #include "platform/XWindowsClipboardHTMLConverter.h" @@ -1000,7 +1001,7 @@ bool XWindowsClipboard::sendReply(Reply *reply) reply->m_replied = true; // nothing to log - if (CLOG->getFilter() < LogLevel::Verbose) { + if (CLOG->getFilter() < LogLevel::Level::Verbose) { sendNotify( reply->m_requestor, m_selection, reply->m_target, reply->m_property, static_cast(reply->m_time) ); diff --git a/src/unittests/base/LogTests.cpp b/src/unittests/base/LogTests.cpp index 3096f99ea..cb5ca3bac 100644 --- a/src/unittests/base/LogTests.cpp +++ b/src/unittests/base/LogTests.cpp @@ -25,7 +25,7 @@ QString sanitizeBuffer(const std::stringstream &in) void LogTests::initTestCase() { std::setlocale(LC_NUMERIC, "C"); - m_log.setFilter(LogLevel::Debug); + m_log.setFilter(LogLevel::Level::Debug); } void LogTests::printWithErrorValidOutput() diff --git a/src/unittests/base/UnicodeTests.cpp b/src/unittests/base/UnicodeTests.cpp index 18d984fe0..2e0af5649 100644 --- a/src/unittests/base/UnicodeTests.cpp +++ b/src/unittests/base/UnicodeTests.cpp @@ -11,7 +11,7 @@ void UnicodeTests::initTestCase() { - m_log.setFilter(LogLevel::Verbose); + m_log.setFilter(LogLevel::Level::Verbose); } void UnicodeTests::UTF16ToUTF8() diff --git a/src/unittests/common/CMakeLists.txt b/src/unittests/common/CMakeLists.txt index 590b50a7f..12f66e599 100644 --- a/src/unittests/common/CMakeLists.txt +++ b/src/unittests/common/CMakeLists.txt @@ -8,6 +8,13 @@ create_test( WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/common" ) +create_test( + NAME LogLevelTests + DEPENDS common + SOURCE LogLevelTests.cpp + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/common" +) + create_test( NAME I18NTests DEPENDS common diff --git a/src/unittests/common/LogLevelTests.cpp b/src/unittests/common/LogLevelTests.cpp new file mode 100644 index 000000000..a256eddee --- /dev/null +++ b/src/unittests/common/LogLevelTests.cpp @@ -0,0 +1,33 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include "LogLevelTests.h" + +#include +#include + +#include "common/LogLevel.h" + +void LogLevelTests::checkLogLevels_Valid() +{ + QCOMPARE(LogLevel::fromOption(QStringLiteral("Fatal")), LogLevel::Level::Fatal); + QCOMPARE(LogLevel::fromOption(QStringLiteral("erRor")), LogLevel::Level::Error); + QCOMPARE(LogLevel::fromOption(QStringLiteral("wArning")), LogLevel::Level::Warning); + QCOMPARE(LogLevel::fromOption(QStringLiteral("info")), LogLevel::Level::Info); + QCOMPARE(LogLevel::fromOption("deBug"), LogLevel::Level::Debug); + QCOMPARE(LogLevel::fromOption("TraCe"), LogLevel::Level::Verbose); +} + +void LogLevelTests::checkLogLevels_Invalid() +{ + QCOMPARE(LogLevel::fromOption({}), LogLevel::Level::Info); + QCOMPARE(LogLevel::fromOption(QStringLiteral("INVALID")), LogLevel::Level::Info); + QCOMPARE(LogLevel::fromOption(QStringLiteral("deBug3")), LogLevel::Level::Info); + QCOMPARE(LogLevel::fromOption(QStringLiteral("infomatic")), LogLevel::Level::Info); + QCOMPARE(LogLevel::fromOption(QStringLiteral("warn")), LogLevel::Level::Info); +} + +QTEST_MAIN(LogLevelTests) diff --git a/src/unittests/common/LogLevelTests.h b/src/unittests/common/LogLevelTests.h new file mode 100644 index 000000000..69ce967ff --- /dev/null +++ b/src/unittests/common/LogLevelTests.h @@ -0,0 +1,14 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ +#include + +class LogLevelTests : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void checkLogLevels_Valid(); + void checkLogLevels_Invalid(); +}; diff --git a/src/unittests/common/SettingsTests.cpp b/src/unittests/common/SettingsTests.cpp index 9ecb351eb..07fca577b 100644 --- a/src/unittests/common/SettingsTests.cpp +++ b/src/unittests/common/SettingsTests.cpp @@ -101,23 +101,4 @@ void SettingsTests::checkCleanScreenName_LongName() QCOMPARE(Settings::value(Settings::Core::ComputerName).toString(), expected); } -void SettingsTests::checkLogLevels_Valid() -{ - QCOMPARE(Settings::logLevelToInt(QStringLiteral("Fatal")), 0); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("erRor")), 1); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("wArning")), 2); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("info")), 3); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("deBug")), 4); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("TraCe")), 5); -} - -void SettingsTests::checkLogLevels_Invalid() -{ - QCOMPARE(Settings::logLevelToInt(QString()), 4); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("INVALID")), 4); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("debug3")), 4); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("infomatic")), 4); - QCOMPARE(Settings::logLevelToInt(QStringLiteral("warn")), 4); -} - QTEST_MAIN(SettingsTests) diff --git a/src/unittests/common/SettingsTests.h b/src/unittests/common/SettingsTests.h index 9e955e139..17384bd6d 100644 --- a/src/unittests/common/SettingsTests.h +++ b/src/unittests/common/SettingsTests.h @@ -24,8 +24,6 @@ private Q_SLOTS: void checkValidSettings(); void checkCleanScreenName(); void checkCleanScreenName_LongName(); - void checkLogLevels_Valid(); - void checkLogLevels_Invalid(); private: inline static const QString m_settingsPathTemp = QStringLiteral("tmp/test"); diff --git a/src/unittests/deskflow/ClipboardTests.cpp b/src/unittests/deskflow/ClipboardTests.cpp index c25db3b1e..dc362b6a4 100644 --- a/src/unittests/deskflow/ClipboardTests.cpp +++ b/src/unittests/deskflow/ClipboardTests.cpp @@ -12,7 +12,7 @@ void ClipboardTests::initTestCase() { - m_log.setFilter(LogLevel::Verbose); + m_log.setFilter(LogLevel::Level::Verbose); } void ClipboardTests::basicFunction() diff --git a/src/unittests/deskflow/KeyboardLayoutManagerTests.cpp b/src/unittests/deskflow/KeyboardLayoutManagerTests.cpp index 063439e0a..313daee2d 100644 --- a/src/unittests/deskflow/KeyboardLayoutManagerTests.cpp +++ b/src/unittests/deskflow/KeyboardLayoutManagerTests.cpp @@ -11,7 +11,7 @@ void KeyboardLayoutManagerTests::initTestCase() { - m_log.setFilter(LogLevel::Verbose); + m_log.setFilter(LogLevel::Level::Verbose); } void KeyboardLayoutManagerTests::remoteLayouts() diff --git a/src/unittests/legacytests/legacytests/main.cpp b/src/unittests/legacytests/legacytests/main.cpp index 0b91ef3d7..1dda26d1f 100644 --- a/src/unittests/legacytests/legacytests/main.cpp +++ b/src/unittests/legacytests/legacytests/main.cpp @@ -32,7 +32,7 @@ int main(int argc, char **argv) arch.init(); Log log; - log.setFilter(LogLevel::Verbose); + log.setFilter(LogLevel::Level::Verbose); ::testing::GTEST_FLAG(throw_on_failure) = true; testing::InitGoogleTest(&argc, argv); diff --git a/src/unittests/platform/MSWindowsClipboardTests.cpp b/src/unittests/platform/MSWindowsClipboardTests.cpp index 55f032636..0f554dde3 100644 --- a/src/unittests/platform/MSWindowsClipboardTests.cpp +++ b/src/unittests/platform/MSWindowsClipboardTests.cpp @@ -12,7 +12,7 @@ void MSWindowsClipboardTests::initTestCase() { - m_log.setFilter(LogLevel::Verbose); + m_log.setFilter(LogLevel::Level::Verbose); MSWindowsClipboard clipboard(NULL); diff --git a/src/unittests/platform/OSXKeyStateTests.cpp b/src/unittests/platform/OSXKeyStateTests.cpp index 58012d35d..469063b5e 100644 --- a/src/unittests/platform/OSXKeyStateTests.cpp +++ b/src/unittests/platform/OSXKeyStateTests.cpp @@ -19,7 +19,7 @@ void OSXKeyStateTests::initTestCase() { m_arch.init(); - m_log.setFilter(LogLevel::Verbose); + m_log.setFilter(LogLevel::Level::Verbose); } void OSXKeyStateTests::mapModifiersFromOSX_OSXMask() diff --git a/src/unittests/platform/WlClipboardTests.cpp b/src/unittests/platform/WlClipboardTests.cpp index 92f0fd088..fd5eb0c1f 100644 --- a/src/unittests/platform/WlClipboardTests.cpp +++ b/src/unittests/platform/WlClipboardTests.cpp @@ -40,7 +40,7 @@ void WlClipboardTests::isAvailable() void WlClipboardTests::initTestCase() { m_arch.init(); - m_log.setFilter(LogLevel::Verbose); + m_log.setFilter(LogLevel::Level::Verbose); // Only run tests if Wayland clipboard tools are available if (!deskflow::platform::isWayland()) { diff --git a/translations/deskflow_es.ts b/translations/deskflow_es.ts index aa15fe70e..1884479fb 100644 --- a/translations/deskflow_es.ts +++ b/translations/deskflow_es.ts @@ -300,6 +300,33 @@ Do you want to connect to the server? Adjuntar a la ventana + + LogLevel + + Fatal + Fatal + + + Error + Error + + + Warning + Advertencia + + + Info + Información + + + Debug + Depurar + + + Verbose + Verboso + + MainWindow diff --git a/translations/deskflow_it.ts b/translations/deskflow_it.ts index 1d43b0289..ee1877cd9 100644 --- a/translations/deskflow_it.ts +++ b/translations/deskflow_it.ts @@ -300,6 +300,33 @@ Vuoi connetterti al server? Allega alla finestra + + LogLevel + + Fatal + Fatale + + + Error + Errore + + + Warning + Avviso + + + Info + Informazioni + + + Debug + Debug + + + Verbose + Verboso + + MainWindow diff --git a/translations/deskflow_ja.ts b/translations/deskflow_ja.ts index 64c8882d9..c68e23dea 100644 --- a/translations/deskflow_ja.ts +++ b/translations/deskflow_ja.ts @@ -300,6 +300,33 @@ Do you want to connect to the server? ウィンドウに結合 + + LogLevel + + Fatal + 重大 + + + Error + エラー + + + Warning + 警告 + + + Info + 情報 + + + Debug + デバッグ + + + Verbose + 冗長 + + MainWindow diff --git a/translations/deskflow_ko.ts b/translations/deskflow_ko.ts index 66f43931d..3c3b0708a 100644 --- a/translations/deskflow_ko.ts +++ b/translations/deskflow_ko.ts @@ -300,6 +300,33 @@ Do you want to connect to the server? 창에 붙이기 + + LogLevel + + Fatal + 치명적 오류 + + + Error + 오류 + + + Warning + 경고 + + + Info + 정보 + + + Debug + 디버그 + + + Verbose + 말 수가 많은 + + MainWindow diff --git a/translations/deskflow_ru.ts b/translations/deskflow_ru.ts index 0d41be131..62b29d24f 100644 --- a/translations/deskflow_ru.ts +++ b/translations/deskflow_ru.ts @@ -300,6 +300,33 @@ Do you want to connect to the server? Прикрепить к окну + + LogLevel + + Fatal + Критический + + + Error + Ошибка + + + Warning + Предупреждение + + + Info + Инфо + + + Debug + Отладка + + + Verbose + Многословный + + MainWindow diff --git a/translations/deskflow_zh_CN.ts b/translations/deskflow_zh_CN.ts index b047c5b93..9d818c250 100644 --- a/translations/deskflow_zh_CN.ts +++ b/translations/deskflow_zh_CN.ts @@ -300,6 +300,33 @@ Do you want to connect to the server? 吸附到窗口 + + LogLevel + + Fatal + 致命 + + + Error + 错误 + + + Warning + 警告 + + + Info + 信息 + + + Debug + 调试 + + + Verbose + 冗长的 + + MainWindow