From 72946d0e153e6167558950832a1fef597c956472 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Thu, 30 Nov 2017 21:25:28 +0800 Subject: [PATCH] Markdown Highlighter: more speed --- src/hgmarkdownhighlighter.cpp | 50 ++++++++++++++++++++----------- src/hgmarkdownhighlighter.h | 18 +++++++---- src/vcodeblockhighlighthelper.cpp | 17 +++++++++-- src/vdocument.cpp | 5 +++- src/vdocument.h | 9 ++++++ src/vmdeditor.cpp | 17 +++++++++-- 6 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/hgmarkdownhighlighter.cpp b/src/hgmarkdownhighlighter.cpp index 3fb236df..9728905e 100644 --- a/src/hgmarkdownhighlighter.cpp +++ b/src/hgmarkdownhighlighter.cpp @@ -34,8 +34,8 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector &s m_codeBlockStyles(codeBlockStyles), m_numOfCodeBlockHighlightsToRecv(0), parsing(0), + m_blockHLResultReady(false), waitInterval(waitInterval), - m_firstParse(true), content(NULL), capacity(0), result(NULL) @@ -65,7 +65,10 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector &s timer = new QTimer(this); timer->setSingleShot(true); timer->setInterval(this->waitInterval); - connect(timer, &QTimer::timeout, this, &HGMarkdownHighlighter::timerTimeout); + connect(timer, &QTimer::timeout, + this, [this]() { + startParseAndHighlight(false); + }); static const int completeWaitTime = 500; m_completeTimer = new QTimer(this); @@ -111,7 +114,7 @@ void HGMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &p void HGMarkdownHighlighter::highlightBlock(const QString &text) { int blockNum = currentBlock().blockNumber(); - if (!parsing && blockHighlights.size() > blockNum) { + if (m_blockHLResultReady && blockHighlights.size() > blockNum) { const QVector &units = blockHighlights[blockNum]; for (int i = 0; i < units.size(); ++i) { // TODO: merge two format within the same range @@ -456,7 +459,7 @@ void HGMarkdownHighlighter::highlightLinkWithSpacesInURL(const QString &p_text) } } -void HGMarkdownHighlighter::parse() +void HGMarkdownHighlighter::parse(bool p_fast) { if (!parsing.testAndSetRelaxed(0, 1)) { return; @@ -467,16 +470,22 @@ void HGMarkdownHighlighter::parse() } { + m_blockHLResultReady = false; + int nrBlocks = document->blockCount(); parseInternal(); initBlockHighlightFromResult(nrBlocks); - initHtmlCommentRegionsFromResult(); + m_blockHLResultReady = true; - initImageRegionsFromResult(); + if (!p_fast) { + initHtmlCommentRegionsFromResult(); - initHeaderRegionsFromResult(); + initImageRegionsFromResult(); + + initHeaderRegionsFromResult(); + } if (result) { pmh_free_elements(result); @@ -524,25 +533,32 @@ void HGMarkdownHighlighter::handleContentChange(int /* position */, int charsRem timer->start(); } -void HGMarkdownHighlighter::timerTimeout() +void HGMarkdownHighlighter::startParseAndHighlight(bool p_fast) { - qDebug() << "HGMarkdownHighlighter start a new parse"; - parse(); - if (!updateCodeBlocks() || m_firstParse) { + qDebug() << "HGMarkdownHighlighter start a new parse (fast" << p_fast << ")"; + parse(p_fast); + + if (p_fast) { rehighlight(); - } + } else { + if (!updateCodeBlocks()) { + rehighlight(); + } - highlightChanged(); - - if (m_firstParse) { - m_firstParse = false; + highlightChanged(); } } void HGMarkdownHighlighter::updateHighlight() { timer->stop(); - timerTimeout(); + startParseAndHighlight(false); +} + +void HGMarkdownHighlighter::updateHighlightFast() +{ + timer->stop(); + startParseAndHighlight(true); } bool HGMarkdownHighlighter::updateCodeBlocks() diff --git a/src/hgmarkdownhighlighter.h b/src/hgmarkdownhighlighter.h index 3415a656..8738b986 100644 --- a/src/hgmarkdownhighlighter.h +++ b/src/hgmarkdownhighlighter.h @@ -128,6 +128,9 @@ public: void clearPossiblePreviewBlocks(const QVector &p_blocksToClear); + // Parse and only update the highlight results for rehighlight(). + void updateHighlightFast(); + signals: void highlightCompleted(); @@ -144,11 +147,14 @@ protected: void highlightBlock(const QString &text) Q_DECL_OVERRIDE; public slots: + // Parse and rehighlight immediately. void updateHighlight(); private slots: void handleContentChange(int position, int charsRemoved, int charsAdded); - void timerTimeout(); + + // @p_fast: if true, just parse and update styles. + void startParseAndHighlight(bool p_fast = false); private: QRegExp codeBlockStartExp; @@ -186,12 +192,13 @@ private: QTimer *m_completeTimer; QAtomicInt parsing; + + // Whether highlight results for blocks are ready. + bool m_blockHLResultReady; + QTimer *timer; int waitInterval; - // Whether this is the first parse. - bool m_firstParse; - // Block number of those blocks which possible contains previewed image. QSet m_possiblePreviewBlocks; @@ -209,7 +216,8 @@ private: // intended to complement this. void highlightLinkWithSpacesInURL(const QString &p_text); - void parse(); + void parse(bool p_fast = false); + void parseInternal(); // Init highlight elements for all the blocks from parse results. diff --git a/src/vcodeblockhighlighthelper.cpp b/src/vcodeblockhighlighthelper.cpp index bff1cbae..a31f509c 100644 --- a/src/vcodeblockhighlighthelper.cpp +++ b/src/vcodeblockhighlighthelper.cpp @@ -8,8 +8,11 @@ VCodeBlockHighlightHelper::VCodeBlockHighlightHelper(HGMarkdownHighlighter *p_highlighter, VDocument *p_vdoc, MarkdownConverterType p_type) - : QObject(p_highlighter), m_highlighter(p_highlighter), m_vdocument(p_vdoc), - m_type(p_type), m_timeStamp(0) + : QObject(p_highlighter), + m_highlighter(p_highlighter), + m_vdocument(p_vdoc), + m_type(p_type), + m_timeStamp(0) { connect(m_highlighter, &HGMarkdownHighlighter::codeBlocksUpdated, this, &VCodeBlockHighlightHelper::handleCodeBlocksUpdated); @@ -56,6 +59,16 @@ QString VCodeBlockHighlightHelper::unindentCodeBlock(const QString &p_text) void VCodeBlockHighlightHelper::handleCodeBlocksUpdated(const QVector &p_codeBlocks) { + if (!m_vdocument->isReadyToHighlight()) { + // Immediately return empty results. + QVector emptyRes; + for (int i = 0; i < p_codeBlocks.size(); ++i) { + updateHighlightResults(0, emptyRes); + } + + return; + } + int curStamp = m_timeStamp.fetchAndAddRelaxed(1) + 1; m_codeBlocks = p_codeBlocks; for (int i = 0; i < m_codeBlocks.size(); ++i) { diff --git a/src/vdocument.cpp b/src/vdocument.cpp index 92ea9d19..66a9fe29 100644 --- a/src/vdocument.cpp +++ b/src/vdocument.cpp @@ -3,7 +3,9 @@ #include VDocument::VDocument(const VFile *v_file, QObject *p_parent) - : QObject(p_parent), m_file(v_file) + : QObject(p_parent), + m_file(v_file), + m_readyToHighlight(false) { } @@ -77,6 +79,7 @@ void VDocument::highlightTextCB(const QString &p_html, int p_id, int p_timeStamp void VDocument::noticeReadyToHighlightText() { + m_readyToHighlight = true; emit readyToHighlightText(); } diff --git a/src/vdocument.h b/src/vdocument.h index 08b51ed2..9833ae0b 100644 --- a/src/vdocument.h +++ b/src/vdocument.h @@ -31,6 +31,8 @@ public: void setFile(const VFile *p_file); + bool isReadyToHighlight() const; + public slots: // Will be called in the HTML side @@ -82,6 +84,13 @@ private: QString m_html; const VFile *m_file; + + // Whether the web side is ready to handle highlight text request. + bool m_readyToHighlight; }; +inline bool VDocument::isReadyToHighlight() const +{ + return m_readyToHighlight; +} #endif // VDOCUMENT_H diff --git a/src/vmdeditor.cpp b/src/vmdeditor.cpp index f2e515f6..29e4ef6f 100644 --- a/src/vmdeditor.cpp +++ b/src/vmdeditor.cpp @@ -46,6 +46,8 @@ VMdEditor::VMdEditor(VFile *p_file, }); // End. + setReadOnly(true); + m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(), g_config->getCodeBlockStyles(), g_config->getMarkdownHighlightInterval(), @@ -110,7 +112,11 @@ void VMdEditor::beginEdit() emit statusChanged(); - updateHeaders(m_mdHighlighter->getHeaderRegions()); + if (m_freshEdit) { + m_mdHighlighter->updateHighlight(); + } else { + updateHeaders(m_mdHighlighter->getHeaderRegions()); + } } void VMdEditor::endEdit() @@ -133,10 +139,17 @@ void VMdEditor::saveFile() void VMdEditor::reloadFile() { + bool readonly = isReadOnly(); + setReadOnly(true); + const QString &content = m_file->getContent(); setPlainText(content); - setModified(false); + m_mdHighlighter->updateHighlightFast(); + + m_freshEdit = true; + + setReadOnly(readonly); } bool VMdEditor::scrollToBlock(int p_blockNumber)