fix(StatusSyntaxHighlighter): code block fixes
- make the code bg/fg color configurable - simplify the code, no need for an extra helper class - fix code(block) regexes Needed for https://github.com/status-im/status-desktop/issues/8649
This commit is contained in:
parent
dda5e100f6
commit
210552b927
|
@ -1,50 +1,61 @@
|
||||||
#ifndef STATUSSYNTAXHIGHLIGHTER_H
|
#pragma once
|
||||||
#define STATUSSYNTAXHIGHLIGHTER_H
|
|
||||||
|
|
||||||
#include <QSyntaxHighlighter>
|
#include <QQmlParserStatus>
|
||||||
#include <QTextCharFormat>
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QSyntaxHighlighter>
|
||||||
|
|
||||||
class QQuickTextDocument;
|
class QQuickTextDocument;
|
||||||
|
class QTextCharFormat;
|
||||||
|
|
||||||
class StatusSyntaxHighlighter : public QSyntaxHighlighter
|
class StatusSyntaxHighlighter : public QSyntaxHighlighter, public QQmlParserStatus
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QQuickTextDocument* quickTextDocument READ quickTextDocument WRITE setQuickTextDocument NOTIFY
|
||||||
|
quickTextDocumentChanged REQUIRED)
|
||||||
|
Q_PROPERTY(QColor codeBackgroundColor READ codeBackgroundColor WRITE setCodeBackgroundColor NOTIFY
|
||||||
|
codeBackgroundColorChanged REQUIRED)
|
||||||
|
Q_PROPERTY(QColor codeForegroundColor READ codeForegroundColor WRITE setCodeForegroundColor NOTIFY
|
||||||
|
codeForegroundColorChanged REQUIRED)
|
||||||
|
|
||||||
|
Q_INTERFACES(QQmlParserStatus)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StatusSyntaxHighlighter(QTextDocument *parent = nullptr);
|
explicit StatusSyntaxHighlighter(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
QQuickTextDocument* quickTextDocument() const;
|
||||||
|
void setQuickTextDocument(QQuickTextDocument* quickTextDocument);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void highlightBlock(const QString &text) override;
|
void classBegin() override{};
|
||||||
|
void componentComplete() override;
|
||||||
|
void highlightBlock(const QString& text) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void quickTextDocumentChanged();
|
||||||
|
void codeBackgroundColorChanged();
|
||||||
|
void codeForegroundColorChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QQuickTextDocument* m_quicktextdocument{nullptr};
|
||||||
|
|
||||||
|
QColor m_codeBackgroundColor;
|
||||||
|
QColor codeBackgroundColor() const;
|
||||||
|
void setCodeBackgroundColor(const QColor& color);
|
||||||
|
|
||||||
|
QColor m_codeForegroundColor;
|
||||||
|
QColor codeForegroundColor() const;
|
||||||
|
void setCodeForegroundColor(const QColor& color);
|
||||||
|
|
||||||
struct HighlightingRule
|
struct HighlightingRule
|
||||||
{
|
{
|
||||||
QRegularExpression pattern;
|
QRegularExpression pattern;
|
||||||
QTextCharFormat format;
|
QTextCharFormat format;
|
||||||
};
|
};
|
||||||
QVector<HighlightingRule> highlightingRules;
|
QVector<HighlightingRule> highlightingRules{5};
|
||||||
|
|
||||||
QTextCharFormat singlelineBoldFormat;
|
QTextCharFormat singlelineBoldFormat;
|
||||||
QTextCharFormat singleLineItalicFormat;
|
QTextCharFormat singleLineItalicFormat;
|
||||||
QTextCharFormat singlelineCodeBlockFormat;
|
QTextCharFormat codeFormat;
|
||||||
QTextCharFormat singleLineStrikeThroughFormat;
|
QTextCharFormat singleLineStrikeThroughFormat;
|
||||||
QTextCharFormat multiLineCodeBlockFormat;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class StatusSyntaxHighlighterHelper : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QQuickTextDocument *quickTextDocument READ quickTextDocument WRITE
|
|
||||||
setQuickTextDocument NOTIFY quickTextDocumentChanged)
|
|
||||||
public:
|
|
||||||
StatusSyntaxHighlighterHelper(QObject *parent = nullptr)
|
|
||||||
: QObject(parent), m_quicktextdocument(nullptr) {}
|
|
||||||
QQuickTextDocument *quickTextDocument() const;
|
|
||||||
void setQuickTextDocument(QQuickTextDocument *quickTextDocument);
|
|
||||||
signals:
|
|
||||||
void quickTextDocumentChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QQuickTextDocument *m_quicktextdocument;
|
|
||||||
};
|
|
||||||
#endif // STATUSSYNTAXHIGHLIGHTER_H
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ void register_meta_types()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<QVector<int>>();
|
qRegisterMetaType<QVector<int>>();
|
||||||
qmlRegisterType<StatusWindow>("DotherSide", 0 , 1, "StatusWindow");
|
qmlRegisterType<StatusWindow>("DotherSide", 0 , 1, "StatusWindow");
|
||||||
qmlRegisterType<StatusSyntaxHighlighterHelper>("DotherSide", 0 , 1, "StatusSyntaxHighlighter");
|
qmlRegisterType<StatusSyntaxHighlighter>("DotherSide", 0 , 1, "StatusSyntaxHighlighter");
|
||||||
qmlRegisterSingletonType<QClipboardProxy>("DotherSide", 0 , 1, "QClipboardProxy", &QClipboardProxy::qmlInstance);
|
qmlRegisterSingletonType<QClipboardProxy>("DotherSide", 0 , 1, "QClipboardProxy", &QClipboardProxy::qmlInstance);
|
||||||
qmlRegisterType<RXValidator>("DotherSide", 0, 1, "RXValidator");
|
qmlRegisterType<RXValidator>("DotherSide", 0, 1, "RXValidator");
|
||||||
qqsfpm::registerTypes();
|
qqsfpm::registerTypes();
|
||||||
|
|
|
@ -1,71 +1,103 @@
|
||||||
#include "DOtherSide/DOtherSideStatusSyntaxHighlighter.h"
|
#include "DOtherSide/DOtherSideStatusSyntaxHighlighter.h"
|
||||||
#include <QQuickTextDocument>
|
|
||||||
#include <Qt>
|
|
||||||
#include <QBrush>
|
|
||||||
|
|
||||||
StatusSyntaxHighlighter::StatusSyntaxHighlighter(QTextDocument *parent)
|
#include <QQuickTextDocument>
|
||||||
|
|
||||||
|
StatusSyntaxHighlighter::StatusSyntaxHighlighter(QObject* parent)
|
||||||
: QSyntaxHighlighter(parent)
|
: QSyntaxHighlighter(parent)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void StatusSyntaxHighlighter::componentComplete()
|
||||||
{
|
{
|
||||||
HighlightingRule rule;
|
HighlightingRule rule;
|
||||||
|
|
||||||
//BOLD
|
//BOLD
|
||||||
singlelineBoldFormat.setFontWeight(QFont::Bold);
|
singlelineBoldFormat.setFontWeight(QFont::Bold);
|
||||||
rule.pattern = QRegularExpression(QStringLiteral("(\\*\\*(.*?)\\*\\*)|(\\_\\_(.*?)\\_\\_)"));
|
rule.pattern = QRegularExpression(QStringLiteral("(\\*\\*(.*?)\\*\\*)|(\\_\\_(.*?)\\_\\_)"));
|
||||||
rule.format = singlelineBoldFormat;
|
rule.format = singlelineBoldFormat;
|
||||||
highlightingRules.append(rule);
|
highlightingRules.append(rule);
|
||||||
//BOLD
|
//BOLD
|
||||||
|
|
||||||
//ITALIC
|
//ITALIC
|
||||||
singleLineItalicFormat.setFontItalic(true);
|
singleLineItalicFormat.setFontItalic(true);
|
||||||
rule.pattern = QRegularExpression(QStringLiteral("(\\*(.*?)\\*)|(\\_(.*?)\\_)"));
|
rule.pattern = QRegularExpression(QStringLiteral("(\\*(.*?)\\*)|(\\_(.*?)\\_)"));
|
||||||
rule.format = singleLineItalicFormat;
|
rule.format = singleLineItalicFormat;
|
||||||
highlightingRules.append(rule);
|
highlightingRules.append(rule);
|
||||||
//ITALIC
|
//ITALIC
|
||||||
|
|
||||||
//CODE
|
//STRIKETHROUGH
|
||||||
singlelineCodeBlockFormat.setFontFamily("Roboto Mono");
|
|
||||||
singlelineCodeBlockFormat.setBackground(QBrush(Qt::lightGray));
|
|
||||||
rule.pattern = QRegularExpression(QStringLiteral("\\`(.*?)\\`"));
|
|
||||||
rule.format = singlelineCodeBlockFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//CODE
|
|
||||||
|
|
||||||
//STRIKETHROUGH
|
|
||||||
singleLineStrikeThroughFormat.setFontStrikeOut(true);
|
singleLineStrikeThroughFormat.setFontStrikeOut(true);
|
||||||
rule.pattern = QRegularExpression(QStringLiteral("\\~\\~(.*?)\\~\\~"));
|
rule.pattern = QRegularExpression(QStringLiteral("\\~\\~(.*?)\\~\\~"));
|
||||||
rule.format = singleLineStrikeThroughFormat;
|
rule.format = singleLineStrikeThroughFormat;
|
||||||
highlightingRules.append(rule);
|
highlightingRules.append(rule);
|
||||||
//STRIKETHROUGH
|
//STRIKETHROUGH
|
||||||
|
|
||||||
//CODE BLOCK
|
//CODE (`foo`)
|
||||||
multiLineCodeBlockFormat.setFontFamily("Roboto Mono");
|
codeFormat.setFontFamily(QStringLiteral("Roboto Mono"));
|
||||||
multiLineCodeBlockFormat.setBackground(QBrush(Qt::lightGray));
|
codeFormat.setBackground(m_codeBackgroundColor);
|
||||||
rule.pattern = QRegularExpression(QStringLiteral("\\`\\`\\`(.*?)\\`\\`\\`"));
|
codeFormat.setForeground(m_codeForegroundColor);
|
||||||
rule.format = multiLineCodeBlockFormat;
|
rule.pattern = QRegularExpression(QStringLiteral("\\`{1}(.+)\\`{1}"),
|
||||||
|
// to not match single backtick pair inside a triple backtick block below
|
||||||
|
QRegularExpression::InvertedGreedinessOption);
|
||||||
|
rule.format = codeFormat;
|
||||||
highlightingRules.append(rule);
|
highlightingRules.append(rule);
|
||||||
//CODE BLOCK
|
//CODE
|
||||||
|
|
||||||
|
//CODEBLOCK (```\nfoo\nbar```)
|
||||||
|
rule.pattern = QRegularExpression(QStringLiteral("\\`{3}(.+)\\`{3}"));
|
||||||
|
rule.format = codeFormat;
|
||||||
|
highlightingRules.append(rule);
|
||||||
|
//CODEBLOCK
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusSyntaxHighlighter::highlightBlock(const QString &text)
|
void StatusSyntaxHighlighter::highlightBlock(const QString& text)
|
||||||
{
|
{
|
||||||
for (const HighlightingRule &rule : qAsConst(highlightingRules)) {
|
for(const HighlightingRule& rule : qAsConst(highlightingRules))
|
||||||
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
|
{
|
||||||
while (matchIterator.hasNext()) {
|
QRegularExpressionMatchIterator matchIterator =
|
||||||
QRegularExpressionMatch match = matchIterator.next();
|
rule.pattern.globalMatch(text, 0, QRegularExpression::PartialPreferCompleteMatch);
|
||||||
|
while(matchIterator.hasNext())
|
||||||
|
{
|
||||||
|
const QRegularExpressionMatch match = matchIterator.next();
|
||||||
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
|
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCurrentBlockState(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickTextDocument *StatusSyntaxHighlighterHelper::quickTextDocument() const {
|
QQuickTextDocument* StatusSyntaxHighlighter::quickTextDocument() const
|
||||||
|
{
|
||||||
return m_quicktextdocument;
|
return m_quicktextdocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusSyntaxHighlighterHelper::setQuickTextDocument(
|
void StatusSyntaxHighlighter::setQuickTextDocument(QQuickTextDocument* quickTextDocument)
|
||||||
QQuickTextDocument *quickTextDocument) {
|
{
|
||||||
|
if(!quickTextDocument) return;
|
||||||
|
if(quickTextDocument == m_quicktextdocument) return;
|
||||||
|
|
||||||
m_quicktextdocument = quickTextDocument;
|
m_quicktextdocument = quickTextDocument;
|
||||||
if (m_quicktextdocument) {
|
setDocument(m_quicktextdocument->textDocument());
|
||||||
new StatusSyntaxHighlighter(m_quicktextdocument->textDocument());
|
emit quickTextDocumentChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QColor StatusSyntaxHighlighter::codeBackgroundColor() const
|
||||||
|
{
|
||||||
|
return m_codeBackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusSyntaxHighlighter::setCodeBackgroundColor(const QColor& color)
|
||||||
|
{
|
||||||
|
if(color == m_codeBackgroundColor) return;
|
||||||
|
m_codeBackgroundColor = color;
|
||||||
|
emit codeBackgroundColorChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor StatusSyntaxHighlighter::codeForegroundColor() const
|
||||||
|
{
|
||||||
|
return m_codeForegroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusSyntaxHighlighter::setCodeForegroundColor(const QColor& color)
|
||||||
|
{
|
||||||
|
if(color == m_codeForegroundColor) return;
|
||||||
|
m_codeForegroundColor = color;
|
||||||
|
emit codeForegroundColorChanged();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue