Browse Source

UI: Fix performance issues with the Log Viewer

This commit includes two big changes, alongside other smaller tweaks.

1) Update the internal QTextDocument of the text component directly
2) Use QPlainTextEdit, which supports HTML & is designed for long text
3) Use QString's arg function for formatting strings

Fix 1 significantly improves realtime performance when adding lines
individually, to the point that the UI no longer freezes if the viewer
is open and the log is being spammed. It also improves initial launch
speed when there's a large amount of text already in the file.
Reference: https://stackoverflow.com/a/54501760/2763321

Fix 2 completely eliminates delay when opening the viewer, regardless
of how many lines are already in the log file. For a standard log
after OBS launch, this cuts opening time from about 2 seconds to half a
second. For anything longer than 1,000 lines, the UI no longer freezes,
and the viewer (& its contents) open within half a second.
Reference: https://stackoverflow.com/a/17466240/2763321
Matt Gajownik 3 years ago
parent
commit
0e57a7beef
2 changed files with 21 additions and 13 deletions
  1. 19 11
      UI/log-viewer.cpp
  2. 2 2
      UI/log-viewer.hpp

+ 19 - 11
UI/log-viewer.cpp

@@ -24,7 +24,7 @@ OBSLogViewer::OBSLogViewer(QWidget *parent) : QDialog(parent)
 	const QFont fixedFont =
 	const QFont fixedFont =
 		QFontDatabase::systemFont(QFontDatabase::FixedFont);
 		QFontDatabase::systemFont(QFontDatabase::FixedFont);
 
 
-	textArea = new QTextEdit();
+	textArea = new QPlainTextEdit();
 	textArea->setReadOnly(true);
 	textArea->setReadOnly(true);
 	textArea->setFont(fixedFont);
 	textArea->setFont(fixedFont);
 
 
@@ -106,13 +106,21 @@ void OBSLogViewer::InitLog()
 		in.setCodec("UTF-8");
 		in.setCodec("UTF-8");
 #endif
 #endif
 
 
+		QTextDocument *doc = textArea->document();
+		QTextCursor cursor(doc);
+		cursor.movePosition(QTextCursor::End);
+		cursor.beginEditBlock();
 		while (!in.atEnd()) {
 		while (!in.atEnd()) {
 			QString line = in.readLine();
 			QString line = in.readLine();
-			AddLine(LOG_INFO, line);
+			cursor.insertHtml(line);
+			cursor.insertBlock();
 		}
 		}
+		cursor.endEditBlock();
 
 
 		file.close();
 		file.close();
 	}
 	}
+	QScrollBar *scroll = textArea->verticalScrollBar();
+	scroll->setValue(scroll->maximum());
 
 
 	obsLogViewer = this;
 	obsLogViewer = this;
 }
 }
@@ -123,12 +131,10 @@ void OBSLogViewer::AddLine(int type, const QString &str)
 
 
 	switch (type) {
 	switch (type) {
 	case LOG_WARNING:
 	case LOG_WARNING:
-		msg = QStringLiteral("<font color=\"#c08000\">") + msg +
-		      QStringLiteral("</font>");
+		msg = QString("<font color=\"#c08000\">%1</font>").arg(msg);
 		break;
 		break;
 	case LOG_ERROR:
 	case LOG_ERROR:
-		msg = QStringLiteral("<font color=\"#c00000\">") + msg +
-		      QStringLiteral("</font>");
+		msg = QString("<font color=\"#c00000\">%1</font>").arg(msg);
 		break;
 		break;
 	}
 	}
 
 
@@ -138,11 +144,13 @@ void OBSLogViewer::AddLine(int type, const QString &str)
 	if (bottomScrolled)
 	if (bottomScrolled)
 		scroll->setValue(scroll->maximum());
 		scroll->setValue(scroll->maximum());
 
 
-	QTextCursor newCursor = textArea->textCursor();
-	newCursor.movePosition(QTextCursor::End);
-	newCursor.insertHtml(
-		QStringLiteral("<pre style=\"white-space: pre-wrap\">") + msg +
-		QStringLiteral("<br></pre>"));
+	QTextDocument *doc = textArea->document();
+	QTextCursor cursor(doc);
+	cursor.movePosition(QTextCursor::End);
+	cursor.beginEditBlock();
+	cursor.insertHtml(msg);
+	cursor.insertBlock();
+	cursor.endEditBlock();
 
 
 	if (bottomScrolled)
 	if (bottomScrolled)
 		scroll->setValue(scroll->maximum());
 		scroll->setValue(scroll->maximum());

+ 2 - 2
UI/log-viewer.hpp

@@ -1,13 +1,13 @@
 #pragma once
 #pragma once
 
 
 #include <QDialog>
 #include <QDialog>
-#include <QTextEdit>
+#include <QPlainTextEdit>
 #include "obs-app.hpp"
 #include "obs-app.hpp"
 
 
 class OBSLogViewer : public QDialog {
 class OBSLogViewer : public QDialog {
 	Q_OBJECT
 	Q_OBJECT
 
 
-	QPointer<QTextEdit> textArea;
+	QPointer<QPlainTextEdit> textArea;
 
 
 	void InitLog();
 	void InitLog();