Markdown Highlighter: more speed

This commit is contained in:
Le Tan 2017-11-30 21:25:28 +08:00
parent 4ec340a403
commit 72946d0e15
6 changed files with 89 additions and 27 deletions

View File

@ -34,8 +34,8 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &s
m_codeBlockStyles(codeBlockStyles), m_codeBlockStyles(codeBlockStyles),
m_numOfCodeBlockHighlightsToRecv(0), m_numOfCodeBlockHighlightsToRecv(0),
parsing(0), parsing(0),
m_blockHLResultReady(false),
waitInterval(waitInterval), waitInterval(waitInterval),
m_firstParse(true),
content(NULL), content(NULL),
capacity(0), capacity(0),
result(NULL) result(NULL)
@ -65,7 +65,10 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &s
timer = new QTimer(this); timer = new QTimer(this);
timer->setSingleShot(true); timer->setSingleShot(true);
timer->setInterval(this->waitInterval); timer->setInterval(this->waitInterval);
connect(timer, &QTimer::timeout, this, &HGMarkdownHighlighter::timerTimeout); connect(timer, &QTimer::timeout,
this, [this]() {
startParseAndHighlight(false);
});
static const int completeWaitTime = 500; static const int completeWaitTime = 500;
m_completeTimer = new QTimer(this); m_completeTimer = new QTimer(this);
@ -111,7 +114,7 @@ void HGMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &p
void HGMarkdownHighlighter::highlightBlock(const QString &text) void HGMarkdownHighlighter::highlightBlock(const QString &text)
{ {
int blockNum = currentBlock().blockNumber(); int blockNum = currentBlock().blockNumber();
if (!parsing && blockHighlights.size() > blockNum) { if (m_blockHLResultReady && blockHighlights.size() > blockNum) {
const QVector<HLUnit> &units = blockHighlights[blockNum]; const QVector<HLUnit> &units = blockHighlights[blockNum];
for (int i = 0; i < units.size(); ++i) { for (int i = 0; i < units.size(); ++i) {
// TODO: merge two format within the same range // 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)) { if (!parsing.testAndSetRelaxed(0, 1)) {
return; return;
@ -467,16 +470,22 @@ void HGMarkdownHighlighter::parse()
} }
{ {
m_blockHLResultReady = false;
int nrBlocks = document->blockCount(); int nrBlocks = document->blockCount();
parseInternal(); parseInternal();
initBlockHighlightFromResult(nrBlocks); initBlockHighlightFromResult(nrBlocks);
initHtmlCommentRegionsFromResult(); m_blockHLResultReady = true;
initImageRegionsFromResult(); if (!p_fast) {
initHtmlCommentRegionsFromResult();
initHeaderRegionsFromResult(); initImageRegionsFromResult();
initHeaderRegionsFromResult();
}
if (result) { if (result) {
pmh_free_elements(result); pmh_free_elements(result);
@ -524,25 +533,32 @@ void HGMarkdownHighlighter::handleContentChange(int /* position */, int charsRem
timer->start(); timer->start();
} }
void HGMarkdownHighlighter::timerTimeout() void HGMarkdownHighlighter::startParseAndHighlight(bool p_fast)
{ {
qDebug() << "HGMarkdownHighlighter start a new parse"; qDebug() << "HGMarkdownHighlighter start a new parse (fast" << p_fast << ")";
parse(); parse(p_fast);
if (!updateCodeBlocks() || m_firstParse) {
if (p_fast) {
rehighlight(); rehighlight();
} } else {
if (!updateCodeBlocks()) {
rehighlight();
}
highlightChanged(); highlightChanged();
if (m_firstParse) {
m_firstParse = false;
} }
} }
void HGMarkdownHighlighter::updateHighlight() void HGMarkdownHighlighter::updateHighlight()
{ {
timer->stop(); timer->stop();
timerTimeout(); startParseAndHighlight(false);
}
void HGMarkdownHighlighter::updateHighlightFast()
{
timer->stop();
startParseAndHighlight(true);
} }
bool HGMarkdownHighlighter::updateCodeBlocks() bool HGMarkdownHighlighter::updateCodeBlocks()

View File

@ -128,6 +128,9 @@ public:
void clearPossiblePreviewBlocks(const QVector<int> &p_blocksToClear); void clearPossiblePreviewBlocks(const QVector<int> &p_blocksToClear);
// Parse and only update the highlight results for rehighlight().
void updateHighlightFast();
signals: signals:
void highlightCompleted(); void highlightCompleted();
@ -144,11 +147,14 @@ protected:
void highlightBlock(const QString &text) Q_DECL_OVERRIDE; void highlightBlock(const QString &text) Q_DECL_OVERRIDE;
public slots: public slots:
// Parse and rehighlight immediately.
void updateHighlight(); void updateHighlight();
private slots: private slots:
void handleContentChange(int position, int charsRemoved, int charsAdded); 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: private:
QRegExp codeBlockStartExp; QRegExp codeBlockStartExp;
@ -186,12 +192,13 @@ private:
QTimer *m_completeTimer; QTimer *m_completeTimer;
QAtomicInt parsing; QAtomicInt parsing;
// Whether highlight results for blocks are ready.
bool m_blockHLResultReady;
QTimer *timer; QTimer *timer;
int waitInterval; int waitInterval;
// Whether this is the first parse.
bool m_firstParse;
// Block number of those blocks which possible contains previewed image. // Block number of those blocks which possible contains previewed image.
QSet<int> m_possiblePreviewBlocks; QSet<int> m_possiblePreviewBlocks;
@ -209,7 +216,8 @@ private:
// intended to complement this. // intended to complement this.
void highlightLinkWithSpacesInURL(const QString &p_text); void highlightLinkWithSpacesInURL(const QString &p_text);
void parse(); void parse(bool p_fast = false);
void parseInternal(); void parseInternal();
// Init highlight elements for all the blocks from parse results. // Init highlight elements for all the blocks from parse results.

View File

@ -8,8 +8,11 @@
VCodeBlockHighlightHelper::VCodeBlockHighlightHelper(HGMarkdownHighlighter *p_highlighter, VCodeBlockHighlightHelper::VCodeBlockHighlightHelper(HGMarkdownHighlighter *p_highlighter,
VDocument *p_vdoc, VDocument *p_vdoc,
MarkdownConverterType p_type) MarkdownConverterType p_type)
: QObject(p_highlighter), m_highlighter(p_highlighter), m_vdocument(p_vdoc), : QObject(p_highlighter),
m_type(p_type), m_timeStamp(0) m_highlighter(p_highlighter),
m_vdocument(p_vdoc),
m_type(p_type),
m_timeStamp(0)
{ {
connect(m_highlighter, &HGMarkdownHighlighter::codeBlocksUpdated, connect(m_highlighter, &HGMarkdownHighlighter::codeBlocksUpdated,
this, &VCodeBlockHighlightHelper::handleCodeBlocksUpdated); this, &VCodeBlockHighlightHelper::handleCodeBlocksUpdated);
@ -56,6 +59,16 @@ QString VCodeBlockHighlightHelper::unindentCodeBlock(const QString &p_text)
void VCodeBlockHighlightHelper::handleCodeBlocksUpdated(const QVector<VCodeBlock> &p_codeBlocks) void VCodeBlockHighlightHelper::handleCodeBlocksUpdated(const QVector<VCodeBlock> &p_codeBlocks)
{ {
if (!m_vdocument->isReadyToHighlight()) {
// Immediately return empty results.
QVector<HLUnitPos> emptyRes;
for (int i = 0; i < p_codeBlocks.size(); ++i) {
updateHighlightResults(0, emptyRes);
}
return;
}
int curStamp = m_timeStamp.fetchAndAddRelaxed(1) + 1; int curStamp = m_timeStamp.fetchAndAddRelaxed(1) + 1;
m_codeBlocks = p_codeBlocks; m_codeBlocks = p_codeBlocks;
for (int i = 0; i < m_codeBlocks.size(); ++i) { for (int i = 0; i < m_codeBlocks.size(); ++i) {

View File

@ -3,7 +3,9 @@
#include <QDebug> #include <QDebug>
VDocument::VDocument(const VFile *v_file, QObject *p_parent) 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() void VDocument::noticeReadyToHighlightText()
{ {
m_readyToHighlight = true;
emit readyToHighlightText(); emit readyToHighlightText();
} }

View File

@ -31,6 +31,8 @@ public:
void setFile(const VFile *p_file); void setFile(const VFile *p_file);
bool isReadyToHighlight() const;
public slots: public slots:
// Will be called in the HTML side // Will be called in the HTML side
@ -82,6 +84,13 @@ private:
QString m_html; QString m_html;
const VFile *m_file; 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 #endif // VDOCUMENT_H

View File

@ -46,6 +46,8 @@ VMdEditor::VMdEditor(VFile *p_file,
}); });
// End. // End.
setReadOnly(true);
m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(), m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(),
g_config->getCodeBlockStyles(), g_config->getCodeBlockStyles(),
g_config->getMarkdownHighlightInterval(), g_config->getMarkdownHighlightInterval(),
@ -110,7 +112,11 @@ void VMdEditor::beginEdit()
emit statusChanged(); emit statusChanged();
updateHeaders(m_mdHighlighter->getHeaderRegions()); if (m_freshEdit) {
m_mdHighlighter->updateHighlight();
} else {
updateHeaders(m_mdHighlighter->getHeaderRegions());
}
} }
void VMdEditor::endEdit() void VMdEditor::endEdit()
@ -133,10 +139,17 @@ void VMdEditor::saveFile()
void VMdEditor::reloadFile() void VMdEditor::reloadFile()
{ {
bool readonly = isReadOnly();
setReadOnly(true);
const QString &content = m_file->getContent(); const QString &content = m_file->getContent();
setPlainText(content); setPlainText(content);
setModified(false); setModified(false);
m_mdHighlighter->updateHighlightFast();
m_freshEdit = true;
setReadOnly(readonly);
} }
bool VMdEditor::scrollToBlock(int p_blockNumber) bool VMdEditor::scrollToBlock(int p_blockNumber)