diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index 0e1b0fb129..cf570eea7a 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -220,7 +220,7 @@ void log_frame::CreateAndConnectActions() // I, for one, welcome our lambda overlord // It's either this or a signal mapper // Then, probably making a list of these actions so that it's easier to iterate to generate the mapper. - auto l_initAct = [this](QAction* act, logs::level logLevel) + const auto l_initAct = [this](QAction* act, logs::level logLevel) { act->setCheckable(true); @@ -293,7 +293,7 @@ void log_frame::CreateAndConnectActions() if (m_ansi_tty && !m_tty_ansi_highlighter) { - m_tty_ansi_highlighter = new AnsiHighlighter(m_tty->document()); + m_tty_ansi_highlighter = new AnsiHighlighter(m_tty); } else if (!m_ansi_tty && m_tty_ansi_highlighter) { @@ -602,6 +602,12 @@ void log_frame::RepaintTextColors() html.replace(old_style, new_style); m_log->document()->setHtml(html); + + if (m_tty_ansi_highlighter) + { + m_tty_ansi_highlighter->update_colors(m_tty); + m_tty_ansi_highlighter->rehighlight(); + } } void log_frame::UpdateUI() diff --git a/rpcs3/rpcs3qt/qt_utils.cpp b/rpcs3/rpcs3qt/qt_utils.cpp index a957dba11c..73dbaa87b6 100644 --- a/rpcs3/rpcs3qt/qt_utils.cpp +++ b/rpcs3/rpcs3qt/qt_utils.cpp @@ -173,21 +173,45 @@ namespace gui } return res; } - - QColor get_foreground_color() + + QColor get_foreground_color(QWidget* widget) { + if (widget) + { + widget->ensurePolished(); + return widget->palette().color(QPalette::ColorRole::WindowText); + } + QLabel dummy_color; dummy_color.ensurePolished(); return dummy_color.palette().color(QPalette::ColorRole::WindowText); } - QColor get_background_color() + QColor get_background_color(QWidget* widget) { + if (widget) + { + widget->ensurePolished(); + return widget->palette().color(QPalette::ColorRole::Window); + } + QLabel dummy_color; dummy_color.ensurePolished(); return dummy_color.palette().color(QPalette::ColorRole::Window); } + QColor adjust_color_for_background(const QColor& fg, const QColor& bg) + { + const int diff = fg.lightness() - bg.lightness(); + + if (std::abs(diff) >= 40) + { + return fg; + } + + return (bg.lightness() < 128) ? fg.lighter(180) : fg.darker(180); + } + QColor get_label_color(const QString& object_name, const QColor& fallback_light, const QColor& fallback_dark, QPalette::ColorRole color_role) { if (!gui::custom_stylesheet_active || !gui::stylesheet.contains(object_name)) diff --git a/rpcs3/rpcs3qt/qt_utils.h b/rpcs3/rpcs3qt/qt_utils.h index c08c5665a7..98e0eb8cd6 100644 --- a/rpcs3/rpcs3qt/qt_utils.h +++ b/rpcs3/rpcs3qt/qt_utils.h @@ -68,11 +68,14 @@ namespace gui // Returns a list of all base names of files in dir whose complete file names contain one of the given name_filters QStringList get_dir_entries(const QDir& dir, const QStringList& name_filters, bool full_path = false); - // Returns the foreground color of QLabel with respect to the current light/dark mode. - QColor get_foreground_color(); + // Returns the foreground color of QLabel or the given widget with respect to the current light/dark mode. + QColor get_foreground_color(QWidget* widget = nullptr); - // Returns the background color of QLabel with respect to the current light/dark mode. - QColor get_background_color(); + // Returns the background color of QLabel or the given widget with respect to the current light/dark mode. + QColor get_background_color(QWidget* widget = nullptr); + + // Returns an adjusted color with better contrast, depending on the background. + QColor adjust_color_for_background(const QColor& fg, const QColor& bg); // Returns the color specified by its color_role for the QLabels with object_name QColor get_label_color(const QString& object_name, const QColor& fallback_light, const QColor& fallback_dark, QPalette::ColorRole color_role = QPalette::WindowText); diff --git a/rpcs3/rpcs3qt/syntax_highlighter.cpp b/rpcs3/rpcs3qt/syntax_highlighter.cpp index 2fd43033d5..a15e36c3a4 100644 --- a/rpcs3/rpcs3qt/syntax_highlighter.cpp +++ b/rpcs3/rpcs3qt/syntax_highlighter.cpp @@ -184,12 +184,37 @@ GlslHighlighter::GlslHighlighter(QTextDocument* parent) : Highlighter(parent) commentEndExpression = QRegularExpression("\\*/"); } -AnsiHighlighter::AnsiHighlighter(QTextDocument* parent) : Highlighter(parent) +AnsiHighlighter::AnsiHighlighter(QPlainTextEdit* text_edit) + : Highlighter(text_edit ? text_edit->document() : nullptr) { - m_escape_format.setForeground(Qt::darkGray); - m_escape_format.setFontItalic(true); + update_colors(text_edit); +} - m_foreground_color = gui::utils::get_foreground_color(); +void AnsiHighlighter::update_colors(QPlainTextEdit* text_edit) +{ + m_foreground_color = gui::utils::get_foreground_color(text_edit); + m_background_color = gui::utils::get_background_color(text_edit); + + m_foreground_colors[30] = gui::utils::adjust_color_for_background(Qt::black, m_background_color); + m_foreground_colors[31] = gui::utils::adjust_color_for_background(Qt::red, m_background_color); + m_foreground_colors[32] = gui::utils::adjust_color_for_background(Qt::darkGreen, m_background_color); + m_foreground_colors[33] = gui::utils::adjust_color_for_background(Qt::darkYellow, m_background_color); + m_foreground_colors[34] = gui::utils::adjust_color_for_background(Qt::darkBlue, m_background_color); + m_foreground_colors[35] = gui::utils::adjust_color_for_background(Qt::darkMagenta, m_background_color); + m_foreground_colors[36] = gui::utils::adjust_color_for_background(Qt::darkCyan, m_background_color); + m_foreground_colors[37] = gui::utils::adjust_color_for_background(Qt::lightGray, m_background_color); + m_foreground_colors[39] = m_foreground_color; + m_foreground_colors[90] = gui::utils::adjust_color_for_background(Qt::darkGray, m_background_color); + m_foreground_colors[91] = gui::utils::adjust_color_for_background(Qt::red, m_background_color); + m_foreground_colors[92] = gui::utils::adjust_color_for_background(Qt::green, m_background_color); + m_foreground_colors[93] = gui::utils::adjust_color_for_background(Qt::yellow, m_background_color); + m_foreground_colors[94] = gui::utils::adjust_color_for_background(Qt::blue, m_background_color); + m_foreground_colors[95] = gui::utils::adjust_color_for_background(Qt::magenta, m_background_color); + m_foreground_colors[96] = gui::utils::adjust_color_for_background(Qt::cyan, m_background_color); + m_foreground_colors[97] = gui::utils::adjust_color_for_background(Qt::white, m_background_color); + + m_escape_format.setForeground(gui::utils::adjust_color_for_background(Qt::darkGray, m_background_color)); + m_escape_format.setFontItalic(true); } void AnsiHighlighter::highlightBlock(const QString& text) @@ -235,39 +260,26 @@ void AnsiHighlighter::highlightBlock(const QString& text) if (!ok) continue; switch (code) { - case 0: - current_format = QTextCharFormat(); - current_format.setForeground(m_foreground_color); - break; - case 1: - current_format.setFontWeight(QFont::Bold); - break; - case 3: - current_format.setFontItalic(true); - break; - case 4: - current_format.setFontUnderline(true); - break; - case 30: current_format.setForeground(Qt::black); break; - case 31: current_format.setForeground(Qt::red); break; - case 32: current_format.setForeground(Qt::darkGreen); break; - case 33: current_format.setForeground(Qt::darkYellow); break; - case 34: current_format.setForeground(Qt::darkBlue); break; - case 35: current_format.setForeground(Qt::darkMagenta); break; - case 36: current_format.setForeground(Qt::darkCyan); break; - case 37: current_format.setForeground(Qt::lightGray); break; - case 39: current_format.setForeground(m_foreground_color); break; - case 90: current_format.setForeground(Qt::darkGray); break; - case 91: current_format.setForeground(Qt::red); break; - case 92: current_format.setForeground(Qt::green); break; - case 93: current_format.setForeground(Qt::yellow); break; - case 94: current_format.setForeground(Qt::blue); break; - case 95: current_format.setForeground(Qt::magenta); break; - case 96: current_format.setForeground(Qt::cyan); break; - case 97: current_format.setForeground(Qt::white); break; + case 0: + current_format = QTextCharFormat(); + current_format.setForeground(m_foreground_color); + break; + case 1: + current_format.setFontWeight(QFont::Bold); + break; + case 3: + current_format.setFontItalic(true); + break; + case 4: + current_format.setFontUnderline(true); + break; + default: // Background and extended colors not yet handled - default: - break; + if (const auto it = m_foreground_colors.find(code); it != m_foreground_colors.cend()) + { + current_format.setForeground(it->second); + } + break; } } } @@ -278,5 +290,7 @@ void AnsiHighlighter::highlightBlock(const QString& text) // Apply remaining format if (pos < text.length()) + { setFormat(pos, text.length() - pos, current_format); + } } diff --git a/rpcs3/rpcs3qt/syntax_highlighter.h b/rpcs3/rpcs3qt/syntax_highlighter.h index 3854059dd7..d94d600dd6 100644 --- a/rpcs3/rpcs3qt/syntax_highlighter.h +++ b/rpcs3/rpcs3qt/syntax_highlighter.h @@ -3,6 +3,9 @@ #include #include #include +#include + +#include // Inspired by https://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html @@ -59,7 +62,9 @@ class AnsiHighlighter : public Highlighter Q_OBJECT public: - explicit AnsiHighlighter(QTextDocument* parent = nullptr); + explicit AnsiHighlighter(QPlainTextEdit* text_edit); + + void update_colors(QPlainTextEdit* text_edit); protected: const QRegularExpression ansi_re = QRegularExpression("\x1b\\[[0-9;]*m"); @@ -67,6 +72,8 @@ protected: QTextCharFormat m_escape_format; QColor m_foreground_color; + QColor m_background_color; + std::map m_foreground_colors; void highlightBlock(const QString& text) override; };