Browse Source

Editor: improve trailing space highlight performance

Le Tan 7 years ago
parent
commit
24a20e60e9
3 changed files with 93 additions and 34 deletions
  1. 64 33
      src/veditor.cpp
  2. 21 1
      src/veditor.h
  3. 8 0
      src/vmdeditor.cpp

+ 64 - 33
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<QTextEdit::ExtraSelection> 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<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,44 +224,23 @@ 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;
-        }
-    }
-}
-
-void VEditor::highlightTrailingSpace()
-{
-    if (!g_config->getEnableTrailingSpaceHighlight()) {
-        QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::TrailingSapce];
-        if (!selects.isEmpty()) {
-            selects.clear();
-            highlightExtraSelections(true);
+            continue;
+        } else {
+            p_selects.append(*it);
         }
-        return;
     }
-
-    QTextCharFormat format;
-    format.setBackground(m_trailingSpaceColor);
-    QString text("\\s+$");
-    highlightTextAll(text,
-                     FindOption::RegularExpression,
-                     SelectionId::TrailingSapce,
-                     format,
-                     trailingSpaceFilter);
 }
 
 void VEditor::highlightExtraSelections(bool p_now)

+ 21 - 1
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<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;
 

+ 8 - 0
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();