xml很多时候用来作为配置文件,有时为了方便在软件中查看编辑配置文件,需要一个简易的xml编辑器,qt没有提供xml语法高亮的例子,但是我们可以对着其他的例子改一个,下面是效果图:
xmlhighlighter.h:
#ifndef XMLHIGHLIGHTER_H
#define XMLHIGHLIGHTER_H
#include <QSyntaxHighlighter>
#include <QObject>
class XmlHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
explicit XmlHighlighter(QTextDocument *parent = nullptr);
protected:
void highlightBlock(const QString &text);
signals:
public slots:
private:
struct HighlightingRule
{
QRegExp pattern;
QTextCharFormat format;
};
QVector<HighlightingRule> highlightingRules;
QRegExp commentStartExpression;
QRegExp commentEndExpression;
QTextCharFormat multiLineCommentFormat;
QTextCharFormat quotationFormat;
QTextCharFormat elementNameFormat;
QTextCharFormat propertyFormat;
};
#endif // XMLHIGHLIGHTER_H
xmlhighlighter.cpp:
#include "xmlhighlighter.h"
XmlHighlighter::XmlHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
{
HighlightingRule rule;
// 双引号
quotationFormat.setForeground(Qt::blue);
rule.pattern = QRegExp("\".*\"");
rule.pattern.setMinimal(true); // 优先匹配最短的
rule.format = quotationFormat;
highlightingRules.append(rule);
// 元素名
propertyFormat.setForeground(Qt::red);
rule.pattern = QRegExp("\\b[A-Za-z0-9_]+[\\s]*(?=\\=)");
rule.pattern.setMinimal(true);
rule.format = propertyFormat;
highlightingRules.append(rule);
// 元素名
elementNameFormat.setForeground(Qt::blue);
rule.pattern = QRegExp("<[\\/]*[A-Za-z0-9_]+\\b|>");
rule.pattern.setMinimal(true);
rule.format = elementNameFormat;
highlightingRules.append(rule);
// 多行注释
multiLineCommentFormat.setForeground(Qt::darkGreen);
commentStartExpression = QRegExp("<!--");
commentEndExpression = QRegExp("-->");
}
void XmlHighlighter::highlightBlock(const QString &text)
{
foreach (const HighlightingRule &rule, highlightingRules) {
QRegExp expression(rule.pattern);
int index = expression.indexIn(text);
while (index >= 0) {
int length = expression.matchedLength();
setFormat(index, length, rule.format);
index = expression.indexIn(text, index + length);
}
}
setCurrentBlockState(0);
// 匹配多行注释
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = commentStartExpression.indexIn(text);
while (startIndex >= 0) {
int endIndex = commentEndExpression.indexIn(text, startIndex);
int commentLength;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex
+ commentEndExpression.matchedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = commentStartExpression.indexIn(text, startIndex + commentLength);
}
}
调用:
ui->textEdit->setTabStopWidth(ui->textEdit->fontMetrics().width(' ')*4); // tab键设为4个空格的宽度
new XmlHighlighter(ui->textEdit->document());