mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-01-15 05:00:10 +01:00
UI: colored ANSI logs fix-ups
This commit is contained in:
parent
b2768bbd61
commit
484d97caf1
|
|
@ -132,8 +132,6 @@ log_frame::log_frame(std::shared_ptr<gui_settings> _gui_settings, QWidget* paren
|
|||
m_tty->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_tty->document()->setMaximumBlockCount(max_block_count_tty);
|
||||
m_tty->installEventFilter(this);
|
||||
|
||||
m_tty_ansi_highlighter = new AnsiHighlighter(m_tty->document());
|
||||
|
||||
m_tty_input = new QLineEdit();
|
||||
if (m_tty_channel >= 0)
|
||||
|
|
@ -164,6 +162,11 @@ log_frame::log_frame(std::shared_ptr<gui_settings> _gui_settings, QWidget* paren
|
|||
CreateAndConnectActions();
|
||||
LoadSettings();
|
||||
|
||||
if (m_ansi_tty)
|
||||
{
|
||||
m_tty_ansi_highlighter = new AnsiHighlighter(m_tty->document());
|
||||
}
|
||||
|
||||
m_timer = new QTimer(this);
|
||||
connect(m_timer, &QTimer::timeout, this, &log_frame::UpdateUI);
|
||||
}
|
||||
|
|
@ -291,6 +294,16 @@ void log_frame::CreateAndConnectActions()
|
|||
{
|
||||
m_gui_settings->SetValue(gui::l_ansi_code, checked);
|
||||
m_ansi_tty = checked;
|
||||
|
||||
if (!m_tty_ansi_highlighter)
|
||||
{
|
||||
m_tty_ansi_highlighter = new AnsiHighlighter(m_tty->document());
|
||||
}
|
||||
else
|
||||
{
|
||||
delete m_tty_ansi_highlighter;
|
||||
m_tty_ansi_highlighter = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
m_tty_channel_acts = new QActionGroup(this);
|
||||
|
|
@ -602,13 +615,15 @@ void log_frame::UpdateUI()
|
|||
buf_line.assign(std::string_view(m_tty_buf).substr(str_index, m_tty_buf.find_first_of('\n', str_index) - str_index));
|
||||
str_index += buf_line.size() + 1;
|
||||
|
||||
// Ignore control characters and greater/equal to 0x80, but preserve ESC (0x1B) if ANSI mode is enabled
|
||||
buf_line.erase(std::remove_if(buf_line.begin(), buf_line.end(), [this](s8 c) {
|
||||
buf_line.erase(std::remove_if(buf_line.begin(), buf_line.end(), [this](s8 c)
|
||||
{
|
||||
// If ANSI TTY is enabled, preserve ESC (0x1B) for ANSI sequences
|
||||
if (m_ansi_tty)
|
||||
{
|
||||
// Keep ESC (0x1B) so ANSI sequences remain intact
|
||||
return c <= 0x8 || c == 0x7F || (c >= 0xE && c <= 0x1F && c != 0x1B);
|
||||
}
|
||||
|
||||
// Remove all control characters so output is clean
|
||||
return c <= 0x8 || c == 0x7F || (c >= 0xE && c <= 0x1F);
|
||||
}), buf_line.end());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/File.h"
|
||||
#include "rpcs3qt/syntax_highlighter.h"
|
||||
#include "util/logs.hpp"
|
||||
|
||||
#include "custom_dock_widget.h"
|
||||
#include "find_dialog.h"
|
||||
#include "syntax_highlighter.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -13,6 +13,8 @@
|
|||
#include <QPlainTextEdit>
|
||||
#include <QActionGroup>
|
||||
|
||||
class AnsiHighlighter;
|
||||
|
||||
class gui_settings;
|
||||
|
||||
class log_frame : public custom_dock_widget
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ private:
|
|||
QString m_full_log;
|
||||
QPlainTextEdit* m_log_text;
|
||||
LogHighlighter* m_log_highlighter;
|
||||
AnsiHighlighter* m_ansi_highlighter;
|
||||
std::unique_ptr<find_dialog> m_find_dialog;
|
||||
std::bitset<32> m_log_levels = std::bitset<32>(0b11111111u);
|
||||
bool m_show_timestamps = true;
|
||||
|
|
|
|||
|
|
@ -186,48 +186,49 @@ GlslHighlighter::GlslHighlighter(QTextDocument* parent) : Highlighter(parent)
|
|||
|
||||
AnsiHighlighter::AnsiHighlighter(QTextDocument* parent) : Highlighter(parent)
|
||||
{
|
||||
m_foreground_color = gui::utils::get_foreground_color();
|
||||
}
|
||||
|
||||
void AnsiHighlighter::highlightBlock(const QString &text)
|
||||
void AnsiHighlighter::highlightBlock(const QString& text)
|
||||
{
|
||||
// Match ANSI SGR sequences, e.g. "\x1b[31m" or "\x1b[1;32m"
|
||||
const QRegularExpression ansi_re("\x1b\\[[0-9;]*m");
|
||||
const QRegularExpression param_re("\x1b\\[([0-9;]*)m");
|
||||
static const QRegularExpression ansi_re("\x1b\\[[0-9;]*m");
|
||||
static const QRegularExpression param_re("\x1b\\[([0-9;]*)m");
|
||||
|
||||
QTextCharFormat escapeFormat;
|
||||
escapeFormat.setForeground(Qt::darkGray);
|
||||
escapeFormat.setFontItalic(true);
|
||||
static QTextCharFormat escape_format;
|
||||
escape_format.setForeground(Qt::darkGray);
|
||||
escape_format.setFontItalic(true);
|
||||
|
||||
QTextCharFormat currentFormat;
|
||||
currentFormat.setForeground(gui::utils::get_foreground_color());
|
||||
static QTextCharFormat current_format;
|
||||
current_format.setForeground(m_foreground_color);
|
||||
|
||||
int pos = 0;
|
||||
auto it = ansi_re.globalMatch(text);
|
||||
while (it.hasNext())
|
||||
{
|
||||
auto match = it.next();
|
||||
int start = match.capturedStart();
|
||||
int length = match.capturedLength();
|
||||
const auto match = it.next();
|
||||
const int start = match.capturedStart();
|
||||
const int length = match.capturedLength();
|
||||
|
||||
// Apply current format to the chunk before this escape sequence
|
||||
if (start > pos)
|
||||
{
|
||||
setFormat(pos, start - pos, currentFormat);
|
||||
setFormat(pos, start - pos, current_format);
|
||||
}
|
||||
|
||||
// Highlight the escape sequence itself
|
||||
setFormat(start, length, escapeFormat);
|
||||
setFormat(start, length, escape_format);
|
||||
|
||||
// Parse SGR parameters and update currentFormat
|
||||
QRegularExpressionMatch pm = param_re.match(match.captured());
|
||||
const QRegularExpressionMatch pm = param_re.match(match.captured());
|
||||
if (pm.hasMatch())
|
||||
{
|
||||
QString params = pm.captured(1);
|
||||
const QString params = pm.captured(1);
|
||||
if (params.isEmpty())
|
||||
{
|
||||
// empty or just \x1b[m = reset
|
||||
currentFormat = QTextCharFormat();
|
||||
currentFormat.setForeground(gui::utils::get_foreground_color());
|
||||
current_format = QTextCharFormat();
|
||||
current_format.setForeground(m_foreground_color);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -240,35 +241,35 @@ void AnsiHighlighter::highlightBlock(const QString &text)
|
|||
switch (code)
|
||||
{
|
||||
case 0:
|
||||
currentFormat = QTextCharFormat();
|
||||
currentFormat.setForeground(gui::utils::get_foreground_color());
|
||||
current_format = QTextCharFormat();
|
||||
current_format.setForeground(m_foreground_color);
|
||||
break;
|
||||
case 1:
|
||||
currentFormat.setFontWeight(QFont::Bold);
|
||||
current_format.setFontWeight(QFont::Bold);
|
||||
break;
|
||||
case 3:
|
||||
currentFormat.setFontItalic(true);
|
||||
current_format.setFontItalic(true);
|
||||
break;
|
||||
case 4:
|
||||
currentFormat.setFontUnderline(true);
|
||||
current_format.setFontUnderline(true);
|
||||
break;
|
||||
case 30: currentFormat.setForeground(Qt::black); break;
|
||||
case 31: currentFormat.setForeground(Qt::red); break;
|
||||
case 32: currentFormat.setForeground(Qt::darkGreen); break;
|
||||
case 33: currentFormat.setForeground(Qt::darkYellow); break;
|
||||
case 34: currentFormat.setForeground(Qt::darkBlue); break;
|
||||
case 35: currentFormat.setForeground(Qt::darkMagenta); break;
|
||||
case 36: currentFormat.setForeground(Qt::darkCyan); break;
|
||||
case 37: currentFormat.setForeground(Qt::lightGray); break;
|
||||
case 39: currentFormat.setForeground(gui::utils::get_foreground_color()); break;
|
||||
case 90: currentFormat.setForeground(Qt::darkGray); break;
|
||||
case 91: currentFormat.setForeground(Qt::red); break;
|
||||
case 92: currentFormat.setForeground(Qt::green); break;
|
||||
case 93: currentFormat.setForeground(Qt::yellow); break;
|
||||
case 94: currentFormat.setForeground(Qt::blue); break;
|
||||
case 95: currentFormat.setForeground(Qt::magenta); break;
|
||||
case 96: currentFormat.setForeground(Qt::cyan); break;
|
||||
case 97: currentFormat.setForeground(Qt::white); 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;
|
||||
// Background and extended colors not yet handled
|
||||
default:
|
||||
break;
|
||||
|
|
@ -282,5 +283,5 @@ void AnsiHighlighter::highlightBlock(const QString &text)
|
|||
|
||||
// Apply remaining format
|
||||
if (pos < text.length())
|
||||
setFormat(pos, text.length() - pos, currentFormat);
|
||||
setFormat(pos, text.length() - pos, current_format);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QRegularExpression>
|
||||
#include <qbrush.h>
|
||||
|
||||
// Inspired by https://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html
|
||||
|
||||
|
|
@ -61,5 +62,7 @@ public:
|
|||
explicit AnsiHighlighter(QTextDocument* parent = nullptr);
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString &text) override;
|
||||
QColor m_foreground_color;
|
||||
|
||||
void highlightBlock(const QString& text) override;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue