refactor(log): Convert LogLevel into a class using LogLevel::Level as its enum, store values as the Option string display as localized string'
This commit is contained in:
parent
b0413ed4ff
commit
acf865fa11
38 changed files with 398 additions and 120 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* 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) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* 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.
|
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;
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -23,12 +24,12 @@ void ArchLogUnix::closeLog()
|
||||||
closelog();
|
closelog();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchLogUnix::writeLog(LogLevel level, const QString &msg)
|
void ArchLogUnix::writeLog(LogLevel::Level level, const QString &msg)
|
||||||
{
|
{
|
||||||
// convert level
|
// convert level
|
||||||
int priority;
|
int priority;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
using enum LogLevel;
|
using enum LogLevel::Level;
|
||||||
case Error:
|
case Error:
|
||||||
priority = LOG_ERR;
|
priority = LOG_ERR;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -21,5 +22,5 @@ public:
|
||||||
// IArchLog overrides
|
// IArchLog overrides
|
||||||
void openLog(const QString &name) override;
|
void openLog(const QString &name) override;
|
||||||
void closeLog() override;
|
void closeLog() override;
|
||||||
void writeLog(LogLevel, const QString &) override;
|
void writeLog(LogLevel::Level, const QString &) override;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* 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) {
|
if (m_eventLog != nullptr) {
|
||||||
// convert priority
|
// convert priority
|
||||||
WORD type;
|
WORD type;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case LogLevel::Error:
|
case LogLevel::Level::Error:
|
||||||
type = EVENTLOG_ERROR_TYPE;
|
type = EVENTLOG_ERROR_TYPE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LogLevel::Warning:
|
case LogLevel::Level::Warning:
|
||||||
type = EVENTLOG_WARNING_TYPE;
|
type = EVENTLOG_WARNING_TYPE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -24,7 +25,7 @@ public:
|
||||||
// IArchLog overrides
|
// IArchLog overrides
|
||||||
void openLog(const QString &name) override;
|
void openLog(const QString &name) override;
|
||||||
void closeLog() override;
|
void closeLog() override;
|
||||||
void writeLog(LogLevel, const QString &) override;
|
void writeLog(LogLevel::Level, const QString &) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HANDLE m_eventLog;
|
HANDLE m_eventLog;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* 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) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* 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
|
message to all outputters in the outputter chain, otherwise
|
||||||
it continues. Most implementations should return true.
|
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;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* 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
|
// for visual studio, then NDEBUG will be set (even if your VS solution
|
||||||
// config is Debug).
|
// config is Debug).
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static const LogLevel g_defaultMaxPriority = LogLevel::Debug;
|
static const auto g_defaultMaxPriority = LogLevel::Level::Debug;
|
||||||
#else
|
#else
|
||||||
static const LogLevel g_defaultMaxPriority = LogLevel::Info;
|
static const auto g_defaultMaxPriority = LogLevel::Level::Info;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
LogLevel getPriority(const char *&fmt)
|
LogLevel::Level getPriority(const char *&fmt)
|
||||||
{
|
{
|
||||||
if (strnlen(fmt, SIZE_MAX) < kPriorityPrefixLength) {
|
if (strnlen(fmt, SIZE_MAX) < kPriorityPrefixLength) {
|
||||||
throw std::invalid_argument("invalid format string, too short");
|
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");
|
throw std::invalid_argument("invalid format string, missing priority");
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<LogLevel>(fmt[2] - '0');
|
return static_cast<LogLevel::Level>(fmt[2] - '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<char> makeMessage(const char *filename, int lineNumber, const char *message, LogLevel priority)
|
std::vector<char> makeMessage(const char *filename, int lineNumber, const char *message, LogLevel::Level priority)
|
||||||
{
|
{
|
||||||
|
|
||||||
// base size includes null terminator, colon, space, etc.
|
// base size includes null terminator, colon, space, etc.
|
||||||
|
|
@ -150,7 +151,7 @@ const char *Log::getFilterName() const
|
||||||
return getFilterName(getFilter());
|
return getFilterName(getFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Log::getFilterName(LogLevel level) const
|
const char *Log::getFilterName(LogLevel::Level level) const
|
||||||
{
|
{
|
||||||
const auto levelIndex = static_cast<int>(level);
|
const auto levelIndex = static_cast<int>(level);
|
||||||
if (levelIndex < 0) {
|
if (levelIndex < 0) {
|
||||||
|
|
@ -164,7 +165,7 @@ void Log::print(const char *file, int line, const char *fmt, ...)
|
||||||
const int initBufferSize = 1024;
|
const int initBufferSize = 1024;
|
||||||
const int bufferResizeScale = 2;
|
const int bufferResizeScale = 2;
|
||||||
|
|
||||||
LogLevel priority = getPriority(fmt);
|
const auto priority = getPriority(fmt);
|
||||||
fmt += kPriorityPrefixLength;
|
fmt += kPriorityPrefixLength;
|
||||||
|
|
||||||
if (priority > getFilter()) {
|
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());
|
output(priority, buffer.data());
|
||||||
} else {
|
} else {
|
||||||
auto message = makeMessage(file, line, buffer.data(), priority);
|
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) {
|
for (int i = 0; i < g_numPriority; ++i) {
|
||||||
if (maxPriority == QString(g_priority[i])) {
|
if (maxPriority == QString(g_priority[i])) {
|
||||||
setFilter(static_cast<LogLevel>(i));
|
setFilter(static_cast<LogLevel::Level>(i));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::setFilter(LogLevel maxPriority)
|
void Log::setFilter(LogLevel::Level maxPriority)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
m_maxPriority = maxPriority;
|
m_maxPriority = maxPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogLevel Log::getFilter() const
|
LogLevel::Level Log::getFilter() const
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
return m_maxPriority;
|
return m_maxPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::output(LogLevel priority, const char *msg)
|
void Log::output(LogLevel::Level priority, const char *msg)
|
||||||
{
|
{
|
||||||
assert(static_cast<int>(priority) >= -2 && static_cast<int>(priority) < g_numPriority);
|
assert(static_cast<int>(priority) >= -2 && static_cast<int>(priority) < g_numPriority);
|
||||||
assert(msg != nullptr);
|
assert(msg != nullptr);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers.
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -88,7 +89,7 @@ public:
|
||||||
bool setFilter(const QString &name);
|
bool setFilter(const QString &name);
|
||||||
|
|
||||||
//! Set the minimum priority filter (by ordinal).
|
//! Set the minimum priority filter (by ordinal).
|
||||||
void setFilter(LogLevel);
|
void setFilter(LogLevel::Level);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
|
|
@ -103,28 +104,28 @@ public:
|
||||||
void print(const char *file, int line, const char *format, ...);
|
void print(const char *file, int line, const char *format, ...);
|
||||||
|
|
||||||
//! Get the minimum priority level.
|
//! Get the minimum priority level.
|
||||||
LogLevel getFilter() const;
|
LogLevel::Level getFilter() const;
|
||||||
|
|
||||||
//! Get the filter name of the current filter level.
|
//! Get the filter name of the current filter level.
|
||||||
const char *getFilterName() const;
|
const char *getFilterName() const;
|
||||||
|
|
||||||
//! Get the filter name of a specified filter level.
|
//! 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
|
//! Get the singleton instance of the log
|
||||||
static Log *getInstance();
|
static Log *getInstance();
|
||||||
|
|
||||||
//! Get the console filter level (messages above this are not sent to
|
//! Get the console filter level (messages above this are not sent to
|
||||||
//! console).
|
//! console).
|
||||||
LogLevel getConsoleMaxLevel() const
|
LogLevel::Level getConsoleMaxLevel() const
|
||||||
{
|
{
|
||||||
return LogLevel::Verbose;
|
return LogLevel::Level::Verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void output(LogLevel priority, const char *msg);
|
void output(LogLevel::Level priority, const char *msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using OutputterList = std::list<ILogOutputter *>;
|
using OutputterList = std::list<ILogOutputter *>;
|
||||||
|
|
@ -134,7 +135,7 @@ private:
|
||||||
mutable std::mutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
OutputterList m_outputters;
|
OutputterList m_outputters;
|
||||||
OutputterList m_alwaysOutputters;
|
OutputterList m_alwaysOutputters;
|
||||||
LogLevel m_maxPriority;
|
LogLevel::Level m_maxPriority;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* 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) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -31,7 +31,7 @@ void StopLogOutputter::close()
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StopLogOutputter::write(LogLevel, const QString &)
|
bool StopLogOutputter::write(LogLevel::Level, const QString &)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -50,9 +50,10 @@ void ConsoleLogOutputter::close()
|
||||||
// do nothing
|
// 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;
|
std::cerr << qPrintable(msg) << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << qPrintable(msg) << std::endl;
|
std::cout << qPrintable(msg) << std::endl;
|
||||||
|
|
@ -79,7 +80,7 @@ void SystemLogOutputter::close()
|
||||||
ARCH->closeLog();
|
ARCH->closeLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemLogOutputter::write(LogLevel level, const QString &msg)
|
bool SystemLogOutputter::write(LogLevel::Level level, const QString &msg)
|
||||||
{
|
{
|
||||||
ARCH->writeLog(level, msg);
|
ARCH->writeLog(level, msg);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -126,7 +127,7 @@ void FileLogOutputter::setLogFilename(const QString &logFile)
|
||||||
m_fileName = logFile;
|
m_fileName = logFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLogOutputter::write(LogLevel, const QString &message)
|
bool FileLogOutputter::write(LogLevel::Level, const QString &message)
|
||||||
{
|
{
|
||||||
QFile file(m_fileName);
|
QFile file(m_fileName);
|
||||||
if (!file.open(QFile::WriteOnly | QFile::Append))
|
if (!file.open(QFile::WriteOnly | QFile::Append))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* 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) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -26,7 +26,7 @@ public:
|
||||||
// ILogOutputter overrides
|
// ILogOutputter overrides
|
||||||
void open(const QString &title) override;
|
void open(const QString &title) override;
|
||||||
void close() 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
|
//! Write log to console
|
||||||
|
|
@ -43,7 +43,7 @@ public:
|
||||||
// ILogOutputter overrides
|
// ILogOutputter overrides
|
||||||
void open(const QString &title) override;
|
void open(const QString &title) override;
|
||||||
void close() override;
|
void close() override;
|
||||||
bool write(LogLevel level, const QString &message) override;
|
bool write(LogLevel::Level level, const QString &message) override;
|
||||||
void flush() const;
|
void flush() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ public:
|
||||||
// ILogOutputter overrides
|
// ILogOutputter overrides
|
||||||
void open(const QString &title) override;
|
void open(const QString &title) override;
|
||||||
void close() 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);
|
void setLogFilename(const QString &title);
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ public:
|
||||||
// ILogOutputter overrides
|
// ILogOutputter overrides
|
||||||
void open(const QString &title) override;
|
void open(const QString &title) override;
|
||||||
void close() 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
|
//! Write log to system log only
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,101 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
//! Log levels
|
class LogLevel : private QObject
|
||||||
/*!
|
|
||||||
The logging priority levels in order of highest to lowest priority.
|
|
||||||
*/
|
|
||||||
enum class LogLevel
|
|
||||||
{
|
{
|
||||||
Print = -1, //!< For print only (no file or time)
|
Q_OBJECT
|
||||||
Fatal, //!< For fatal errors
|
//! Log levels
|
||||||
Error, //!< For serious errors
|
/*!
|
||||||
Warning, //!< For minor errors and warnings
|
The logging priority levels in order of highest to lowest priority.
|
||||||
Info, //!< For informational messages
|
*/
|
||||||
Debug, //!< For important debugging messages
|
public:
|
||||||
Verbose //!< For verbose debugging messages
|
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<int>(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<int>(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
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
|
#include "LogLevel.h"
|
||||||
#include "NetworkProtocol.h"
|
#include "NetworkProtocol.h"
|
||||||
#include "UrlConstants.h"
|
#include "UrlConstants.h"
|
||||||
|
|
||||||
|
|
@ -95,6 +96,10 @@ Settings::Settings(QObject *parent) : QObject(parent)
|
||||||
|
|
||||||
void Settings::upgradeSettings()
|
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()) {
|
for (const auto [oldKey, newKey] : m_upgradedMap.asKeyValueRange()) {
|
||||||
if (m_settings->contains(oldKey) && !m_settings->contains(newKey)) {
|
if (m_settings->contains(oldKey) && !m_settings->contains(newKey)) {
|
||||||
m_settings->setValue(newKey, m_settings->value(oldKey));
|
m_settings->setValue(newKey, m_settings->value(oldKey));
|
||||||
|
|
@ -156,13 +161,6 @@ QString Settings::cleanComputerName(const QString &name)
|
||||||
return cleanName;
|
return cleanName;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Settings::logLevelToInt(const QString &level)
|
|
||||||
{
|
|
||||||
if (level.isEmpty() || !m_logLevels.contains(level, Qt::CaseInsensitive))
|
|
||||||
return 4;
|
|
||||||
return static_cast<int>(m_logLevels.indexOf(level, 0, Qt::CaseInsensitive));
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant Settings::defaultValue(const QString &key)
|
QVariant Settings::defaultValue(const QString &key)
|
||||||
{
|
{
|
||||||
if (m_defaultFalseValues.contains(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);
|
return QStringLiteral("%1/%2.log").arg(QDir::homePath(), kAppId);
|
||||||
|
|
||||||
if (key == Log::Level)
|
if (key == Log::Level)
|
||||||
return 4; // INFO
|
return QVariant::fromValue(LogLevel::Level::Info).toString();
|
||||||
|
|
||||||
if (key == Daemon::Elevate)
|
if (key == Daemon::Elevate)
|
||||||
return !Settings::isPortableMode();
|
return !Settings::isPortableMode();
|
||||||
|
|
@ -215,11 +213,6 @@ QVariant Settings::defaultValue(const QString &key)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Settings::logLevelText()
|
|
||||||
{
|
|
||||||
return Settings::m_logLevels.at(Settings::value(Log::Level).toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
QSettingsProxy &Settings::proxy()
|
QSettingsProxy &Settings::proxy()
|
||||||
{
|
{
|
||||||
return *instance()->m_settingsProxy;
|
return *instance()->m_settingsProxy;
|
||||||
|
|
@ -291,6 +284,11 @@ QString Settings::tlsTrustedClientsDb()
|
||||||
return QFileInfo(QStringLiteral("%1/trusted-clients").arg(instance()->tlsDir())).absoluteFilePath();
|
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)
|
void Settings::setValue(const QString &key, const QVariant &value)
|
||||||
{
|
{
|
||||||
const bool useState = Settings::m_stateKeys.contains(key) && !instance()->isPortableMode();
|
const bool useState = Settings::m_stateKeys.contains(key) && !instance()->isPortableMode();
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,6 @@ public:
|
||||||
static QSettingsProxy &proxy();
|
static QSettingsProxy &proxy();
|
||||||
static void save(bool emitSaving = true);
|
static void save(bool emitSaving = true);
|
||||||
static QStringList validKeys();
|
static QStringList validKeys();
|
||||||
static int logLevelToInt(const QString &level);
|
|
||||||
static QString portableSettingsFile();
|
static QString portableSettingsFile();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
@ -190,15 +189,6 @@ private:
|
||||||
std::shared_ptr<QSettingsProxy> m_settingsProxy;
|
std::shared_ptr<QSettingsProxy> m_settingsProxy;
|
||||||
|
|
||||||
// clang-format off
|
// 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 = {
|
inline static const QStringList m_validKeys = {
|
||||||
Settings::Client::DynamicConnectionRetry
|
Settings::Client::DynamicConnectionRetry
|
||||||
, Settings::Client::InvertYScroll
|
, Settings::Client::InvertYScroll
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SettingsDialog.h"
|
#include "SettingsDialog.h"
|
||||||
|
#include "common/LogLevel.h"
|
||||||
#include "common/PlatformInfo.h"
|
#include "common/PlatformInfo.h"
|
||||||
#include "ui_SettingsDialog.h"
|
#include "ui_SettingsDialog.h"
|
||||||
|
|
||||||
|
|
@ -216,7 +217,9 @@ void SettingsDialog::accept()
|
||||||
{
|
{
|
||||||
Settings::setValue(Settings::Core::Port, ui->sbPort->value());
|
Settings::setValue(Settings::Core::Port, ui->sbPort->value());
|
||||||
Settings::setValue(Settings::Core::Interface, ui->comboInterface->currentData());
|
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<LogLevel::Level>(ui->comboLogLevel->currentIndex()))
|
||||||
|
);
|
||||||
Settings::setValue(Settings::Log::ToFile, ui->groupLogToFile->isChecked());
|
Settings::setValue(Settings::Log::ToFile, ui->groupLogToFile->isChecked());
|
||||||
Settings::setValue(Settings::Log::File, ui->lineLogFilename->text());
|
Settings::setValue(Settings::Log::File, ui->lineLogFilename->text());
|
||||||
Settings::setValue(Settings::Daemon::Elevate, ui->cbElevateDaemon->isChecked());
|
Settings::setValue(Settings::Daemon::Elevate, ui->cbElevateDaemon->isChecked());
|
||||||
|
|
@ -251,7 +254,7 @@ void SettingsDialog::accept()
|
||||||
void SettingsDialog::loadFromConfig()
|
void SettingsDialog::loadFromConfig()
|
||||||
{
|
{
|
||||||
ui->sbPort->setValue(Settings::value(Settings::Core::Port).toInt());
|
ui->sbPort->setValue(Settings::value(Settings::Core::Port).toInt());
|
||||||
ui->comboLogLevel->setCurrentIndex(Settings::value(Settings::Log::Level).toInt());
|
ui->comboLogLevel->setCurrentIndex(static_cast<int>(LogLevel::fromOption(Settings::logLevelText())));
|
||||||
ui->groupLogToFile->setChecked(Settings::value(Settings::Log::ToFile).toBool());
|
ui->groupLogToFile->setChecked(Settings::value(Settings::Log::ToFile).toBool());
|
||||||
ui->lineLogFilename->setText(Settings::value(Settings::Log::File).toString());
|
ui->lineLogFilename->setText(Settings::value(Settings::Log::File).toString());
|
||||||
ui->cbPreventSleep->setChecked(Settings::value(Settings::Core::PreventSleep).toBool());
|
ui->cbPreventSleep->setChecked(Settings::value(Settings::Core::PreventSleep).toBool());
|
||||||
|
|
@ -284,7 +287,9 @@ void SettingsDialog::loadFromConfig()
|
||||||
ui->rbCloseToTray->setChecked(closeToTray);
|
ui->rbCloseToTray->setChecked(closeToTray);
|
||||||
ui->rbExitOnClose->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<int>(LogLevel::Level::Info)
|
||||||
|
);
|
||||||
|
|
||||||
ui->comboInterface->setCurrentText(Settings::value(Settings::Core::Interface).toString());
|
ui->comboInterface->setCurrentText(Settings::value(Settings::Core::Interface).toString());
|
||||||
if (ui->comboInterface->currentIndex() <= 0) {
|
if (ui->comboInterface->currentIndex() <= 0) {
|
||||||
|
|
@ -409,7 +414,7 @@ void SettingsDialog::updateRequestedKeySize() const
|
||||||
|
|
||||||
void SettingsDialog::logLevelChanged()
|
void SettingsDialog::logLevelChanged()
|
||||||
{
|
{
|
||||||
ui->lblDebugWarning->setVisible(ui->comboLogLevel->currentIndex() > 3);
|
ui->lblDebugWarning->setVisible(ui->comboLogLevel->currentIndex() > static_cast<int>(LogLevel::Level::Info));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SettingsDialog::isModified() const
|
bool SettingsDialog::isModified() const
|
||||||
|
|
@ -419,7 +424,7 @@ bool SettingsDialog::isModified() const
|
||||||
|
|
||||||
bool modified =
|
bool modified =
|
||||||
(ui->sbPort->value() != Settings::value(Settings::Core::Port).toInt()) ||
|
(ui->sbPort->value() != Settings::value(Settings::Core::Port).toInt()) ||
|
||||||
(ui->comboLogLevel->currentIndex() != Settings::value(Settings::Log::Level).toInt()) ||
|
(ui->comboLogLevel->currentIndex() != static_cast<int>(LogLevel::fromOption(Settings::logLevelText()))) ||
|
||||||
(ui->groupLogToFile->isChecked() != Settings::value(Settings::Log::ToFile).toBool()) ||
|
(ui->groupLogToFile->isChecked() != Settings::value(Settings::Log::ToFile).toBool()) ||
|
||||||
(ui->lineLogFilename->text() != Settings::value(Settings::Log::File).toString()) ||
|
(ui->lineLogFilename->text() != Settings::value(Settings::Log::File).toString()) ||
|
||||||
(ui->rbAutoHide->isChecked() != Settings::value(Settings::Gui::Autohide).toBool()) ||
|
(ui->rbAutoHide->isChecked() != Settings::value(Settings::Gui::Autohide).toBool()) ||
|
||||||
|
|
@ -450,10 +455,12 @@ bool SettingsDialog::isModified() const
|
||||||
bool SettingsDialog::isDefault() const
|
bool SettingsDialog::isDefault() const
|
||||||
{
|
{
|
||||||
const auto processMode = Settings::defaultValue(Settings::Core::ProcessMode).value<Settings::ProcessMode>();
|
const auto processMode = Settings::defaultValue(Settings::Core::ProcessMode).value<Settings::ProcessMode>();
|
||||||
|
const auto logLevelIndex =
|
||||||
|
static_cast<int>(LogLevel::fromOption(Settings::defaultValue(Settings::Log::Level).toString()));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(ui->sbPort->value() == Settings::defaultValue(Settings::Core::Port).toInt()) &&
|
(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->groupLogToFile->isChecked() == Settings::defaultValue(Settings::Log::ToFile).toBool()) &&
|
||||||
(ui->lineLogFilename->text() == Settings::defaultValue(Settings::Log::File).toString()) &&
|
(ui->lineLogFilename->text() == Settings::defaultValue(Settings::Log::File).toString()) &&
|
||||||
(ui->rbAutoHide->isChecked() == Settings::defaultValue(Settings::Gui::Autohide).toBool()) &&
|
(ui->rbAutoHide->isChecked() == Settings::defaultValue(Settings::Gui::Autohide).toBool()) &&
|
||||||
|
|
@ -482,7 +489,9 @@ bool SettingsDialog::isDefault() const
|
||||||
void SettingsDialog::resetToDefault()
|
void SettingsDialog::resetToDefault()
|
||||||
{
|
{
|
||||||
ui->sbPort->setValue(Settings::defaultValue(Settings::Core::Port).toInt());
|
ui->sbPort->setValue(Settings::defaultValue(Settings::Core::Port).toInt());
|
||||||
ui->comboLogLevel->setCurrentIndex(Settings::defaultValue(Settings::Log::Level).toInt());
|
ui->comboLogLevel->setCurrentIndex(
|
||||||
|
static_cast<int>(LogLevel::fromOption(Settings::defaultValue(Settings::Log::Level).toString()))
|
||||||
|
);
|
||||||
ui->groupLogToFile->setChecked(Settings::defaultValue(Settings::Log::ToFile).toBool());
|
ui->groupLogToFile->setChecked(Settings::defaultValue(Settings::Log::ToFile).toBool());
|
||||||
ui->lineLogFilename->setText(Settings::defaultValue(Settings::Log::File).toString());
|
ui->lineLogFilename->setText(Settings::defaultValue(Settings::Log::File).toString());
|
||||||
ui->cbPreventSleep->setChecked(Settings::defaultValue(Settings::Core::PreventSleep).toBool());
|
ui->cbPreventSleep->setChecked(Settings::defaultValue(Settings::Core::PreventSleep).toBool());
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ void logRemoteSecureCipherInfo(const SSL *ssl)
|
||||||
|
|
||||||
void SslLogger::logSecureLibInfo()
|
void SslLogger::logSecureLibInfo()
|
||||||
{
|
{
|
||||||
if (CLOG->getFilter() >= LogLevel::Debug) {
|
if (CLOG->getFilter() >= LogLevel::Level::Debug) {
|
||||||
LOG_DEBUG("openssl version: %s", SSLeay_version(SSLEAY_VERSION));
|
LOG_DEBUG("openssl version: %s", SSLeay_version(SSLEAY_VERSION));
|
||||||
LOG_VERBOSE("openssl flags: %s", SSLeay_version(SSLEAY_CFLAGS));
|
LOG_VERBOSE("openssl flags: %s", SSLeay_version(SSLEAY_CFLAGS));
|
||||||
LOG_VERBOSE("openssl built on: %s", SSLeay_version(SSLEAY_BUILT_ON));
|
LOG_VERBOSE("openssl built on: %s", SSLeay_version(SSLEAY_BUILT_ON));
|
||||||
|
|
@ -77,7 +77,7 @@ void SslLogger::logSecureLibInfo()
|
||||||
|
|
||||||
void SslLogger::logSecureCipherInfo(const SSL *ssl)
|
void SslLogger::logSecureCipherInfo(const SSL *ssl)
|
||||||
{
|
{
|
||||||
if (ssl && CLOG->getFilter() >= LogLevel::Verbose) {
|
if (ssl && CLOG->getFilter() >= LogLevel::Level::Verbose) {
|
||||||
logLocalSecureCipherInfo(ssl);
|
logLocalSecureCipherInfo(ssl);
|
||||||
logRemoteSecureCipherInfo(ssl);
|
logRemoteSecureCipherInfo(ssl);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ void MSWindowsDebugOutputter::close()
|
||||||
// do nothing
|
// 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";
|
std::wstring out = msg.toStdWString() + L"\n";
|
||||||
OutputDebugString(out.c_str());
|
OutputDebugString(out.c_str());
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,6 @@ public:
|
||||||
// ILogOutputter overrides
|
// ILogOutputter overrides
|
||||||
void open(const QString &title) override;
|
void open(const QString &title) override;
|
||||||
void close() override;
|
void close() override;
|
||||||
bool write(LogLevel level, const QString &message) override;
|
bool write(LogLevel::Level level, const QString &message) override;
|
||||||
void flush();
|
void flush();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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.
|
// The file log outputter adds its own newlines, so trim the decoded string to avoid double newlines.
|
||||||
const auto trimmed = decoded.trimmed();
|
const auto trimmed = decoded.trimmed();
|
||||||
m_fileLogOutputter.write(LogLevel::Print, trimmed);
|
m_fileLogOutputter.write(LogLevel::Level::Print, trimmed);
|
||||||
|
|
||||||
if (m_foreground) {
|
if (m_foreground) {
|
||||||
// Doesn't add it's own newlines, so use the original ones from the process output.
|
// Doesn't add it's own newlines, so use the original ones from the process output.
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "platform/XWindowsClipboard.h"
|
|
||||||
|
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
|
|
||||||
|
#include "platform/XWindowsClipboard.h"
|
||||||
|
|
||||||
#include "base/Stopwatch.h"
|
#include "base/Stopwatch.h"
|
||||||
#include "platform/XWindowsClipboardBMPConverter.h"
|
#include "platform/XWindowsClipboardBMPConverter.h"
|
||||||
#include "platform/XWindowsClipboardHTMLConverter.h"
|
#include "platform/XWindowsClipboardHTMLConverter.h"
|
||||||
|
|
@ -1000,7 +1001,7 @@ bool XWindowsClipboard::sendReply(Reply *reply)
|
||||||
reply->m_replied = true;
|
reply->m_replied = true;
|
||||||
|
|
||||||
// nothing to log
|
// nothing to log
|
||||||
if (CLOG->getFilter() < LogLevel::Verbose) {
|
if (CLOG->getFilter() < LogLevel::Level::Verbose) {
|
||||||
sendNotify(
|
sendNotify(
|
||||||
reply->m_requestor, m_selection, reply->m_target, reply->m_property, static_cast<unsigned int>(reply->m_time)
|
reply->m_requestor, m_selection, reply->m_target, reply->m_property, static_cast<unsigned int>(reply->m_time)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ QString sanitizeBuffer(const std::stringstream &in)
|
||||||
void LogTests::initTestCase()
|
void LogTests::initTestCase()
|
||||||
{
|
{
|
||||||
std::setlocale(LC_NUMERIC, "C");
|
std::setlocale(LC_NUMERIC, "C");
|
||||||
m_log.setFilter(LogLevel::Debug);
|
m_log.setFilter(LogLevel::Level::Debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogTests::printWithErrorValidOutput()
|
void LogTests::printWithErrorValidOutput()
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
void UnicodeTests::initTestCase()
|
void UnicodeTests::initTestCase()
|
||||||
{
|
{
|
||||||
m_log.setFilter(LogLevel::Verbose);
|
m_log.setFilter(LogLevel::Level::Verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnicodeTests::UTF16ToUTF8()
|
void UnicodeTests::UTF16ToUTF8()
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@ create_test(
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/common"
|
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(
|
create_test(
|
||||||
NAME I18NTests
|
NAME I18NTests
|
||||||
DEPENDS common
|
DEPENDS common
|
||||||
|
|
|
||||||
33
src/unittests/common/LogLevelTests.cpp
Normal file
33
src/unittests/common/LogLevelTests.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LogLevelTests.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QSignalSpy>
|
||||||
|
|
||||||
|
#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)
|
||||||
14
src/unittests/common/LogLevelTests.h
Normal file
14
src/unittests/common/LogLevelTests.h
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
*/
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
class LogLevelTests : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private Q_SLOTS:
|
||||||
|
void checkLogLevels_Valid();
|
||||||
|
void checkLogLevels_Invalid();
|
||||||
|
};
|
||||||
|
|
@ -101,23 +101,4 @@ void SettingsTests::checkCleanScreenName_LongName()
|
||||||
QCOMPARE(Settings::value(Settings::Core::ComputerName).toString(), expected);
|
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)
|
QTEST_MAIN(SettingsTests)
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ private Q_SLOTS:
|
||||||
void checkValidSettings();
|
void checkValidSettings();
|
||||||
void checkCleanScreenName();
|
void checkCleanScreenName();
|
||||||
void checkCleanScreenName_LongName();
|
void checkCleanScreenName_LongName();
|
||||||
void checkLogLevels_Valid();
|
|
||||||
void checkLogLevels_Invalid();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static const QString m_settingsPathTemp = QStringLiteral("tmp/test");
|
inline static const QString m_settingsPathTemp = QStringLiteral("tmp/test");
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
void ClipboardTests::initTestCase()
|
void ClipboardTests::initTestCase()
|
||||||
{
|
{
|
||||||
m_log.setFilter(LogLevel::Verbose);
|
m_log.setFilter(LogLevel::Level::Verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClipboardTests::basicFunction()
|
void ClipboardTests::basicFunction()
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
void KeyboardLayoutManagerTests::initTestCase()
|
void KeyboardLayoutManagerTests::initTestCase()
|
||||||
{
|
{
|
||||||
m_log.setFilter(LogLevel::Verbose);
|
m_log.setFilter(LogLevel::Level::Verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardLayoutManagerTests::remoteLayouts()
|
void KeyboardLayoutManagerTests::remoteLayouts()
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ int main(int argc, char **argv)
|
||||||
arch.init();
|
arch.init();
|
||||||
|
|
||||||
Log log;
|
Log log;
|
||||||
log.setFilter(LogLevel::Verbose);
|
log.setFilter(LogLevel::Level::Verbose);
|
||||||
|
|
||||||
::testing::GTEST_FLAG(throw_on_failure) = true;
|
::testing::GTEST_FLAG(throw_on_failure) = true;
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
void MSWindowsClipboardTests::initTestCase()
|
void MSWindowsClipboardTests::initTestCase()
|
||||||
{
|
{
|
||||||
m_log.setFilter(LogLevel::Verbose);
|
m_log.setFilter(LogLevel::Level::Verbose);
|
||||||
|
|
||||||
MSWindowsClipboard clipboard(NULL);
|
MSWindowsClipboard clipboard(NULL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
void OSXKeyStateTests::initTestCase()
|
void OSXKeyStateTests::initTestCase()
|
||||||
{
|
{
|
||||||
m_arch.init();
|
m_arch.init();
|
||||||
m_log.setFilter(LogLevel::Verbose);
|
m_log.setFilter(LogLevel::Level::Verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSXKeyStateTests::mapModifiersFromOSX_OSXMask()
|
void OSXKeyStateTests::mapModifiersFromOSX_OSXMask()
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ void WlClipboardTests::isAvailable()
|
||||||
void WlClipboardTests::initTestCase()
|
void WlClipboardTests::initTestCase()
|
||||||
{
|
{
|
||||||
m_arch.init();
|
m_arch.init();
|
||||||
m_log.setFilter(LogLevel::Verbose);
|
m_log.setFilter(LogLevel::Level::Verbose);
|
||||||
|
|
||||||
// Only run tests if Wayland clipboard tools are available
|
// Only run tests if Wayland clipboard tools are available
|
||||||
if (!deskflow::platform::isWayland()) {
|
if (!deskflow::platform::isWayland()) {
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,33 @@ Do you want to connect to the server?
|
||||||
<translation type="unfinished">Adjuntar a la ventana</translation>
|
<translation type="unfinished">Adjuntar a la ventana</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>LogLevel</name>
|
||||||
|
<message>
|
||||||
|
<source>Fatal</source>
|
||||||
|
<translation type="unfinished">Fatal</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Error</source>
|
||||||
|
<translation type="unfinished">Error</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Warning</source>
|
||||||
|
<translation type="unfinished">Advertencia</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Info</source>
|
||||||
|
<translation type="unfinished">Información</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Debug</source>
|
||||||
|
<translation type="unfinished">Depurar</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Verbose</source>
|
||||||
|
<translation type="unfinished">Verboso</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,33 @@ Vuoi connetterti al server?
|
||||||
<translation>Allega alla finestra</translation>
|
<translation>Allega alla finestra</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>LogLevel</name>
|
||||||
|
<message>
|
||||||
|
<source>Fatal</source>
|
||||||
|
<translation type="unfinished">Fatale</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Error</source>
|
||||||
|
<translation type="unfinished">Errore</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Warning</source>
|
||||||
|
<translation type="unfinished">Avviso</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Info</source>
|
||||||
|
<translation type="unfinished">Informazioni</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Debug</source>
|
||||||
|
<translation type="unfinished">Debug</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Verbose</source>
|
||||||
|
<translation type="unfinished">Verboso</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,33 @@ Do you want to connect to the server?
|
||||||
<translation>ウィンドウに結合</translation>
|
<translation>ウィンドウに結合</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>LogLevel</name>
|
||||||
|
<message>
|
||||||
|
<source>Fatal</source>
|
||||||
|
<translation type="unfinished">重大</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Error</source>
|
||||||
|
<translation type="unfinished">エラー</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Warning</source>
|
||||||
|
<translation type="unfinished">警告</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Info</source>
|
||||||
|
<translation type="unfinished">情報</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Debug</source>
|
||||||
|
<translation type="unfinished">デバッグ</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Verbose</source>
|
||||||
|
<translation type="unfinished">冗長</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,33 @@ Do you want to connect to the server?
|
||||||
<translation>창에 붙이기</translation>
|
<translation>창에 붙이기</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>LogLevel</name>
|
||||||
|
<message>
|
||||||
|
<source>Fatal</source>
|
||||||
|
<translation type="unfinished">치명적 오류</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Error</source>
|
||||||
|
<translation type="unfinished">오류</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Warning</source>
|
||||||
|
<translation type="unfinished">경고</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Info</source>
|
||||||
|
<translation type="unfinished">정보</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Debug</source>
|
||||||
|
<translation type="unfinished">디버그</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Verbose</source>
|
||||||
|
<translation type="unfinished">말 수가 많은</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,33 @@ Do you want to connect to the server?
|
||||||
<translation>Прикрепить к окну</translation>
|
<translation>Прикрепить к окну</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>LogLevel</name>
|
||||||
|
<message>
|
||||||
|
<source>Fatal</source>
|
||||||
|
<translation type="unfinished">Критический</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Error</source>
|
||||||
|
<translation type="unfinished">Ошибка</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Warning</source>
|
||||||
|
<translation type="unfinished">Предупреждение</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Info</source>
|
||||||
|
<translation type="unfinished">Инфо</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Debug</source>
|
||||||
|
<translation type="unfinished">Отладка</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Verbose</source>
|
||||||
|
<translation type="unfinished">Многословный</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,33 @@ Do you want to connect to the server?
|
||||||
<translation>吸附到窗口</translation>
|
<translation>吸附到窗口</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>LogLevel</name>
|
||||||
|
<message>
|
||||||
|
<source>Fatal</source>
|
||||||
|
<translation type="unfinished">致命</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Error</source>
|
||||||
|
<translation type="unfinished">错误</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Warning</source>
|
||||||
|
<translation type="unfinished">警告</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Info</source>
|
||||||
|
<translation type="unfinished">信息</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Debug</source>
|
||||||
|
<translation type="unfinished">调试</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Verbose</source>
|
||||||
|
<translation type="unfinished">冗长的</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue