Editor: improve trailing space highlight performance

This commit is contained in:
Le Tan 2018-07-29 13:20:57 +08:00
parent 8679ffa051
commit 24a20e60e9
3 changed files with 93 additions and 34 deletions

View File

@ -21,7 +21,9 @@ VEditor::VEditor(VFile *p_file, QWidget *p_editor)
m_file(p_file),
m_editOps(nullptr),
m_document(nullptr),
m_enableInputMethod(true)
m_enableInputMethod(true),
m_timeStamp(0),
m_trailingSpaceSelectionTS(0)
{
}
@ -33,6 +35,7 @@ void VEditor::init()
{
const int labelTimerInterval = 500;
const int extraSelectionHighlightTimer = 500;
const int trailingSpaceUpdateTimer = 500;
const int labelSize = 64;
m_document = documentW();
@ -67,6 +70,12 @@ void VEditor::init()
QObject::connect(m_highlightTimer, &QTimer::timeout,
m_object, &VEditorObject::doHighlightExtraSelections);
m_trailingSpaceTimer = new QTimer(m_editor);
m_trailingSpaceTimer->setSingleShot(true);
m_trailingSpaceTimer->setInterval(trailingSpaceUpdateTimer);
QObject::connect(m_trailingSpaceTimer, &QTimer::timeout,
m_object, &VEditorObject::doUpdateTrailingSpaceHighlights);
m_extraSelections.resize((int)SelectionId::MaxSelection);
updateFontAndPalette();
@ -80,18 +89,56 @@ void VEditor::labelTimerTimeout()
m_wrapLabel->hide();
}
void VEditor::updateTrailingSpaceHighlights()
{
if (m_trailingSpaceSelectionTS != m_timeStamp) {
m_trailingSpaceTimer->start();
} else {
highlightExtraSelections(false);
}
}
void VEditor::doHighlightExtraSelections()
{
int nrExtra = m_extraSelections.size();
Q_ASSERT(nrExtra == (int)SelectionId::MaxSelection);
QList<QTextEdit::ExtraSelection> extraSelects;
for (int i = 0; i < nrExtra; ++i) {
if (i == (int)SelectionId::TrailingSapce) {
filterTrailingSpace(extraSelects, m_extraSelections[i]);
} else {
extraSelects.append(m_extraSelections[i]);
}
}
setExtraSelectionsW(extraSelects);
}
void VEditor::doUpdateTrailingSpaceHighlights()
{
if (!g_config->getEnableTrailingSpaceHighlight()) {
QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::TrailingSapce];
if (!selects.isEmpty()) {
selects.clear();
highlightExtraSelections(true);
}
m_trailingSpaceSelectionTS = m_timeStamp;
return;
}
QTextCharFormat format;
format.setBackground(m_trailingSpaceColor);
QString text("\\s+$");
highlightTextAll(text,
FindOption::RegularExpression,
SelectionId::TrailingSapce,
format);
m_trailingSpaceSelectionTS = m_timeStamp;
highlightExtraSelections(true);
}
void VEditor::updateEditConfig()
{
m_config.update(QFontMetrics(m_editor->font()));
@ -109,13 +156,13 @@ void VEditor::highlightOnCursorPositionChanged()
QTextCursor cursor = textCursorW();
if (lastCursor.isNull() || cursor.blockNumber() != lastCursor.blockNumber()) {
updateTrailingSpaceHighlights();
highlightCurrentLine();
highlightTrailingSpace();
} else {
// Judge whether we have trailing space at current line.
QString text = cursor.block().text();
if (text.rbegin()->isSpace()) {
highlightTrailingSpace();
updateTrailingSpaceHighlights();
}
// Handle word-wrap in one block.
@ -129,6 +176,11 @@ void VEditor::highlightOnCursorPositionChanged()
lastCursor = cursor;
}
void VEditor::updateTimeStamp()
{
++m_timeStamp;
}
void VEditor::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::CurrentLine];
@ -172,46 +224,25 @@ void VEditor::highlightCurrentLine()
highlightExtraSelections(true);
}
// Do not highlight trailing spaces with current cursor right behind.
static void trailingSpaceFilter(VEditor *p_editor, QList<QTextEdit::ExtraSelection> &p_result)
void VEditor::filterTrailingSpace(QList<QTextEdit::ExtraSelection> &p_selects,
const QList<QTextEdit::ExtraSelection> &p_src)
{
QTextCursor cursor = p_editor->textCursorW();
QTextCursor cursor = textCursorW();
if (!cursor.atBlockEnd()) {
p_selects.append(p_src);
return;
}
int cursorPos = cursor.position();
for (auto it = p_result.begin(); it != p_result.end(); ++it) {
for (auto it = p_src.begin(); it != p_src.end(); ++it) {
if (it->cursor.selectionEnd() == cursorPos) {
p_result.erase(it);
// There will be only one.
return;
continue;
} else {
p_selects.append(*it);
}
}
}
void VEditor::highlightTrailingSpace()
{
if (!g_config->getEnableTrailingSpaceHighlight()) {
QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::TrailingSapce];
if (!selects.isEmpty()) {
selects.clear();
highlightExtraSelections(true);
}
return;
}
QTextCharFormat format;
format.setBackground(m_trailingSpaceColor);
QString text("\\s+$");
highlightTextAll(text,
FindOption::RegularExpression,
SelectionId::TrailingSapce,
format,
trailingSpaceFilter);
}
void VEditor::highlightExtraSelections(bool p_now)
{
m_highlightTimer->stop();

View File

@ -212,6 +212,8 @@ protected:
// Do some highlight on cursor position changed.
void highlightOnCursorPositionChanged();
void updateTimeStamp();
// Highlight selected text.
void highlightSelectedWord();
@ -246,7 +248,9 @@ protected:
private:
friend class VEditorObject;
void highlightTrailingSpace();
// Filter out the trailing space right before cursor.
void filterTrailingSpace(QList<QTextEdit::ExtraSelection> &p_selects,
const QList<QTextEdit::ExtraSelection> &p_src);
// Trigger the timer to request highlight.
// If @p_now is true, stop the timer and highlight immediately.
@ -310,6 +314,9 @@ private:
// Timer for extra selections highlight.
QTimer *m_highlightTimer;
// Timer for update trailing space.
QTimer *m_trailingSpaceTimer;
bool m_readyToScroll;
bool m_mouseMoveScrolled;
int m_oriMouseX;
@ -318,12 +325,20 @@ private:
// Whether enable input method.
bool m_enableInputMethod;
TimeStamp m_timeStamp;
TimeStamp m_trailingSpaceSelectionTS;
// Functions for private slots.
private:
void labelTimerTimeout();
// Do the real work to highlight extra selections.
void doHighlightExtraSelections();
void updateTrailingSpaceHighlights();
void doUpdateTrailingSpaceHighlights();
};
@ -387,6 +402,11 @@ private slots:
m_editor->doHighlightExtraSelections();
}
void doUpdateTrailingSpaceHighlights()
{
m_editor->doUpdateTrailingSpaceHighlights();
}
private:
friend class VEditor;

View File

@ -52,6 +52,14 @@ VMdEditor::VMdEditor(VFile *p_file,
highlightOnCursorPositionChanged();
});
connect(document(), &QTextDocument::contentsChange,
this, [this](int p_position, int p_charsRemoved, int p_charsAdded) {
Q_UNUSED(p_position);
if (p_charsAdded > 0 || p_charsAdded > 0) {
updateTimeStamp();
}
});
connect(this, &VTextEdit::selectionChanged,
this, [this]() {
highlightSelectedWord();