Merge pull request #13787 from jordan-woyak/game-config-highlighter-fix

DolphinQt: Make GameConfigHighlighter better handle large files.
This commit is contained in:
Tilka 2025-08-10 05:02:21 +01:00 committed by GitHub
commit 5a6c5e2639
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 43 additions and 13 deletions

View file

@ -7,6 +7,7 @@
#include <QCompleter> #include <QCompleter>
#include <QDesktopServices> #include <QDesktopServices>
#include <QFile> #include <QFile>
#include <QKeyEvent>
#include <QMenu> #include <QMenu>
#include <QMenuBar> #include <QMenuBar>
#include <QPushButton> #include <QPushButton>

View file

@ -5,6 +5,10 @@
#include <QBrush> #include <QBrush>
#include <QColor> #include <QColor>
#include <QRegularExpression>
#include <QTextBlock>
#include <QTextCharFormat>
#include <QTextDocument>
#include "DolphinQt/Settings.h" #include "DolphinQt/Settings.h"
@ -16,7 +20,7 @@ struct HighlightingRule
GameConfigHighlighter::~GameConfigHighlighter() = default; GameConfigHighlighter::~GameConfigHighlighter() = default;
GameConfigHighlighter::GameConfigHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) GameConfigHighlighter::GameConfigHighlighter(QTextDocument* parent) : QObject(parent)
{ {
const bool is_dark_theme = Settings::Instance().IsThemeDark(); const bool is_dark_theme = Settings::Instance().IsThemeDark();
@ -65,17 +69,42 @@ GameConfigHighlighter::GameConfigHighlighter(QTextDocument* parent) : QSyntaxHig
HighlightingRule{QRegularExpression(QStringLiteral("^\\$.*")), comment_format}); HighlightingRule{QRegularExpression(QStringLiteral("^\\$.*")), comment_format});
m_rules.emplace_back( m_rules.emplace_back(
HighlightingRule{QRegularExpression(QStringLiteral("^\\*.*")), comment_format}); HighlightingRule{QRegularExpression(QStringLiteral("^\\*.*")), comment_format});
// Highlight block on change.
// We're manually highlighting blocks because QSyntaxHighlighter
// hangs with large (>2MB) files for some reason.
connect(parent, &QTextDocument::contentsChange, this,
[this, parent](const int pos, int /* removed */, const int added) {
QTextBlock block = parent->findBlock(pos);
const auto pos_end = pos + added;
while (block.isValid() && block.position() <= pos_end)
{
HighlightBlock(block);
block = block.next();
}
});
// Highlight all blocks right now.
for (QTextBlock block = parent->begin(); block.isValid(); block = block.next())
HighlightBlock(block);
} }
void GameConfigHighlighter::highlightBlock(const QString& text) void GameConfigHighlighter::HighlightBlock(const QTextBlock& block)
{ {
QList<QTextLayout::FormatRange> format_ranges;
for (const auto& rule : m_rules) for (const auto& rule : m_rules)
{ {
auto it = rule.pattern.globalMatch(text); auto it = rule.pattern.globalMatch(block.text());
while (it.hasNext()) while (it.hasNext())
{ {
auto match = it.next(); const auto match = it.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format); format_ranges.emplace_back(QTextLayout::FormatRange{.start = int(match.capturedStart()),
.length = int(match.capturedLength()),
.format = rule.format});
} }
} }
block.layout()->clearFormats();
block.layout()->setFormats(format_ranges);
} }

View file

@ -5,23 +5,23 @@
#include <vector> #include <vector>
#include <QRegularExpression> #include <QObject>
#include <QSyntaxHighlighter>
#include <QTextCharFormat>
struct HighlightingRule; struct HighlightingRule;
class GameConfigHighlighter : public QSyntaxHighlighter class QTextBlock;
class QTextDocument;
class GameConfigHighlighter : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GameConfigHighlighter(QTextDocument* parent = nullptr); explicit GameConfigHighlighter(QTextDocument* parent);
~GameConfigHighlighter() override; ~GameConfigHighlighter() override;
protected:
void highlightBlock(const QString& text) override;
private: private:
void HighlightBlock(const QTextBlock& block);
std::vector<HighlightingRule> m_rules; std::vector<HighlightingRule> m_rules;
}; };