diff --git a/src/common/log.cpp b/src/common/log.cpp index 2fbdfe9af..87bbfa54f 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -44,36 +44,24 @@ static void UnregisterCallback(CallbackFunctionType callbackFunction, void* pUse const std::unique_lock& lock); static bool FilterTest(Channel channel, Level level); -static void ExecuteCallbacks(Channel channel, const char* functionName, Level level, std::string_view message, - const std::unique_lock& lock); -static void FormatLogMessageForDisplay(fmt::memory_buffer& buffer, const char* channelName, const char* functionName, - Level level, std::string_view message, bool timestamp, bool ansi_color_code); -static void ConsoleOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level, +static void ExecuteCallbacks(MessageCategory cat, const char* functionName, std::string_view message); +static void FormatLogMessageForDisplay(fmt::memory_buffer& buffer, MessageCategory cat, const char* functionName, + std::string_view message, bool timestamp, bool ansi_color_code); +static void ConsoleOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName, std::string_view message); -static void DebugOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level, +static void DebugOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName, std::string_view message); -static void FileOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level, +static void FileOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName, std::string_view message); template -static void FormatLogMessageAndPrint(const char* channelName, const char* functionName, Level level, - std::string_view message, bool timestamp, bool ansi_color_code, const T& callback); +static void FormatLogMessageAndPrint(MessageCategory cat, const char* functionName, std::string_view message, + bool timestamp, bool ansi_color_code, const T& callback); #ifdef _WIN32 template -static void FormatLogMessageAndPrintW(const char* channelName, const char* functionName, Level level, - std::string_view message, bool timestamp, bool ansi_color_code, - const T& callback); +static void FormatLogMessageAndPrintW(MessageCategory cat, const char* functionName, std::string_view message, + bool timestamp, bool ansi_color_code, const T& callback); #endif -ALWAYS_INLINE static Channel UnpackLogChannel(PackedChannelAndLevel cat) -{ - return static_cast(cat >> 3); -} - -ALWAYS_INLINE static Level UnpackLogLevel(PackedChannelAndLevel cat) -{ - return static_cast(cat & 0x7); -} - static constexpr const std::array(Level::MaxCount)> s_log_level_characters = { {'X', 'E', 'W', 'I', 'V', 'D', 'B', 'T'}}; @@ -191,31 +179,59 @@ bool Log::IsDebugOutputEnabled() return s_state.debug_output_enabled; } -void Log::ExecuteCallbacks(Channel channel, const char* functionName, Level level, std::string_view message, - const std::unique_lock& lock) +Log::Color Log::GetColorForLevel(Level level) { - for (RegisteredCallback& callback : s_state.callbacks) - callback.Function(callback.Parameter, s_log_channel_names[static_cast(channel)], functionName, level, - message); -} - -ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& buffer, const char* channelName, - const char* functionName, Level level, - std::string_view message, bool timestamp, - bool ansi_color_code) -{ - static constexpr const std::array s_ansi_color_codes = { - "\033[0m"sv, // None - "\033[1;31m"sv, // Error - "\033[1;33m"sv, // Warning - "\033[1;37m"sv, // Info - "\033[1;32m"sv, // Verbose - "\033[0;37m"sv, // Dev - "\033[0;32m"sv, // Debug - "\033[0;34m"sv, // Trace + static constexpr const std::array s_level_colours = { + Color::Default, // None + Color::StrongRed, // Error + Color::StrongYellow, // Warning + Color::StrongWhite, // Info + Color::StrongGreen, // Verbose + Color::White, // Dev + Color::Green, // Debug + Color::Blue, // Trace }; - std::string_view color_start = ansi_color_code ? s_ansi_color_codes[static_cast(level)] : ""sv; + return s_level_colours[static_cast(level)]; +} + +void Log::ExecuteCallbacks(MessageCategory cat, const char* functionName, std::string_view message) +{ + for (RegisteredCallback& callback : s_state.callbacks) + callback.Function(callback.Parameter, cat, functionName, message); +} + +ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& buffer, MessageCategory cat, + const char* functionName, std::string_view message, + bool timestamp, bool ansi_color_code) +{ + static constexpr const std::array s_ansi_color_codes = { + "\033[0m"sv, // default + "\033[30m\033[1m"sv, // black + "\033[32m"sv, // green + "\033[31m"sv, // red + "\033[34m"sv, // blue + "\033[35m"sv, // magenta + "\033[38;5;217m"sv, // orange + "\033[36m"sv, // cyan + "\033[33m"sv, // yellow + "\033[37m"sv, // white + "\033[30m\033[1m"sv, // strong black + "\033[31m\033[1m"sv, // strong red + "\033[32m\033[1m"sv, // strong green + "\033[34m\033[1m"sv, // strong blue + "\033[35m\033[1m"sv, // strong magenta + "\033[38;5;202m"sv, // strong orange + "\033[36m\033[1m"sv, // strong cyan + "\033[33m\033[1m"sv, // strong yellow + "\033[37m\033[1m"sv, // strong white + }; + + const Level level = UnpackLevel(cat); + const Color color = (UnpackColor(cat) == Color::Default) ? GetColorForLevel(level) : UnpackColor(cat); + const char* channel_name = GetChannelName(UnpackChannel(cat)); + + std::string_view color_start = ansi_color_code ? s_ansi_color_codes[static_cast(color)] : ""sv; std::string_view color_end = ansi_color_code ? s_ansi_color_codes[0] : ""sv; auto appender = std::back_inserter(buffer); @@ -243,7 +259,7 @@ ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& b else { fmt::format_to(appender, "[{:10.4f}] {}{}/{}: {}{}{}", message_time, color_start, - s_log_level_characters[static_cast(level)], channelName, sub_message, color_end, + s_log_level_characters[static_cast(level)], channel_name, sub_message, color_end, end_message); } @@ -263,30 +279,30 @@ ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& b else { fmt::format_to(appender, "{}{}/{}: {}{}\n", color_start, s_log_level_characters[static_cast(level)], - channelName, message, color_end); + channel_name, message, color_end); } } } template -ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrint(const char* channelName, const char* functionName, Level level, +ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrint(MessageCategory cat, const char* functionName, std::string_view message, bool timestamp, bool ansi_color_code, const T& callback) { fmt::memory_buffer buffer; - FormatLogMessageForDisplay(buffer, channelName, functionName, level, message, timestamp, ansi_color_code); + FormatLogMessageForDisplay(buffer, cat, functionName, message, timestamp, ansi_color_code); callback(std::string_view(buffer.data(), buffer.size())); } #ifdef _WIN32 template -ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrintW(const char* channelName, const char* functionName, - Level level, std::string_view message, bool timestamp, +ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrintW(MessageCategory cat, const char* functionName, + std::string_view message, bool timestamp, bool ansi_color_code, const T& callback) { fmt::memory_buffer buffer; - FormatLogMessageForDisplay(buffer, channelName, functionName, level, message, timestamp, ansi_color_code); + FormatLogMessageForDisplay(buffer, cat, functionName, message, timestamp, ansi_color_code); // Convert to UTF-16 first so unicode characters display correctly. NT is going to do it // anyway... @@ -326,7 +342,7 @@ static bool EnableVirtualTerminalProcessing(HANDLE hConsole) #endif -void Log::ConsoleOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level, +void Log::ConsoleOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName, std::string_view message) { if (!s_state.console_output_enabled) @@ -334,29 +350,28 @@ void Log::ConsoleOutputLogCallback(void* pUserParam, const char* channelName, co #if defined(_WIN32) FormatLogMessageAndPrintW( - channelName, functionName, level, message, s_state.console_output_timestamps, true, - [level](const std::wstring_view& message) { - HANDLE hOutput = (level <= Level::Warning) ? s_state.hConsoleStdErr : s_state.hConsoleStdOut; + cat, functionName, message, s_state.console_output_timestamps, true, [cat](const std::wstring_view& message) { + HANDLE hOutput = (UnpackLevel(cat) <= Level::Warning) ? s_state.hConsoleStdErr : s_state.hConsoleStdOut; DWORD chars_written; WriteConsoleW(hOutput, message.data(), static_cast(message.length()), &chars_written, nullptr); }); #elif !defined(__ANDROID__) - FormatLogMessageAndPrint(channelName, functionName, level, message, s_state.console_output_timestamps, true, - [level](std::string_view message) { - const int outputFd = (level <= Log::Level::Warning) ? STDERR_FILENO : STDOUT_FILENO; - write(outputFd, message.data(), message.length()); - }); + FormatLogMessageAndPrint( + cat, functionName, message, s_state.console_output_timestamps, true, [cat](std::string_view message) { + const int outputFd = (UnpackLevel(cat) <= Log::Level::Warning) ? STDERR_FILENO : STDOUT_FILENO; + write(outputFd, message.data(), message.length()); + }); #endif } -void Log::DebugOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level, +void Log::DebugOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName, std::string_view message) { if (!s_state.debug_output_enabled) return; #if defined(_WIN32) - FormatLogMessageAndPrintW(channelName, functionName, level, message, false, false, + FormatLogMessageAndPrintW(cat, functionName, message, false, false, [](const std::wstring_view& message) { OutputDebugStringW(message.data()); }); #elif defined(__ANDROID__) if (message.empty()) @@ -373,8 +388,8 @@ void Log::DebugOutputLogCallback(void* pUserParam, const char* channelName, cons ANDROID_LOG_DEBUG, // Trace }; - __android_log_print(logPriority[static_cast(level)], channelName, "%.*s", static_cast(message.length()), - message.data()); + __android_log_print(logPriority[static_cast(UnpackLevel(cat))], GetChannelName(UnpackChannel(cat)), "%.*s", + static_cast(message.length()), message.data()); #endif } @@ -471,13 +486,13 @@ void Log::SetDebugOutputParams(bool enabled) UnregisterCallback(DebugOutputLogCallback, nullptr, lock); } -void Log::FileOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level, +void Log::FileOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName, std::string_view message) { if (!s_state.file_output_enabled) return; - FormatLogMessageAndPrint(channelName, functionName, level, message, true, false, [](std::string_view message) { + FormatLogMessageAndPrint(cat, functionName, message, true, false, [](std::string_view message) { std::fwrite(message.data(), 1, message.size(), s_state.file_handle.get()); std::fflush(s_state.file_handle.get()); }); @@ -494,8 +509,8 @@ void Log::SetFileOutputParams(bool enabled, const char* filename, bool timestamp s_state.file_handle = FileSystem::OpenManagedCFile(filename, "wb"); if (!s_state.file_handle) [[unlikely]] { - ExecuteCallbacks(Log::Channel::Log, __FUNCTION__, Level::Error, - TinyString::from_format("Failed to open log file '{}'", filename), lock); + ExecuteCallbacks(PackCategory(Channel::Log, Level::Error, Color::Default), nullptr, + TinyString::from_format("Failed to open log file '{}'", filename)); return; } @@ -535,57 +550,54 @@ void Log::SetLogChannelEnabled(Channel channel, bool enabled) s_state.log_channels_enabled[static_cast(channel)] = enabled; } +const char* Log::GetChannelName(Channel channel) +{ + return s_log_channel_names[static_cast(channel)]; +} + ALWAYS_INLINE_RELEASE bool Log::FilterTest(Channel channel, Level level) { return (level <= s_state.log_level && s_state.log_channels_enabled[static_cast(channel)]); } -void Log::Write(PackedChannelAndLevel cat, std::string_view message) +void Log::Write(MessageCategory cat, std::string_view message) { - const Channel channel = UnpackLogChannel(cat); - const Level level = UnpackLogLevel(cat); - if (!FilterTest(channel, level)) + if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat))) return; std::unique_lock lock(s_state.callbacks_mutex); - ExecuteCallbacks(channel, nullptr, level, message, lock); + ExecuteCallbacks(cat, nullptr, message); } -void Log::Write(PackedChannelAndLevel cat, const char* functionName, std::string_view message) +void Log::Write(MessageCategory cat, const char* functionName, std::string_view message) { - const Channel channel = UnpackLogChannel(cat); - const Level level = UnpackLogLevel(cat); - if (!FilterTest(channel, level)) + if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat))) return; std::unique_lock lock(s_state.callbacks_mutex); - ExecuteCallbacks(channel, functionName, level, message, lock); + ExecuteCallbacks(cat, functionName, message); } -void Log::WriteFmtArgs(PackedChannelAndLevel cat, fmt::string_view fmt, fmt::format_args args) +void Log::WriteFmtArgs(MessageCategory cat, fmt::string_view fmt, fmt::format_args args) { - const Channel channel = UnpackLogChannel(cat); - const Level level = UnpackLogLevel(cat); - if (!FilterTest(channel, level)) + if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat))) return; fmt::memory_buffer buffer; fmt::vformat_to(std::back_inserter(buffer), fmt, args); std::unique_lock lock(s_state.callbacks_mutex); - ExecuteCallbacks(channel, nullptr, level, std::string_view(buffer.data(), buffer.size()), lock); + ExecuteCallbacks(cat, nullptr, std::string_view(buffer.data(), buffer.size())); } -void Log::WriteFmtArgs(PackedChannelAndLevel cat, const char* functionName, fmt::string_view fmt, fmt::format_args args) +void Log::WriteFmtArgs(MessageCategory cat, const char* functionName, fmt::string_view fmt, fmt::format_args args) { - const Channel channel = UnpackLogChannel(cat); - const Level level = UnpackLogLevel(cat); - if (!FilterTest(channel, level)) + if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat))) return; fmt::memory_buffer buffer; fmt::vformat_to(std::back_inserter(buffer), fmt, args); std::unique_lock lock(s_state.callbacks_mutex); - ExecuteCallbacks(channel, functionName, level, std::string_view(buffer.data(), buffer.size()), lock); + ExecuteCallbacks(cat, functionName, std::string_view(buffer.data(), buffer.size())); } diff --git a/src/common/log.h b/src/common/log.h index deffc1361..0f0380644 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -29,6 +29,31 @@ enum class Level : u32 MaxCount }; +enum class Color : u32 +{ + Default, + Black, + Green, + Red, + Blue, + Magenta, + Orange, + Cyan, + Yellow, + White, + StrongBlack, + StrongRed, + StrongGreen, + StrongBlue, + StrongMagenta, + StrongOrange, + StrongCyan, + StrongYellow, + StrongWhite, + + MaxCount +}; + enum class Channel : u32 { #define LOG_CHANNEL_ENUM(X) X, @@ -38,8 +63,28 @@ enum class Channel : u32 MaxCount }; +// Packs a level and channel into one 16-bit number. +using MessageCategory = u32; +[[maybe_unused]] ALWAYS_INLINE static constexpr u32 PackCategory(Channel channel, Level level, Color colour) +{ + return ((static_cast(colour) << 10) | (static_cast(channel) << 3) | + static_cast(level)); +} +[[maybe_unused]] ALWAYS_INLINE static constexpr Color UnpackColor(MessageCategory cat) +{ + return static_cast((cat >> 10) & 0x1f); +} +[[maybe_unused]] ALWAYS_INLINE static constexpr Channel UnpackChannel(MessageCategory cat) +{ + return static_cast((cat >> 3) & 0x7f); +} +[[maybe_unused]] ALWAYS_INLINE static constexpr Level UnpackLevel(MessageCategory cat) +{ + return static_cast(cat & 0x7); +} + // log message callback type -using CallbackFunctionType = void (*)(void* pUserParam, const char* channelName, const char* functionName, Level level, +using CallbackFunctionType = void (*)(void* pUserParam, MessageCategory category, const char* functionName, std::string_view message); // registers a log callback @@ -79,41 +124,65 @@ void SetLogLevel(Level level); // Sets global filter, any messages from these channels won't be sent to any of the logging sinks. void SetLogChannelEnabled(Channel channel, bool enabled); -// Packs a level and channel into one 16-bit number. -using PackedChannelAndLevel = u32; -[[maybe_unused]] ALWAYS_INLINE static u32 PackChannelAndLevel(Channel channel, Level level) -{ - return ((static_cast(channel) << 3) | static_cast(level)); -} +// Returns the name of the specified log channel. +const char* GetChannelName(Channel channel); + +// Returns the default colour for a log level. +Color GetColorForLevel(Level level); // writes a message to the log -void Write(PackedChannelAndLevel cat, std::string_view message); -void Write(PackedChannelAndLevel cat, const char* functionName, std::string_view message); -void WriteFmtArgs(PackedChannelAndLevel cat, fmt::string_view fmt, fmt::format_args args); -void WriteFmtArgs(PackedChannelAndLevel cat, const char* functionName, fmt::string_view fmt, fmt::format_args args); +void Write(MessageCategory cat, std::string_view message); +void Write(MessageCategory cat, const char* functionName, std::string_view message); +void WriteFmtArgs(MessageCategory cat, fmt::string_view fmt, fmt::format_args args); +void WriteFmtArgs(MessageCategory cat, const char* functionName, fmt::string_view fmt, fmt::format_args args); ALWAYS_INLINE static void FastWrite(Channel channel, Level level, std::string_view message) { if (level <= GetLogLevel()) [[unlikely]] - Write(PackChannelAndLevel(channel, level), message); + Write(PackCategory(channel, level, Color::Default), message); } ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level, std::string_view message) { if (level <= GetLogLevel()) [[unlikely]] - Write(PackChannelAndLevel(channel, level), functionName, message); + Write(PackCategory(channel, level, Color::Default), functionName, message); } template ALWAYS_INLINE static void FastWrite(Channel channel, Level level, fmt::format_string fmt, T&&... args) { if (level <= GetLogLevel()) [[unlikely]] - WriteFmtArgs(PackChannelAndLevel(channel, level), fmt, fmt::make_format_args(args...)); + WriteFmtArgs(PackCategory(channel, level, Color::Default), fmt, fmt::make_format_args(args...)); } template ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level, fmt::format_string fmt, T&&... args) { if (level <= GetLogLevel()) [[unlikely]] - WriteFmtArgs(PackChannelAndLevel(channel, level), functionName, fmt, fmt::make_format_args(args...)); + WriteFmtArgs(PackCategory(channel, level, Color::Default), functionName, fmt, fmt::make_format_args(args...)); +} +ALWAYS_INLINE static void FastWrite(Channel channel, Level level, Color colour, std::string_view message) +{ + if (level <= GetLogLevel()) [[unlikely]] + Write(PackCategory(channel, level, colour), message); +} +ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level, Color colour, + std::string_view message) +{ + if (level <= GetLogLevel()) [[unlikely]] + Write(PackCategory(channel, level, colour), functionName, message); +} +template +ALWAYS_INLINE static void FastWrite(Channel channel, Level level, Color colour, fmt::format_string fmt, + T&&... args) +{ + if (level <= GetLogLevel()) [[unlikely]] + WriteFmtArgs(PackCategory(channel, level, colour), fmt, fmt::make_format_args(args...)); +} +template +ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level, Color colour, + fmt::format_string fmt, T&&... args) +{ + if (level <= GetLogLevel()) [[unlikely]] + WriteFmtArgs(PackCategory(channel, level, colour), functionName, fmt, fmt::make_format_args(args...)); } } // namespace Log @@ -139,3 +208,26 @@ ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, L { \ } while (0) #endif + +// clang-format off +#define ERROR_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Error, Log::Color::colour, __VA_ARGS__) +#define WARNING_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Warning, Log::Color::colour, __VA_ARGS__) +#define INFO_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Info, Log::Color::colour, __VA_ARGS__) +#define VERBOSE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Verbose, Log::Color::colour, __VA_ARGS__) +#define DEV_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Dev, Log::Color::colour, __VA_ARGS__) + +#ifdef _DEBUG +#define DEBUG_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Debug, Log::Color::colour, __VA_ARGS__) +#define TRACE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Trace, Log::Color::colour,__VA_ARGS__) +#else +#define DEBUG_COLOR_LOG(colour, ...) \ + do \ + { \ + } while (0) +#define TRACE_COLOR_LOG(colour, ...) \ + do \ + { \ + } while (0) +#endif + +// clang-format on diff --git a/src/core/cheats.cpp b/src/core/cheats.cpp index 61e69b75d..ccba2ebac 100644 --- a/src/core/cheats.cpp +++ b/src/core/cheats.cpp @@ -77,7 +77,7 @@ public: { if (!stop_on_error) { - Log::WriteFmtArgs(Log::PackChannelAndLevel(Log::Channel::Cheats, Log::Level::Warning), fmt, + Log::WriteFmtArgs(Log::PackCategory(Log::Channel::Cheats, Log::Level::Warning, Log::Color::StrongOrange), fmt, fmt::make_format_args(args...)); return true; } diff --git a/src/duckstation-qt/logwindow.cpp b/src/duckstation-qt/logwindow.cpp index ea180fa42..0291ee7f2 100644 --- a/src/duckstation-qt/logwindow.cpp +++ b/src/duckstation-qt/logwindow.cpp @@ -254,7 +254,7 @@ void LogWindow::onSaveTriggered() tr("Log was written to %1.\n").arg(path)); } -void LogWindow::logCallback(void* pUserParam, const char* channelName, const char* functionName, Log::Level level, +void LogWindow::logCallback(void* pUserParam, Log::MessageCategory cat, const char* functionName, std::string_view message) { LogWindow* this_ptr = static_cast(pUserParam); @@ -267,16 +267,17 @@ void LogWindow::logCallback(void* pUserParam, const char* channelName, const cha qmessage.append(QUtf8StringView(message.data(), message.length())); qmessage.append(QChar('\n')); - const QLatin1StringView qchannel((level <= Log::Level::Warning) ? functionName : channelName); + const QLatin1StringView qchannel( + (Log::UnpackLevel(cat) <= Log::Level::Warning) ? functionName : Log::GetChannelName(Log::UnpackChannel(cat))); if (QThread::isMainThread()) { - this_ptr->appendMessage(qchannel, static_cast(level), qmessage); + this_ptr->appendMessage(qchannel, static_cast(cat), qmessage); } else { QMetaObject::invokeMethod(this_ptr, "appendMessage", Qt::QueuedConnection, - Q_ARG(const QLatin1StringView&, qchannel), Q_ARG(quint32, static_cast(level)), + Q_ARG(const QLatin1StringView&, qchannel), Q_ARG(quint32, static_cast(cat)), Q_ARG(const QString&, qmessage)); } } @@ -304,7 +305,7 @@ void LogWindow::changeEvent(QEvent* event) QMainWindow::changeEvent(event); } -void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 level, const QString& message) +void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 cat, const QString& message) { QTextCursor temp_cursor = m_text->textCursor(); QScrollBar* scrollbar = m_text->verticalScrollBar(); @@ -316,28 +317,50 @@ void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 level, c { static constexpr const QChar level_characters[static_cast(Log::Level::MaxCount)] = {'X', 'E', 'W', 'I', 'V', 'D', 'B', 'T'}; - static constexpr const QColor level_colors[2][static_cast(Log::Level::MaxCount)] = { + static constexpr const QColor message_colors[2][static_cast(Log::Color::MaxCount)] = { + // Light theme { - // Light theme - QColor(0, 0, 0), // NONE - QColor(0x80, 0x00, 0x00), // ERROR, Red Intensity - QColor(0xb4, 0xb4, 0x00), // WARNING, Yellow Intensity - QColor(0x0d, 0x0d, 0x0d), // INFO, White Intensity - QColor(0x00, 0x80, 0x00), // VERBOSE, Green Intensity - QColor(0x70, 0x70, 0x70), // DEV, White - QColor(0xec, 0x5e, 0xf1), // DEBUG, Green - QColor(0xe9, 0x39, 0xf3), // TRACE, Blue + QColor(0x00, 0x00, 0x00), // Default + QColor(0x00, 0x00, 0x00), // Black + QColor(0x70, 0x00, 0x00), // Red + QColor(0xec, 0x5e, 0xf1), // Green + QColor(0xe9, 0x39, 0xf3), // Blue + QColor(0xA0, 0x00, 0xA0), // Magenta + QColor(0xA0, 0x78, 0x00), // Orange + QColor(0x80, 0xB4, 0xB4), // Cyan + QColor(0xB4, 0xB4, 0x80), // Yellow + QColor(0x70, 0x70, 0x70), // White + QColor(0x00, 0x00, 0x00), // StrongBlack + QColor(0x80, 0x00, 0x00), // StrongRed + QColor(0x00, 0x80, 0x00), // StrongGreen + QColor(0x00, 0x00, 0x80), // StrongBlue + QColor(0xA0, 0x00, 0xA0), // StrongMagenta + QColor(0xA0, 0x78, 0x00), // StrongOrange + QColor(0x80, 0xB4, 0xB4), // StrongCyan + QColor(0xb4, 0xb4, 0x00), // StrongYellow + QColor(0x0D, 0x0d, 0x0D) // StrongWhite }, + // Dark theme { - // Dark theme - QColor(255, 255, 255), // NONE - QColor(0xE7, 0x48, 0x56), // ERROR, Red Intensity - QColor(0xF9, 0xF1, 0xA5), // WARNING, Yellow Intensity - QColor(0xF2, 0xF2, 0xF2), // INFO, White Intensity - QColor(0x16, 0xC6, 0x0C), // VERBOSE, Green Intensity - QColor(0xCC, 0xCC, 0xCC), // DEV, White - QColor(0x13, 0xA1, 0x0E), // DEBUG, Green - QColor(0x00, 0x37, 0xDA), // TRACE, Blue + QColor(0xD0, 0xD0, 0xD0), // Default + QColor(0xFF, 0xFF, 0xFF), // Black + QColor(0xB4, 0x00, 0x00), // Red + QColor(0x13, 0xA1, 0x0E), // Green + QColor(0x00, 0x37, 0xDA), // Blue + QColor(0xA0, 0x00, 0xA0), // Magenta + QColor(0xA0, 0x78, 0x00), // Orange + QColor(0x80, 0xB4, 0xB4), // Cyan + QColor(0xB4, 0xB4, 0x80), // Yellow + QColor(0xCC, 0xCC, 0xCC), // White + QColor(0xFF, 0xFF, 0xFF), // StrongBlack + QColor(0xE7, 0x48, 0x56), // StrongRed + QColor(0x16, 0xC6, 0x0C), // StrongGreen + QColor(0x20, 0x20, 0xCC), // StrongBlue + QColor(0xA0, 0x00, 0xA0), // StrongMagenta + QColor(0xB4, 0x96, 0x00), // StrongOrange + QColor(0x80, 0xB4, 0xB4), // StrongCyan + QColor(0xF9, 0xF1, 0xA5), // StrongYellow + QColor(0xFF, 0xFF, 0xFF), // StrongWhite }, }; static constexpr const QColor timestamp_color[2] = {QColor(0x60, 0x60, 0x60), QColor(0xcc, 0xcc, 0xcc)}; @@ -355,15 +378,20 @@ void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 level, c temp_cursor.insertText(qtimestamp); } - const QString qchannel = (level <= static_cast(Log::Level::Warning)) ? - QStringLiteral("%1(%2): ").arg(level_characters[level]).arg(channel) : - QStringLiteral("%1/%2: ").arg(level_characters[level]).arg(channel); + const Log::Level level = Log::UnpackLevel(static_cast(cat)); + const Log::Color color = (Log::UnpackColor(static_cast(cat)) == Log::Color::Default) ? + Log::GetColorForLevel(level) : + Log::UnpackColor(static_cast(cat)); + const QString qchannel = + (level <= Log::Level::Warning) ? + QStringLiteral("%1(%2): ").arg(level_characters[static_cast(level)]).arg(channel) : + QStringLiteral("%1/%2: ").arg(level_characters[static_cast(level)]).arg(channel); format.setForeground(QBrush(channel_color[dark])); temp_cursor.setCharFormat(format); temp_cursor.insertText(qchannel); // message has \n already - format.setForeground(QBrush(level_colors[dark][level])); + format.setForeground(QBrush(message_colors[dark][static_cast(color)])); temp_cursor.setCharFormat(format); temp_cursor.insertText(message); } diff --git a/src/duckstation-qt/logwindow.h b/src/duckstation-qt/logwindow.h index ffd2e0ee1..1c7f6a7a2 100644 --- a/src/duckstation-qt/logwindow.h +++ b/src/duckstation-qt/logwindow.h @@ -32,7 +32,7 @@ private: void updateLogLevelUi(); void setLogLevel(Log::Level level); - static void logCallback(void* pUserParam, const char* channelName, const char* functionName, Log::Level level, + static void logCallback(void* pUserParam, Log::MessageCategory cat, const char* functionName, std::string_view message); protected: @@ -42,7 +42,7 @@ protected: private Q_SLOTS: void onClearTriggered(); void onSaveTriggered(); - void appendMessage(const QLatin1StringView& channel, quint32 level, const QString& message); + void appendMessage(const QLatin1StringView& channel, quint32 cat, const QString& message); private: static constexpr int DEFAULT_WIDTH = 750;