swift
Loading...
Searching...
No Matches
statusmessagelist.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
7
8#include <QJsonValue>
9#include <QString>
10#include <QStringBuilder>
11#include <QStringList>
12
14
15SWIFT_DEFINE_SEQUENCE_MIXINS(swift::misc, CStatusMessage, CStatusMessageList)
16
17namespace swift::misc
18{
20
21 CStatusMessageList::CStatusMessageList(const CStatusMessage &statusMessage) { this->push_back(statusMessage); }
22
23 CStatusMessageList CStatusMessageList::findByCategory(const CLogCategory &category) const
24 {
25 return this->findBy([&](const CStatusMessage &msg) { return msg.getCategories().contains(category); });
26 }
27
28 CStatusMessageList CStatusMessageList::findBySeverity(CStatusMessage::StatusSeverity severity) const
29 {
30 return this->findBy(&CStatusMessage::getSeverity, severity);
31 }
32
33 bool CStatusMessageList::hasErrorMessages() const
34 {
35 return this->contains(&CStatusMessage::getSeverity, CStatusMessage::SeverityError);
36 }
37
38 bool CStatusMessageList::hasWarningMessages() const
39 {
40 return this->contains(&CStatusMessage::getSeverity, CStatusMessage::SeverityWarning);
41 }
42
43 bool CStatusMessageList::hasWarningOrErrorMessages() const
44 {
45 return this->containsBy([=](const CStatusMessage &m) {
46 return m.getSeverity() == CStatusMessage::SeverityWarning ||
47 m.getSeverity() == CStatusMessage::SeverityError;
48 });
49 }
50
51 bool CStatusMessageList::isSuccess() const { return !this->isFailure(); }
52
53 bool CStatusMessageList::isFailure() const { return this->contains(&CStatusMessage::isFailure, true); }
54
55 CStatusMessageList CStatusMessageList::getErrorMessages() const { return findBySeverity(SeverityError); }
56
57 CStatusMessageList CStatusMessageList::getWarningAndErrorMessages() const
58 {
59 return this->findBy(
60 [&](const CStatusMessage &msg) { return msg.getSeverity() >= CStatusMessage::SeverityWarning; });
61 }
62
63 void CStatusMessageList::addCategory(const CLogCategory &category)
64 {
65 for (auto &msg : *this)
66 {
67 msg.addCategory(category);
68 }
69 }
70
71 void CStatusMessageList::addValidationCategory() { this->addCategory(CLogCategories::validation()); }
72
73 void CStatusMessageList::addCategories(const CLogCategoryList &categories)
74 {
75 for (auto &msg : *this)
76 {
77 msg.addCategories(categories);
78 }
79 }
80
81 void CStatusMessageList::addValidationMessage(const QString &validationText,
82 CStatusMessage::StatusSeverity severity)
83 {
84 static const CLogCategoryList cats({ CLogCategories::validation() });
85 const CStatusMessage msg(cats, severity, validationText);
86 this->push_back(msg);
87 }
88
89 void CStatusMessageList::setCategory(const CLogCategory &category)
90 {
91 for (auto &msg : *this)
92 {
93 msg.setCategory(category);
94 }
95 }
96
97 void CStatusMessageList::setCategories(const CLogCategoryList &categories)
98 {
99 for (auto &msg : *this)
100 {
101 msg.setCategories(categories);
102 }
103 }
104
105 void CStatusMessageList::clampSeverity(CStatusMessage::StatusSeverity severity)
106 {
107 for (auto &msg : *this)
108 {
109 msg.clampSeverity(severity);
110 }
111 }
112
113 void CStatusMessageList::warningToError()
114 {
115 for (CStatusMessage &msg : *this)
116 {
117 if (msg.getSeverity() != CStatusMessage::SeverityWarning)
118 {
119 continue;
120 }
121 msg.setSeverity(CStatusMessage::SeverityError);
122 }
123 }
124
125 void CStatusMessageList::sortBySeverity() { this->sortBy(&CStatusMessage::getSeverity); }
126
127 void CStatusMessageList::sortBySeverityHighestFirst()
128 {
129 this->sortBy(&CStatusMessage::getSeverity);
130 this->reverse();
131 }
132
133 void CStatusMessageList::removeWarningsAndBelow()
134 {
135 if (this->isEmpty())
136 {
137 return;
138 }
139 this->removeIf(&CStatusMessage::getSeverity, CStatusMessage::SeverityWarning);
140 this->removeInfoAndBelow();
141 }
142
143 void CStatusMessageList::removeSeverity(CStatusMessage::StatusSeverity severity)
144 {
145 if (this->isEmpty())
146 {
147 return;
148 }
149 this->removeIf(&CStatusMessage::getSeverity, severity);
150 }
151
152 void CStatusMessageList::removeInfoAndBelow()
153 {
154 if (this->isEmpty())
155 {
156 return;
157 }
158 this->removeIf(&CStatusMessage::getSeverity, CStatusMessage::SeverityDebug);
159 this->removeIf(&CStatusMessage::getSeverity, CStatusMessage::SeverityInfo);
160 }
161
162 int CStatusMessageList::keepLatest(int estimtatedNumber)
163 {
164 const int oldSize = this->size();
165 if (estimtatedNumber >= oldSize)
166 {
167 return 0;
168 }
169 if (estimtatedNumber < 1)
170 {
171 this->clear();
172 return oldSize;
173 }
174
175 CStatusMessageList copy(*this);
176 copy.sortLatestFirst();
177 const QDateTime ts = copy[estimtatedNumber - 1].getUtcTimestamp();
178 copy = *this; // keep order
179 copy.removeBefore(ts);
180 *this = copy;
181 return oldSize - this->size();
182 }
183
184 CStatusMessage::StatusSeverity CStatusMessageList::worstSeverity() const
185 {
186 CStatusMessage::StatusSeverity s = CStatusMessage::SeverityDebug;
187 for (const CStatusMessage &msg : *this)
188 {
189 CStatusMessage::StatusSeverity ms = msg.getSeverity();
190 if (ms == CStatusMessage::SeverityError)
191 {
192 return CStatusMessage::SeverityError;
193 }
194 if (ms <= s)
195 {
196 continue;
197 }
198 s = ms;
199 }
200 return s;
201 }
202
203 QMap<int, int> CStatusMessageList::countSeverities() const
204 {
205 QMap<int, int> counts;
206 counts.insert(SeverityDebug, 0);
207 counts.insert(SeverityInfo, 0);
208 counts.insert(SeverityWarning, 0);
209 counts.insert(SeverityError, 0);
210 for (const CStatusMessage &m : *this)
211 {
212 counts[m.getSeverity()]++;
213 }
214 return counts;
215 }
216
217 CStatusMessage CStatusMessageList::toSingleMessage() const
218 {
219 if (this->isEmpty())
220 {
221 return {};
222 }
223 if (this->size() == 1)
224 {
225 return this->front();
226 }
227 QStringList newMsgs;
228 CStatusMessage::StatusSeverity s = CStatusMessage::SeverityDebug;
229 CLogCategoryList cats;
230 for (const CStatusMessage &msg : *this)
231 {
232 if (msg.isEmpty())
233 {
234 continue;
235 }
236 newMsgs.append(msg.getMessage());
237 CStatusMessage::StatusSeverity ms = msg.getSeverity();
238 s = std::max(s, ms);
239 cats.push_back(msg.getCategories());
240 }
241 const CStatusMessage newMsg(cats, s, newMsgs.join(", "));
242 return newMsg;
243 }
244
245 QString CStatusMessageList::toHtml(const CPropertyIndexList &indexes) const
246 {
247 if (indexes.isEmpty() || this->isEmpty())
248 {
249 return {};
250 }
251 QString html;
252 int line = 1;
253 const bool withLineNumbers = indexes.contains(CPropertyIndexRef::GlobalIndexLineNumber);
254 CPropertyIndexList usedIndexes(indexes);
255 if (withLineNumbers)
256 {
257 usedIndexes.remove(CPropertyIndexRef::GlobalIndexLineNumber);
258 }
259 for (const CStatusMessage &statusMessage : *this)
260 {
261 QString rowHtml;
262 if (withLineNumbers)
263 {
264 rowHtml = u"<td>" % QString::number(line++) % u"</td>";
265 }
266
267 for (const CPropertyIndex &index : usedIndexes)
268 {
269 rowHtml += u"<td>" %
270 statusMessage.propertyByIndex(index).toString().toHtmlEscaped().replace('\n', "<br>") %
271 u"</td>";
272 }
273
274 const QString severityClass = statusMessage.getSeverityAsString();
275 html += QStringLiteral("<tr class=\"%1\">%2</tr>").arg(severityClass, rowHtml);
276 }
277 return u"<table>" % html % u"</table>";
278 }
279
280 const CPropertyIndexList &CStatusMessageList::simpleHtmlOutput()
281 {
282 static const CPropertyIndexList properties(
283 { CPropertyIndexRef::GlobalIndexLineNumber, CStatusMessage::IndexMessage });
284 return properties;
285 }
286
287 const CPropertyIndexList &CStatusMessageList::timestampHtmlOutput()
288 {
289 static const CPropertyIndexList properties(
290 { CStatusMessage::IndexUtcTimestampFormattedHms, CStatusMessage::IndexMessage });
291 return properties;
292 }
293
294 QString htmlStyleSheetImpl()
295 {
296 const QString style =
297 u'.' % CStatusMessage::severityToString(CStatusMessage::SeverityDebug) % u" { color: lightgreen; } " %
298 u'.' % CStatusMessage::severityToString(CStatusMessage::SeverityInfo) % u" { color: lightgreen; } " % u'.' %
299 CStatusMessage::severityToString(CStatusMessage::SeverityWarning) % u" { color: yellow; } " % u'.' %
300 CStatusMessage::severityToString(CStatusMessage::SeverityError) % u" { color: red; }";
301 return style;
302 }
303
304 const QString &CStatusMessageList::htmlStyleSheet()
305 {
306 static const QString style(htmlStyleSheetImpl());
307 return style;
308 }
309
310 CStatusMessageList CStatusMessageList::fromDatabaseJson(const QJsonArray &array)
311 {
312 CStatusMessageList messages;
313 for (const QJsonValue &value : array)
314 {
315 messages.push_back(CStatusMessage::fromDatabaseJson(value.toObject()));
316 }
317 return messages;
318 }
319} // namespace swift::misc
320
Generic sequential container with value semantics.
Definition sequence.h:86
Streamable status message, e.g.
CStatusMessageList()=default
Constructor.
Free functions in swift::misc.
void append(QList< T > &&value)
QMap< Key, T >::iterator insert(QMap< Key, T >::const_iterator pos, const Key &key, const T &value)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString number(double n, char format, int precision)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QString toHtmlEscaped() const const
QString join(QChar separator) const const
#define SWIFT_DEFINE_SEQUENCE_MIXINS(Namespace, T, List)
Explicit template definition of mixins for a CSequence subclass.
Definition sequence.h:63
bool isFailure(HRESULT result)
Correctly casted values/checks.