1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <QXmlStreamReader>
41
42#include "qcoloringmessagehandler_p.h"
43#include "qxmlpatternistcli_p.h"
44
45QT_BEGIN_NAMESPACE
46
47using namespace QPatternist;
48
49ColoringMessageHandler::ColoringMessageHandler(QObject *parent) : QAbstractMessageHandler(parent)
50{
51 m_classToColor.insert(akey: QLatin1String("XQuery-data"), avalue: Data);
52 m_classToColor.insert(akey: QLatin1String("XQuery-expression"), avalue: Keyword);
53 m_classToColor.insert(akey: QLatin1String("XQuery-function"), avalue: Keyword);
54 m_classToColor.insert(akey: QLatin1String("XQuery-keyword"), avalue: Keyword);
55 m_classToColor.insert(akey: QLatin1String("XQuery-type"), avalue: Keyword);
56 m_classToColor.insert(akey: QLatin1String("XQuery-uri"), avalue: Data);
57 m_classToColor.insert(akey: QLatin1String("XQuery-filepath"), avalue: Data);
58
59 /* If you're tuning the colors, take it easy laddie. Take into account:
60 *
61 * - Get over your own taste, there's others too on this planet
62 * - Make sure it works well on black & white
63 * - Make sure it works well on white & black
64 */
65 insertMapping(colorID: Location, colorCode: CyanForeground);
66 insertMapping(colorID: ErrorCode, colorCode: RedForeground);
67 insertMapping(colorID: Keyword, colorCode: BlueForeground);
68 insertMapping(colorID: Data, colorCode: BlueForeground);
69 insertMapping(colorID: RunningText, colorCode: DefaultColor);
70}
71
72void ColoringMessageHandler::handleMessage(QtMsgType type,
73 const QString &description,
74 const QUrl &identifier,
75 const QSourceLocation &sourceLocation)
76{
77 const bool hasLine = sourceLocation.line() != -1;
78
79 switch(type)
80 {
81 case QtWarningMsg:
82 {
83 if(hasLine)
84 {
85 writeUncolored(message: QXmlPatternistCLI::tr(sourceText: "Warning in %1, at line %2, column %3: %4").arg(args: sourceLocation.uri().toString(),
86 args: QString::number(sourceLocation.line()),
87 args: QString::number(sourceLocation.column()),
88 args: colorifyDescription(in: description)));
89 }
90 else
91 {
92 writeUncolored(message: QXmlPatternistCLI::tr(sourceText: "Warning in %1: %2").arg(args: sourceLocation.uri().toString(),
93 args: colorifyDescription(in: description)));
94 }
95
96 break;
97 }
98 case QtFatalMsg:
99 {
100 const QString errorCode(identifier.fragment());
101 Q_ASSERT(!errorCode.isEmpty());
102 QUrl uri(identifier);
103 uri.setFragment(fragment: QString());
104
105 QString location;
106
107 if(sourceLocation.isNull())
108 location = QXmlPatternistCLI::tr(sourceText: "Unknown location");
109 else
110 location = sourceLocation.uri().toString();
111
112 QString errorId;
113 /* If it's a standard error code, we don't want to output the
114 * whole URI. */
115 if(uri.toString() == QLatin1String("http://www.w3.org/2005/xqt-errors"))
116 errorId = errorCode;
117 else
118 errorId = identifier.toString();
119
120 if(hasLine)
121 {
122 writeUncolored(message: QXmlPatternistCLI::tr(sourceText: "Error %1 in %2, at line %3, column %4: %5").arg(args: colorify(message: errorId, color: ErrorCode),
123 args: colorify(message: location, color: Location),
124 args: colorify(message: QString::number(sourceLocation.line()), color: Location),
125 args: colorify(message: QString::number(sourceLocation.column()), color: Location),
126 args: colorifyDescription(in: description)));
127 }
128 else
129 {
130 writeUncolored(message: QXmlPatternistCLI::tr(sourceText: "Error %1 in %2: %3").arg(args: colorify(message: errorId, color: ErrorCode),
131 args: colorify(message: location, color: Location),
132 args: colorifyDescription(in: description)));
133 }
134 break;
135 }
136 case QtCriticalMsg:
137 case QtDebugMsg:
138 case QtInfoMsg:
139 {
140 Q_ASSERT_X(false, Q_FUNC_INFO,
141 "message() is not supposed to receive QtCriticalMsg, QtInfoMsg or QtDebugMsg.");
142 return;
143 }
144 }
145}
146
147QString ColoringMessageHandler::colorifyDescription(const QString &in) const
148{
149 QXmlStreamReader reader(in);
150 QString result;
151 result.reserve(asize: in.size());
152 ColorType currentColor = RunningText;
153
154 while(!reader.atEnd())
155 {
156 reader.readNext();
157
158 switch(reader.tokenType())
159 {
160 case QXmlStreamReader::StartElement:
161 {
162 if(reader.name() == QLatin1String("span"))
163 {
164 Q_ASSERT(m_classToColor.contains(reader.attributes().value(QLatin1String("class")).toString()));
165 currentColor = m_classToColor.value(akey: reader.attributes().value(qualifiedName: QLatin1String("class")).toString());
166 }
167
168 continue;
169 }
170 case QXmlStreamReader::Characters:
171 {
172 result.append(s: colorify(message: reader.text().toString(), color: currentColor));
173 continue;
174 }
175 case QXmlStreamReader::EndElement:
176 {
177 currentColor = RunningText;
178 continue;
179 }
180 case QXmlStreamReader::StartDocument:
181 case QXmlStreamReader::EndDocument:
182 continue;
183 default:
184 Q_ASSERT_X(false, Q_FUNC_INFO,
185 "Unexpected node.");
186 }
187 }
188
189 Q_ASSERT_X(!reader.hasError(), Q_FUNC_INFO,
190 "The output from Patternist must be well-formed.");
191 return result;
192}
193
194QT_END_NAMESPACE
195

source code of qtxmlpatterns/src/xmlpatterns/api/qcoloringmessagehandler.cpp