swift
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 
13 #include "misc/propertyindexlist.h"
14 
15 SWIFT_DEFINE_SEQUENCE_MIXINS(swift::misc, CStatusMessage, CStatusMessageList)
16 
17 namespace swift::misc
18 {
19  CStatusMessageList::CStatusMessageList(const CSequence<CStatusMessage> &other) : CSequence<CStatusMessage>(other) {}
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) { msg.addCategory(category); }
66  }
67 
68  void CStatusMessageList::addValidationCategory() { this->addCategory(CLogCategories::validation()); }
69 
70  void CStatusMessageList::addCategories(const CLogCategoryList &categories)
71  {
72  for (auto &msg : *this) { msg.addCategories(categories); }
73  }
74 
75  void CStatusMessageList::addValidationMessage(const QString &validationText,
77  {
78  static const CLogCategoryList cats({ CLogCategories::validation() });
79  const CStatusMessage msg(cats, severity, validationText);
80  this->push_back(msg);
81  }
82 
83  void CStatusMessageList::setCategory(const CLogCategory &category)
84  {
85  for (auto &msg : *this) { msg.setCategory(category); }
86  }
87 
88  void CStatusMessageList::setCategories(const CLogCategoryList &categories)
89  {
90  for (auto &msg : *this) { msg.setCategories(categories); }
91  }
92 
93  void CStatusMessageList::clampSeverity(CStatusMessage::StatusSeverity severity)
94  {
95  for (auto &msg : *this) { msg.clampSeverity(severity); }
96  }
97 
98  void CStatusMessageList::warningToError()
99  {
100  for (CStatusMessage &msg : *this)
101  {
102  if (msg.getSeverity() != CStatusMessage::SeverityWarning) { continue; }
103  msg.setSeverity(CStatusMessage::SeverityError);
104  }
105  }
106 
107  void CStatusMessageList::sortBySeverity() { this->sortBy(&CStatusMessage::getSeverity); }
108 
109  void CStatusMessageList::sortBySeverityHighestFirst()
110  {
111  this->sortBy(&CStatusMessage::getSeverity);
112  this->reverse();
113  }
114 
115  void CStatusMessageList::removeWarningsAndBelow()
116  {
117  if (this->isEmpty()) { return; }
118  this->removeIf(&CStatusMessage::getSeverity, CStatusMessage::SeverityWarning);
119  this->removeInfoAndBelow();
120  }
121 
122  void CStatusMessageList::removeSeverity(CStatusMessage::StatusSeverity severity)
123  {
124  if (this->isEmpty()) { return; }
125  this->removeIf(&CStatusMessage::getSeverity, severity);
126  }
127 
128  void CStatusMessageList::removeInfoAndBelow()
129  {
130  if (this->isEmpty()) { return; }
131  this->removeIf(&CStatusMessage::getSeverity, CStatusMessage::SeverityDebug);
132  this->removeIf(&CStatusMessage::getSeverity, CStatusMessage::SeverityInfo);
133  }
134 
135  int CStatusMessageList::keepLatest(int estimtatedNumber)
136  {
137  const int oldSize = this->size();
138  if (estimtatedNumber >= oldSize) { return 0; }
139  if (estimtatedNumber < 1)
140  {
141  this->clear();
142  return oldSize;
143  }
144 
145  CStatusMessageList copy(*this);
146  copy.sortLatestFirst();
147  const QDateTime ts = copy[estimtatedNumber - 1].getUtcTimestamp();
148  copy = *this; // keep order
149  copy.removeBefore(ts);
150  *this = copy;
151  return oldSize - this->size();
152  }
153 
154  CStatusMessage::StatusSeverity CStatusMessageList::worstSeverity() const
155  {
156  CStatusMessage::StatusSeverity s = CStatusMessage::SeverityDebug;
157  for (const CStatusMessage &msg : *this)
158  {
159  CStatusMessage::StatusSeverity ms = msg.getSeverity();
160  if (ms == CStatusMessage::SeverityError) { return CStatusMessage::SeverityError; }
161  if (ms <= s) { continue; }
162  s = ms;
163  }
164  return s;
165  }
166 
167  QMap<int, int> CStatusMessageList::countSeverities() const
168  {
169  QMap<int, int> counts;
170  counts.insert(SeverityDebug, 0);
171  counts.insert(SeverityInfo, 0);
172  counts.insert(SeverityWarning, 0);
173  counts.insert(SeverityError, 0);
174  for (const CStatusMessage &m : *this) { counts[m.getSeverity()]++; }
175  return counts;
176  }
177 
178  CStatusMessage CStatusMessageList::toSingleMessage() const
179  {
180  if (this->isEmpty()) { return CStatusMessage(); }
181  if (this->size() == 1) { return this->front(); }
182  QStringList newMsgs;
183  CStatusMessage::StatusSeverity s = CStatusMessage::SeverityDebug;
184  CLogCategoryList cats;
185  for (const CStatusMessage &msg : *this)
186  {
187  if (msg.isEmpty()) { continue; }
188  newMsgs.append(msg.getMessage());
189  CStatusMessage::StatusSeverity ms = msg.getSeverity();
190  if (s < ms) { s = ms; }
191  cats.push_back(msg.getCategories());
192  }
193  const CStatusMessage newMsg(cats, s, newMsgs.join(", "));
194  return newMsg;
195  }
196 
197  QString CStatusMessageList::toHtml(const CPropertyIndexList &indexes) const
198  {
199  if (indexes.isEmpty() || this->isEmpty()) { return {}; }
200  QString html;
201  int line = 1;
202  const bool withLineNumbers = indexes.contains(CPropertyIndexRef::GlobalIndexLineNumber);
203  CPropertyIndexList usedIndexes(indexes);
204  if (withLineNumbers) { usedIndexes.remove(CPropertyIndexRef::GlobalIndexLineNumber); }
205  for (const CStatusMessage &statusMessage : *this)
206  {
207  QString rowHtml;
208  if (withLineNumbers) { rowHtml = u"<td>" % QString::number(line++) % u"</td>"; }
209 
210  for (const CPropertyIndex &index : usedIndexes)
211  {
212  rowHtml += u"<td>" %
213  statusMessage.propertyByIndex(index).toString().toHtmlEscaped().replace('\n', "<br>") %
214  u"</td>";
215  }
216 
217  const QString severityClass = statusMessage.getSeverityAsString();
218  html += QStringLiteral("<tr class=\"%1\">%2</tr>").arg(severityClass, rowHtml);
219  }
220  return u"<table>" % html % u"</table>";
221  }
222 
223  const CPropertyIndexList &CStatusMessageList::simpleHtmlOutput()
224  {
225  static const CPropertyIndexList properties(
226  { CPropertyIndexRef::GlobalIndexLineNumber, CStatusMessage::IndexMessage });
227  return properties;
228  }
229 
230  const CPropertyIndexList &CStatusMessageList::timestampHtmlOutput()
231  {
232  static const CPropertyIndexList properties(
233  { CStatusMessage::IndexUtcTimestampFormattedHms, CStatusMessage::IndexMessage });
234  return properties;
235  }
236 
237  QString htmlStyleSheetImpl()
238  {
239  const QString style =
240  u'.' % CStatusMessage::severityToString(CStatusMessage::SeverityDebug) % u" { color: lightgreen; } " %
241  u'.' % CStatusMessage::severityToString(CStatusMessage::SeverityInfo) % u" { color: lightgreen; } " % u'.' %
242  CStatusMessage::severityToString(CStatusMessage::SeverityWarning) % u" { color: yellow; } " % u'.' %
243  CStatusMessage::severityToString(CStatusMessage::SeverityError) % u" { color: red; }";
244  return style;
245  }
246 
247  const QString &CStatusMessageList::htmlStyleSheet()
248  {
249  static const QString style(htmlStyleSheetImpl());
250  return style;
251  }
252 
253  CStatusMessageList CStatusMessageList::fromDatabaseJson(const QJsonArray &array)
254  {
255  CStatusMessageList messages;
256  for (const QJsonValue &value : array)
257  {
258  messages.push_back(CStatusMessage::fromDatabaseJson(value.toObject()));
259  }
260  return messages;
261  }
262 } // namespace swift::misc
263 
CStatusMessageList()=default
Constructor.
Free functions in swift::misc.
StatusSeverity
Status severities.
Definition: statusmessage.h:35
#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.