Improve log formatting

* Updated log level detection for current Minecraft versions
* Better formatting: using a monospaced font and raw text instead of HTML (fixes #111)
This commit is contained in:
Petr Mrázek 2014-11-09 14:53:08 +01:00
parent f9a7c1cf21
commit 2e9284951c
3 changed files with 97 additions and 62 deletions

View File

@ -16,6 +16,14 @@ LogPage::LogPage(MinecraftProcess *proc, QWidget *parent)
connect(m_process, SIGNAL(log(QString, MessageLevel::Enum)), this, connect(m_process, SIGNAL(log(QString, MessageLevel::Enum)), this,
SLOT(write(QString, MessageLevel::Enum))); SLOT(write(QString, MessageLevel::Enum)));
// create the format and set its font
defaultFormat = new QTextCharFormat(ui->text->currentCharFormat());
QFont font;
font.setFamily("Courier");
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
defaultFormat->setFont(font);
auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this); auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
connect(findShortcut, SIGNAL(activated()), SLOT(findActivated())); connect(findShortcut, SIGNAL(activated()), SLOT(findActivated()));
auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this); auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this);
@ -28,6 +36,7 @@ LogPage::LogPage(MinecraftProcess *proc, QWidget *parent)
LogPage::~LogPage() LogPage::~LogPage()
{ {
delete ui; delete ui;
delete defaultFormat;
} }
bool LogPage::apply() bool LogPage::apply()
@ -107,24 +116,6 @@ void LogPage::findPreviousActivated()
} }
} }
void LogPage::writeColor(QString text, const char *color, const char *background)
{
// append a paragraph
QString newtext;
newtext += "<span style=\"";
{
if (color)
newtext += QString("color:") + color + ";";
if (background)
newtext += QString("background-color:") + background + ";";
newtext += "font-family: monospace;";
}
newtext += "\">";
newtext += text.toHtmlEscaped();
newtext += "</span>";
ui->text->appendHtml(newtext);
}
void LogPage::write(QString data, MessageLevel::Enum mode) void LogPage::write(QString data, MessageLevel::Enum mode)
{ {
if (!m_write_active) if (!m_write_active)
@ -159,31 +150,59 @@ void LogPage::write(QString data, MessageLevel::Enum mode)
for (QString &paragraph : paragraphs) for (QString &paragraph : paragraphs)
{ {
//TODO: implement filtering here. //TODO: implement filtering here.
filtered.append(paragraph.trimmed()); filtered.append(paragraph);
} }
QListIterator<QString> iter(filtered); QListIterator<QString> iter(filtered);
if (mode == MessageLevel::MultiMC) QTextCharFormat format(*defaultFormat);
while (iter.hasNext())
writeColor(iter.next(), "blue", 0); switch(mode)
else if (mode == MessageLevel::Error) {
while (iter.hasNext()) case MessageLevel::MultiMC:
writeColor(iter.next(), "red", 0); {
else if (mode == MessageLevel::Warning) format.setForeground(QColor("blue"));
while (iter.hasNext()) break;
writeColor(iter.next(), "orange", 0); }
else if (mode == MessageLevel::Fatal) case MessageLevel::Debug:
while (iter.hasNext()) {
writeColor(iter.next(), "red", "black"); format.setForeground(QColor("green"));
else if (mode == MessageLevel::Debug) break;
while (iter.hasNext()) }
writeColor(iter.next(), "green", 0); case MessageLevel::Warning:
else if (mode == MessageLevel::PrePost) {
while (iter.hasNext()) format.setForeground(QColor("orange"));
writeColor(iter.next(), "grey", 0); break;
// TODO: implement other MessageLevels }
else case MessageLevel::Error:
while (iter.hasNext()) {
writeColor(iter.next(), 0, 0); format.setForeground(QColor("red"));
break;
}
case MessageLevel::Fatal:
{
format.setForeground(QColor("red"));
format.setBackground(QColor("black"));
}
case MessageLevel::PrePost:
{
format.setForeground(QColor("grey"));
}
case MessageLevel::Info:
case MessageLevel::Message:
default:
{
// do nothing, keep original
}
}
while (iter.hasNext())
{
// append a paragraph/line
auto workCursor = ui->text->textCursor();
workCursor.movePosition(QTextCursor::End);
workCursor.insertText(iter.next(), format);
workCursor.insertBlock();
}
if (isVisible()) if (isVisible())
{ {
if (m_scroll_active) if (m_scroll_active)

View File

@ -28,6 +28,7 @@ namespace Ui
{ {
class LogPage; class LogPage;
} }
class QTextCharFormat;
class LogPage : public QWidget, public BasePage class LogPage : public QWidget, public BasePage
{ {
@ -55,15 +56,6 @@ public:
} }
virtual bool shouldDisplay() const; virtual bool shouldDisplay() const;
private:
/**
* @brief write a colored paragraph
* @param data the string
* @param color the css color name
* this will only insert a single paragraph.
* \n are ignored. a real \n is always appended.
*/
void writeColor(QString text, const char *color, const char *background);
private slots: private slots:
/** /**
* @brief write a string * @brief write a string
@ -90,4 +82,6 @@ private:
bool m_scroll_active = true; bool m_scroll_active = true;
int m_saved_offset = 0; int m_saved_offset = 0;
bool m_write_active = true; bool m_write_active = true;
QTextCharFormat * defaultFormat;
}; };

View File

@ -144,19 +144,41 @@ QString MinecraftProcess::censorPrivateInfo(QString in)
// console window // console window
MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLevel::Enum level) MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLevel::Enum level)
{ {
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") || QRegularExpression re("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
line.contains("[FINER]") || line.contains("[FINEST]")) auto match = re.match(line);
level = MessageLevel::Message; if(match.hasMatch())
if (line.contains("[SEVERE]") || line.contains("[STDERR]")) {
level = MessageLevel::Error; // New style logs from log4j
if (line.contains("[WARNING]")) QString timestamp = match.captured("timestamp");
level = MessageLevel::Warning; QString levelStr = match.captured("level");
if (line.contains("Exception in thread") || line.contains(" at ")) if(levelStr == "INFO")
level = MessageLevel::Fatal; level = MessageLevel::Message;
if (line.contains("[DEBUG]")) if(levelStr == "WARN")
level = MessageLevel::Debug; level = MessageLevel::Warning;
if(levelStr == "ERROR")
level = MessageLevel::Error;
if(levelStr == "FATAL")
level = MessageLevel::Fatal;
if(levelStr == "TRACE" || levelStr == "DEBUG")
level = MessageLevel::Debug;
}
else
{
// Old style forge logs
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
line.contains("[FINER]") || line.contains("[FINEST]"))
level = MessageLevel::Message;
if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
level = MessageLevel::Error;
if (line.contains("[WARNING]"))
level = MessageLevel::Warning;
if (line.contains("[DEBUG]"))
level = MessageLevel::Debug;
}
if (line.contains("overwriting existing")) if (line.contains("overwriting existing"))
level = MessageLevel::Fatal; return MessageLevel::Fatal;
if (line.contains("Exception in thread") || line.contains(" at "))
return MessageLevel::Fatal;
return level; return level;
} }