1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** Copyright (C) 2020 Francesc Martinez
7** LinkedIn: www.linkedin.com/in/cescmm/
8** Web: www.francescmm.com
9**
10** This file is part of the examples of the Qt Toolkit.
11**
12** $QT_BEGIN_LICENSE:BSD$
13** Commercial License Usage
14** Licensees holding valid commercial Qt licenses may use this file in
15** accordance with the commercial license agreement provided with the
16** Software or, alternatively, in accordance with the terms contained in
17** a written agreement between you and The Qt Company. For licensing terms
18** and conditions see https://www.qt.io/terms-conditions. For further
19** information use the contact form at https://www.qt.io/contact-us.
20**
21** BSD License Usage
22** Alternatively, you may use this file under the terms of the BSD license
23** as follows:
24**
25** "Redistribution and use in source and binary forms, with or without
26** modification, are permitted provided that the following conditions are
27** met:
28** * Redistributions of source code must retain the above copyright
29** notice, this list of conditions and the following disclaimer.
30** * Redistributions in binary form must reproduce the above copyright
31** notice, this list of conditions and the following disclaimer in
32** the documentation and/or other materials provided with the
33** distribution.
34** * Neither the name of The Qt Company Ltd nor the names of its
35** contributors may be used to endorse or promote products derived
36** from this software without specific prior written permission.
37**
38**
39** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
40** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
41** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
42** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
43** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
46** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
47** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
48** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
49** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
50**
51** $QT_END_LICENSE$
52**
53****************************************************************************/
54
55#include "Highlighter.h"
56
57namespace
58{
59
60void createHighlightningRules(QVector<Highlighter::HighlightingRule> &highlightingRules)
61{
62 if (highlightingRules.empty())
63 {
64 Highlighter::HighlightingRule rule;
65
66 QTextCharFormat format;
67 format.setForeground(QColor(255, 184, 108));
68 rule.pattern = QRegularExpression(QStringLiteral("::[A-Za-z0-9_]+"));
69 rule.format = format;
70 highlightingRules.append(rule);
71
72 format.setForeground(QColor(219, 219, 168));
73 rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()"));
74 rule.format = format;
75 highlightingRules.append(rule);
76
77 format.setForeground(QColor(80, 200, 175));
78 rule.pattern = QRegularExpression(QStringLiteral("new \\b[A-Za-z0-9_]+(?=\\()"));
79 rule.format = format;
80 highlightingRules.append(rule);
81
82 format.setForeground(QColor(87, 155, 213));
83 const QString keywordPatterns[]
84 = { QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"),
85 QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"),
86 QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"),
87 QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"),
88 QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"),
89 QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"),
90 QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"),
91 QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"),
92 QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"),
93 QStringLiteral("\\bauto\\b"), QStringLiteral("\\bexplicit\\b"), QStringLiteral("\\bfinal\\b"),
94 QStringLiteral("\\bnullptr\\b"), QStringLiteral("\\boverride\\b"), QStringLiteral("\\busing\\b"),
95 QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b"),
96 QStringLiteral("\\btrue\\b"), QStringLiteral("\\bfalse\\b"), QStringLiteral("\\bdelete\\b"),
97 QStringLiteral("\\bnew\\b"), QStringLiteral("\\bthis\\b") };
98
99 for (const QString &pattern : keywordPatterns)
100 {
101 rule.pattern = QRegularExpression(pattern);
102 rule.format = format;
103 highlightingRules.append(rule);
104 }
105
106 format.setForeground(QColor(80, 200, 175));
107 rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b"));
108 rule.format = format;
109 highlightingRules.append(rule);
110
111 format.setForeground(QColor(98, 114, 164));
112 rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
113 rule.format = format;
114 highlightingRules.append(rule);
115
116 format.setForeground(QColor(205, 144, 119));
117 rule.pattern = QRegularExpression(QStringLiteral("\".*\""));
118 rule.format = format;
119 highlightingRules.append(rule);
120
121 format.setForeground(QColor(219, 219, 168));
122 rule.pattern = QRegularExpression(QStringLiteral("\\&[A-Za-z0-9_]+::[A-Za-z0-9_]+"));
123 rule.format = format;
124 highlightingRules.append(rule);
125
126 format.setForeground(QColor(80, 200, 175));
127 rule.pattern = QRegularExpression(QStringLiteral("\\&?\\b[A-Za-z0-9_]+::"));
128 rule.format = format;
129 highlightingRules.append(rule);
130
131 format.setForeground(QColor(205, 144, 119));
132 rule.pattern = QRegularExpression(QStringLiteral("<[A-Za-z0-9_\\.]+>"));
133 rule.format = format;
134 highlightingRules.append(rule);
135
136 format.setForeground(QColor(80, 200, 175));
137 rule.pattern = QRegularExpression(QStringLiteral("[A-Za-z0-9_\\.]+<[A-Za-z0-9_\\.]+>"));
138 rule.format = format;
139 highlightingRules.append(rule);
140
141 format.setForeground(QColor(195, 133, 191));
142 rule.pattern = QRegularExpression(QStringLiteral("#include"));
143 rule.format = format;
144 highlightingRules.append(rule);
145
146 format.setForeground(Qt::white);
147 rule.pattern = QRegularExpression(QStringLiteral("::"));
148 rule.format = format;
149 highlightingRules.append(rule);
150 }
151}
152
153}
154
155QVector<Highlighter::HighlightingRule> Highlighter::highlightingRules;
156
157Highlighter::Highlighter(QTextDocument *parent)
158 : QSyntaxHighlighter(parent)
159{
160 createHighlightningRules(highlightingRules);
161 multiLineCommentFormat.setForeground(QColor(98, 114, 164));
162 commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
163 commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
164}
165
166void Highlighter::highlightBlock(const QString &text)
167{
168 for (const HighlightingRule &rule : qAsConst(highlightingRules))
169 {
170 QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
171 while (matchIterator.hasNext())
172 {
173 QRegularExpressionMatch match = matchIterator.next();
174 setFormat(match.capturedStart(), match.capturedLength(), rule.format);
175 }
176 }
177 setCurrentBlockState(0);
178
179 int startIndex = 0;
180 if (previousBlockState() != 1)
181 startIndex = text.indexOf(commentStartExpression);
182
183 while (startIndex >= 0)
184 {
185 QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
186 int endIndex = match.capturedStart();
187 int commentLength = 0;
188
189 if (endIndex == -1)
190 {
191 setCurrentBlockState(1);
192 commentLength = text.length() - startIndex;
193 }
194 else
195 {
196 commentLength = endIndex - startIndex + match.capturedLength();
197 }
198 setFormat(startIndex, commentLength, multiLineCommentFormat);
199 startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
200 }
201}
202