diff --git a/tools/triage/codeeditor.cpp b/tools/triage/codeeditor.cpp index 4d5461e60..51eaeb7cb 100644 --- a/tools/triage/codeeditor.cpp +++ b/tools/triage/codeeditor.cpp @@ -3,19 +3,124 @@ #include "codeeditor.h" +Highlighter::Highlighter(QTextDocument *parent) + : QSyntaxHighlighter(parent) +{ + HighlightingRule rule; + + keywordFormat.setForeground(Qt::darkBlue); + keywordFormat.setFontWeight(QFont::Bold); + QStringList keywordPatterns; + keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b" + << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b" + << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b" + << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b" + << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b" + << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b" + << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b" + << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b" + << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b" + << "\\bvoid\\b" << "\\bvolatile\\b" << "\\bbool\\b"; + foreach (const QString &pattern, keywordPatterns) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + classFormat.setFontWeight(QFont::Bold); + classFormat.setForeground(Qt::darkMagenta); + rule.pattern = QRegularExpression("\\bQ[A-Za-z]+\\b"); + rule.format = classFormat; + highlightingRules.append(rule); + + quotationFormat.setForeground(Qt::darkGreen); + rule.pattern = QRegularExpression("\".*\""); + rule.format = quotationFormat; + highlightingRules.append(rule); + + functionFormat.setFontItalic(true); + functionFormat.setForeground(Qt::blue); + rule.pattern = QRegularExpression("\\b[A-Za-z0-9_]+(?=\\()"); + rule.format = functionFormat; + highlightingRules.append(rule); + + singleLineCommentFormat.setForeground(Qt::gray); + rule.pattern = QRegularExpression("//[^\n]*"); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); + + multiLineCommentFormat.setForeground(Qt::gray); + + commentStartExpression = QRegularExpression("/\\*"); + commentEndExpression = QRegularExpression("\\*/"); +} + +void Highlighter::highlightBlock(const QString &text) +{ + foreach (const HighlightingRule &rule, highlightingRules) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + setCurrentBlockState(0); + + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = text.indexOf(commentStartExpression); + + while (startIndex >= 0) { + QRegularExpressionMatch match = commentEndExpression.match(text, startIndex); + int endIndex = match.capturedStart(); + int commentLength = 0; + if (endIndex == -1) { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } else { + commentLength = endIndex - startIndex + + match.capturedLength(); + } + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); + } +} + + CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent) { lineNumberArea = new LineNumberArea(this); + highlighter = new Highlighter(this->document()); + mErrorPosition = -1; connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine())); updateLineNumberAreaWidth(0); - highlightCurrentLine(); } +static int getPos(const QString &fileData, int lineNumber) +{ + for (int pos = 0, line = 1; pos < fileData.size(); ++pos) { + if (fileData[pos] != '\n') + continue; + ++line; + if (line == lineNumber) + return pos + 1; + } + return fileData.size(); +} +void CodeEditor::setErrorLine(int errorLine) +{ + mErrorPosition = getPos(toPlainText(), errorLine); + QTextCursor tc = textCursor(); + tc.setPosition(mErrorPosition); + setTextCursor(tc); + centerCursor(); +} int CodeEditor::lineNumberAreaWidth() { @@ -27,19 +132,14 @@ int CodeEditor::lineNumberAreaWidth() } int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; - return space; } - - void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */) { setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); } - - void CodeEditor::updateLineNumberArea(const QRect &rect, int dy) { if (dy) @@ -51,44 +151,38 @@ void CodeEditor::updateLineNumberArea(const QRect &rect, int dy) updateLineNumberAreaWidth(0); } - - -void CodeEditor::resizeEvent(QResizeEvent *e) +void CodeEditor::resizeEvent(QResizeEvent *event) { - QPlainTextEdit::resizeEvent(e); - + QPlainTextEdit::resizeEvent(event); QRect cr = contentsRect(); lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); } - - void CodeEditor::highlightCurrentLine() { + QTextCursor tc = textCursor(); + tc.setPosition(mErrorPosition); + setTextCursor(tc); + QList extraSelections; - if (!isReadOnly()) { - QTextEdit::ExtraSelection selection; + QTextEdit::ExtraSelection selection; - QColor lineColor = QColor(Qt::yellow).lighter(160); + QColor lineColor = QColor(255,220,220); - selection.format.setBackground(lineColor); - selection.format.setProperty(QTextFormat::FullWidthSelection, true); - selection.cursor = textCursor(); - selection.cursor.clearSelection(); - extraSelections.append(selection); - } + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); setExtraSelections(extraSelections); } - - void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) { QPainter painter(lineNumberArea); - painter.fillRect(event->rect(), Qt::lightGray); - + painter.fillRect(event->rect(), QColor(240,240,240)); QTextBlock block = firstVisibleBlock(); int blockNumber = block.blockNumber(); diff --git a/tools/triage/codeeditor.h b/tools/triage/codeeditor.h index 4dae5c36a..41d555016 100644 --- a/tools/triage/codeeditor.h +++ b/tools/triage/codeeditor.h @@ -1,8 +1,10 @@ #ifndef CODEEDITOR_H #define CODEEDITOR_H +#include #include #include +#include class QPaintEvent; class QResizeEvent; @@ -12,15 +14,44 @@ class QWidget; class LineNumberArea; +class Highlighter : public QSyntaxHighlighter { + Q_OBJECT + +public: + explicit Highlighter(QTextDocument *parent); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QRegularExpression commentStartExpression; + QRegularExpression commentEndExpression; + + QTextCharFormat keywordFormat; + QTextCharFormat classFormat; + QTextCharFormat singleLineCommentFormat; + QTextCharFormat multiLineCommentFormat; + QTextCharFormat quotationFormat; + QTextCharFormat functionFormat; +}; + class CodeEditor : public QPlainTextEdit { Q_OBJECT public: - explicit CodeEditor(QWidget *parent = 0); + explicit CodeEditor(QWidget *parent); void lineNumberAreaPaintEvent(QPaintEvent *event); int lineNumberAreaWidth(); + void setErrorLine(int errorLine); + protected: void resizeEvent(QResizeEvent *event) override; @@ -31,6 +62,8 @@ private slots: private: QWidget *lineNumberArea; + Highlighter *highlighter; + int mErrorPosition; };