#ifndef PEGMARKDOWNHIGHLIGHTER_H #define PEGMARKDOWNHIGHLIGHTER_H #include #include #include "vtextblockdata.h" #include "markdownhighlighterdata.h" #include "peghighlighterresult.h" class PegParser; class QTimer; class PegMarkdownHighlighter : public QSyntaxHighlighter { Q_OBJECT public: explicit PegMarkdownHighlighter(QTextDocument *p_doc = nullptr); void init(const QVector &p_styles, const QHash &p_codeBlockStyles, bool p_mathjaxEnabled, int p_timerInterval); // Set code block highlight result by VCodeBlockHighlightHelper. void setCodeBlockHighlights(TimeStamp p_timeStamp, const QVector &p_units); const QVector &getHeaderRegions() const; const QSet &getPossiblePreviewBlocks() const; void clearPossiblePreviewBlocks(const QVector &p_blocksToClear); void addPossiblePreviewBlock(int p_blockNumber); // Parse and only update the highlight results for rehighlight(). void updateHighlightFast(); QHash &getCodeBlockStyles(); QVector &getStyles(); const QVector &getStyles() const; const QTextDocument *getDocument() const; public slots: // Parse and rehighlight immediately. void updateHighlight(); signals: void highlightCompleted(); // QVector is implicitly shared. void codeBlocksUpdated(TimeStamp p_timeStamp, const QVector &p_codeBlocks); // Emitted when image regions have been fetched from a new parsing result. void imageLinksUpdated(const QVector &p_imageRegions); // Emitted when header regions have been fetched from a new parsing result. void headersUpdated(const QVector &p_headerRegions); // Emitted when Mathjax blocks updated. void mathjaxBlocksUpdated(const QVector &p_mathjaxBlocks); protected: void highlightBlock(const QString &p_text) Q_DECL_OVERRIDE; private slots: void handleContentsChange(int p_position, int p_charsRemoved, int p_charsAdded); void handleParseResult(const QSharedPointer &p_result); private: void startParse(); void startFastParse(int p_position, int p_charsRemoved, int p_charsAdded); void updateCodeBlocks(QSharedPointer p_result); // Set the user data of currentBlock(). void updateBlockUserData(int p_blockNum, const QString &p_text); void updateBlockUserState(const QSharedPointer &p_result, int p_blockNum, const QString &p_text); // Highlight fenced code block according to VCodeBlockHighlightHelper result. void highlightCodeBlock(const QSharedPointer &p_result, int p_blockNum, const QString &p_text); // Highlight color column in code block. void highlightCodeBlockColorColumn(const QString &p_text); VTextBlockData *currentBlockData() const; VTextBlockData *previousBlockData() const; void completeHighlight(QSharedPointer p_result); bool isMathJaxEnabled() const; void getFastParseBlockRange(int p_position, int p_charsRemoved, int p_charsAdded, int &p_firstBlock, int &p_lastBlock) const; void processFastParseResult(const QSharedPointer &p_result); void highlightBlockOne(const QVector> &p_highlights, int p_blockNum); // To avoid line height jitter. void preHighlightSingleFormatBlock(const QVector> &p_highlights, int p_blockNum, const QString &p_text); void updateSingleFormatBlocks(const QVector> &p_highlights); QTextDocument *m_doc; TimeStamp m_timeStamp; QVector m_styles; QHash m_codeBlockStyles; QTextCharFormat m_codeBlockFormat; QTextCharFormat m_colorColumnFormat; PegParser *m_parser; QSharedPointer m_result; QSharedPointer m_fastResult; // Block number of those blocks which possible contains previewed image. QSet m_possiblePreviewBlocks; // Extensions for parser. int m_parserExts; // Timer to trigger parse. QTimer *m_timer; QTimer *m_fastParseTimer; // Blocks have only one format set which occupies the whole block. QSet m_singleFormatBlocks; }; inline const QVector &PegMarkdownHighlighter::getHeaderRegions() const { return m_result->m_headerRegions; } inline const QSet &PegMarkdownHighlighter::getPossiblePreviewBlocks() const { return m_possiblePreviewBlocks; } inline void PegMarkdownHighlighter::clearPossiblePreviewBlocks(const QVector &p_blocksToClear) { for (auto i : p_blocksToClear) { m_possiblePreviewBlocks.remove(i); } } inline void PegMarkdownHighlighter::addPossiblePreviewBlock(int p_blockNumber) { m_possiblePreviewBlocks.insert(p_blockNumber); } inline QHash &PegMarkdownHighlighter::getCodeBlockStyles() { return m_codeBlockStyles; } inline QVector &PegMarkdownHighlighter::getStyles() { return m_styles; } inline const QVector &PegMarkdownHighlighter::getStyles() const { return m_styles; } inline const QTextDocument *PegMarkdownHighlighter::getDocument() const { return m_doc; } inline VTextBlockData *PegMarkdownHighlighter::currentBlockData() const { return static_cast(currentBlockUserData()); } inline VTextBlockData *PegMarkdownHighlighter::previousBlockData() const { QTextBlock block = currentBlock().previous(); if (!block.isValid()) { return NULL; } return static_cast(block.userData()); } inline bool PegMarkdownHighlighter::isMathJaxEnabled() const { return m_parserExts & pmh_EXT_MATH; } #endif // PEGMARKDOWNHIGHLIGHTER_H