From 24a20e60e956483cbc0ce3cca7400dc09fab77e3 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sun, 29 Jul 2018 13:20:57 +0800 Subject: [PATCH] Editor: improve trailing space highlight performance --- src/veditor.cpp | 97 +++++++++++++++++++++++++++++++---------------- src/veditor.h | 22 ++++++++++- src/vmdeditor.cpp | 8 ++++ 3 files changed, 93 insertions(+), 34 deletions(-) diff --git a/src/veditor.cpp b/src/veditor.cpp index c7cc5aff..cf7477df 100644 --- a/src/veditor.cpp +++ b/src/veditor.cpp @@ -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 extraSelects; for (int i = 0; i < nrExtra; ++i) { - extraSelects.append(m_extraSelections[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 &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 &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 &p_result) +void VEditor::filterTrailingSpace(QList &p_selects, + const QList &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 &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(); diff --git a/src/veditor.h b/src/veditor.h index 3888ee4e..c3bdb6bf 100644 --- a/src/veditor.h +++ b/src/veditor.h @@ -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 &p_selects, + const QList &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; diff --git a/src/vmdeditor.cpp b/src/vmdeditor.cpp index 73812de7..74a883eb 100644 --- a/src/vmdeditor.cpp +++ b/src/vmdeditor.cpp @@ -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();