mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-06 06:19:52 +08:00
Markdown Highlighter: more speed
This commit is contained in:
parent
4ec340a403
commit
72946d0e15
@ -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()
|
||||||
|
@ -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.
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user