swift
livery.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "misc/aviation/livery.h"
5 
6 #include <QCoreApplication>
7 #include <QJsonValue>
8 #include <QStringBuilder>
9 #include <Qt>
10 #include <QtGlobal>
11 
12 #include "misc/comparefunctions.h"
14 #include "misc/logcategories.h"
16 #include "misc/propertyindexref.h"
17 #include "misc/statusmessage.h"
18 #include "misc/stringutils.h"
19 #include "misc/verify.h"
20 
21 using namespace swift::misc;
22 using namespace swift::misc::db;
23 
24 SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::aviation, CLivery)
25 
26 namespace swift::misc::aviation
27 {
28  CLivery::CLivery(const QString &combinedCode, const CAirlineIcaoCode &airline, const QString &description)
29  : CLivery(-1, combinedCode, airline, description, "", "", false)
30  {}
31 
32  CLivery::CLivery(const QString &combinedCode, const CAirlineIcaoCode &airline, const QString &description,
33  const QString &colorFuselage, const QString &colorTail, bool isMilitary)
34  : CLivery(-1, combinedCode, airline, description, colorFuselage, colorTail, isMilitary)
35  {}
36 
37  CLivery::CLivery(const QString &combinedCode, const CAirlineIcaoCode &airline, const QString &description,
38  const CRgbColor &colorFuselage, const CRgbColor &colorTail, bool isMilitary)
39  : CLivery(-1, combinedCode, airline, description, colorFuselage, colorTail, isMilitary)
40  {}
41 
42  CLivery::CLivery(int dbKey, const QString &combinedCode, const CAirlineIcaoCode &airline,
43  const QString &description, const QString &colorFuselage, const QString &colorTail,
44  bool isMilitary)
45  : IDatastoreObjectWithIntegerKey(dbKey), m_airline(airline), m_combinedCode(combinedCode.trimmed().toUpper()),
46  m_description(description.trimmed()), m_colorFuselage(CRgbColor(colorFuselage)),
47  m_colorTail(CRgbColor(colorTail)), m_military(isMilitary)
48  {}
49 
50  CLivery::CLivery(int dbKey, const QString &combinedCode, const CAirlineIcaoCode &airline,
51  const QString &description, const CRgbColor &colorFuselage, const CRgbColor &colorTail,
52  bool isMilitary)
53  : IDatastoreObjectWithIntegerKey(dbKey), m_airline(airline), m_combinedCode(combinedCode.trimmed().toUpper()),
54  m_description(description.trimmed()), m_colorFuselage(colorFuselage), m_colorTail(colorTail),
55  m_military(isMilitary)
56  {}
57 
59  {
60  return this->getCombinedCode() %
61  (this->getDescription().isEmpty() ? QString() : (u' ' % this->getDescription()));
62  }
63 
65  {
66  return this->getCombinedCode() % this->getDbKeyAsStringInParentheses(" ");
67  }
68 
70  {
71  return this->getCombinedCodePlusInfo() % this->getDbKeyAsStringInParentheses(" ");
72  }
73 
75  {
76  return this->getAirlineIcaoCode().isContainedInSimplifiedName(candidate);
77  }
78 
80  {
81  if (m_airline == airlineIcao) { return false; }
82  m_airline = airlineIcao;
83  return true;
84  }
85 
86  bool CLivery::setAirlineIcaoCodeDesignator(const QString &airlineIcaoDesignator)
87  {
88  if (m_airline.getDesignator() == airlineIcaoDesignator) { return false; }
89  m_airline.setDesignator(airlineIcaoDesignator);
90  return true;
91  }
92 
93  bool CLivery::hasColorFuselage() const { return m_colorFuselage.isValid(); }
94 
95  bool CLivery::hasColorTail() const { return m_colorTail.isValid(); }
96 
97  bool CLivery::hasValidColors() const { return this->hasColorFuselage() && this->hasColorTail(); }
98 
99  bool CLivery::matchesCombinedCode(const QString &candidate) const
100  {
101  if (candidate.isEmpty() || !this->hasCombinedCode()) { return false; }
102  const QString c(candidate.trimmed().toUpper());
103  return c == m_combinedCode;
104  }
105 
106  bool CLivery::matchesColors(const CRgbColor &fuselage, const CRgbColor &tail) const
107  {
108  return this->getColorFuselage() == fuselage && this->getColorTail() == tail;
109  }
110 
112  {
113  static const QString livery("Livery");
114  static const QString liveryI18n(QCoreApplication::translate("Aviation", "Livery"));
115 
116  return (i18n ? liveryI18n : livery) % u" cc: '" % m_combinedCode % u"' airline: '" % m_airline.toQString(i18n) %
117  u"' desc.: '" % m_description % u"' F: '" % m_colorFuselage.hex() % u"' T: '" % m_colorTail.hex() %
118  u"' Mil: " % boolToYesNo(this->isMilitary());
119 
120  // force strings for translation in resource files
121  (void)QT_TRANSLATE_NOOP("Aviation", "Livery");
122  }
123 
124  bool CLivery::hasCompleteData() const { return !m_description.isEmpty() && !m_combinedCode.isEmpty(); }
125 
127  {
128  static const CLogCategoryList cats(CLogCategoryList(this).withValidation());
129  CStatusMessageList msg;
130  if (!hasCombinedCode())
131  {
132  msg.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, u"Livery: missing livery code"));
133  }
134  if (!hasColorFuselage())
135  {
136  msg.push_back(CStatusMessage(cats, CStatusMessage::SeverityWarning, u"Livery: no fuselage color"));
137  }
138  if (!hasColorTail())
139  {
140  msg.push_back(CStatusMessage(cats, CStatusMessage::SeverityWarning, u"Livery: no tail color"));
141  }
142  if (this->isColorLivery())
143  {
144  if (!this->getAirlineIcaoCodeDesignator().isEmpty())
145  {
146  // color livery, supposed to have empty airline
148  u"Livery: color livery, but airline looks odd"));
149  }
150  }
151  else { msg.push_back(m_airline.validate()); }
152  return msg;
153  }
154 
155  bool CLivery::hasValidAirlineDesignator() const { return m_airline.hasValidDesignator(); }
156 
157  bool CLivery::hasAirlineName() const { return m_airline.hasName(); }
158 
160  {
161  Q_ASSERT_X(!m_combinedCode.startsWith("." + standardLiveryMarker()), Q_FUNC_INFO, "illegal combined code");
162  return !m_combinedCode.isEmpty();
163  }
164 
165  bool CLivery::isAirlineLivery() const { return (m_airline.hasValidDesignator()); }
166 
168  {
169  return this->isAirlineLivery() && this->getAirlineIcaoCode().isOperating();
170  }
171 
173  {
174  if (isColorLivery()) { return false; }
175  return (m_airline.hasValidDesignator() && m_combinedCode.endsWith(standardLiveryMarker()));
176  }
177 
178  bool CLivery::isColorLivery() const { return m_combinedCode.startsWith(colorLiveryMarker()); }
179 
180  double CLivery::getColorDistance(const CLivery &otherLivery) const
181  {
182  return this->getColorDistance(otherLivery.getColorFuselage(), otherLivery.getColorTail());
183  }
184 
185  double CLivery::getColorDistance(const CRgbColor &fuselage, const CRgbColor &tail) const
186  {
187  if (!fuselage.isValid() || !tail.isValid()) { return 1.0; }
188  if (this->getColorFuselage().isValid() && this->getColorTail().isValid())
189  {
190  if (this->matchesColors(fuselage, tail)) { return 0.0; } // avoid rounding
191  const double xDist = this->getColorFuselage().colorDistance(fuselage);
192  const double yDist = this->getColorTail().colorDistance(tail);
193  const double d = xDist * xDist + yDist * yDist;
194  return d / 2.0; // normalize to 0..1
195  }
196  else { return 1.0; }
197  }
198 
200  {
201  if (!existsKey(json, prefix))
202  {
203  // when using relationship, this can be null
204  return {};
205  }
206 
207  const QString combinedCode(json.value(prefix % u"combinedcode").toString());
208  if (combinedCode.isEmpty())
209  {
210  CLivery liveryStub; // only consists of id, maybe key and timestamp
211  liveryStub.setKeyVersionTimestampFromDatabaseJson(json, prefix);
212  return liveryStub;
213  }
214 
215  const bool isColorLivery = combinedCode.startsWith(colorLiveryMarker());
216  const QString description(json.value(prefix % u"description").toString());
217  const CRgbColor colorFuselage(json.value(prefix % u"colorfuselage").toString());
218  const CRgbColor colorTail(json.value(prefix % u"colortail").toString());
219  const bool military = CDatastoreUtility::dbBoolStringToBool(json.value(prefix % u"military").toString());
220  CAirlineIcaoCode airline;
221  if (!isColorLivery) { airline = CAirlineIcaoCode::fromDatabaseJson(json, "al_"); }
222  CLivery livery(combinedCode, airline, description, colorFuselage, colorTail, military);
223  livery.setKeyVersionTimestampFromDatabaseJson(json, prefix);
224 
225  // color liveries must have default ICAO, but airline liveries must have DB airline
226  SWIFT_VERIFY_X((livery.isColorLivery() && !livery.getAirlineIcaoCode().hasValidDbKey()) ||
227  (livery.isAirlineLivery() && livery.getAirlineIcaoCode().hasValidDbKey()),
228  Q_FUNC_INFO, "inconsistent data");
229 
230  return livery;
231  }
232 
234  const QString &prefix)
235  {
236  if (!existsKey(json, prefix))
237  {
238  // when using relationship, this can be null
239  return {};
240  }
241 
242  const QString combinedCode(json.value(prefix % u"combinedcode").toString());
243  if (combinedCode.isEmpty())
244  {
245  CLivery liveryStub; // only consists of id, maybe key and timestamp
246  liveryStub.setKeyVersionTimestampFromDatabaseJson(json, prefix);
247  return liveryStub;
248  }
249 
250  const bool isColorLivery = combinedCode.startsWith(colorLiveryMarker());
251  const QString description(json.value(prefix % u"description").toString());
252  const CRgbColor colorFuselage(json.value(prefix % u"colorfuselage").toString());
253  const CRgbColor colorTail(json.value(prefix % u"colortail").toString());
254  const bool military = CDatastoreUtility::dbBoolStringToBool(json.value(prefix % u"military").toString());
255 
256  CAirlineIcaoCode airline;
257  if (!isColorLivery)
258  {
259  static const QString prefixAirline("al_");
260  const int idAirlineIcao = json.value(prefixAirline % u"id").toInt(-1);
261  const bool cachedAirlineIcao = idAirlineIcao >= 0 && airlineIcaos.contains(idAirlineIcao);
262 
263  airline = cachedAirlineIcao ? airlineIcaos[idAirlineIcao] :
264  CAirlineIcaoCode::fromDatabaseJson(json, prefixAirline);
265 
266  if (!cachedAirlineIcao && airline.isLoadedFromDb()) { airlineIcaos[idAirlineIcao] = airline; }
267  }
268 
269  CLivery livery(combinedCode, airline, description, colorFuselage, colorTail, military);
270  livery.setKeyVersionTimestampFromDatabaseJson(json, prefix);
271 
272  // color liveries must have default ICAO, but airline liveries must have DB airline
273  SWIFT_VERIFY_X((livery.isColorLivery() && !livery.getAirlineIcaoCode().hasValidDbKey()) ||
274  (livery.isAirlineLivery() && livery.getAirlineIcaoCode().hasValidDbKey()),
275  Q_FUNC_INFO, "inconsistent data");
276 
277  return livery;
278  }
279 
280  bool CLivery::isValidCombinedCode(const QString &candidate)
281  {
282  if (candidate.isEmpty()) { return false; }
283  if (candidate.startsWith(colorLiveryMarker())) { return candidate.length() > colorLiveryMarker().length() + 1; }
284  else
285  {
286  if (candidate.count('.') != 1) { return false; }
287  return candidate.length() > 2;
288  }
289  }
290 
292  {
293  static const QString s("_STD");
294  return s;
295  }
296 
298  {
299  QString code(airline.getVDesignator());
300  return code.isEmpty() ? "" : code.append('.').append(standardLiveryMarker());
301  }
302 
304  {
305  static const QString s("_CC");
306  return s;
307  }
308 
310  {
311  static const QString temp("_CC_NOCOLOR");
312  return temp;
313  }
314 
315  CStatusMessage CLivery::logMessage(const CLivery &livery, const QString &message,
316  const QStringList &extraCategories, CStatusMessage::StatusSeverity s)
317  {
318  static const CLogCategoryList cats({ CLogCategories::aviation() });
319  const CStatusMessage m(cats.with(CLogCategoryList::fromQStringList(extraCategories)), s,
320  livery.hasCombinedCode() ?
321  livery.getCombinedCodePlusInfoAndId() + ": " + message.trimmed() :
322  message.trimmed());
323  return m;
324  }
325 
326  void CLivery::addLogDetailsToList(CStatusMessageList *log, const CLivery &livery, const QString &message,
327  const QStringList &extraCategories, CStatusMessage::StatusSeverity s)
328  {
329  if (!log) { return; }
330  if (message.isEmpty()) { return; }
331  log->push_back(logMessage(livery, message, extraCategories, s));
332  }
333 
335  {
336  if (index.isMyself()) { return QVariant::fromValue(*this); }
337  if (IDatastoreObjectWithIntegerKey::canHandleIndex(index))
338  {
339  return IDatastoreObjectWithIntegerKey::propertyByIndex(index);
340  }
341  const auto i = index.frontCasted<ColumnIndex>();
342  switch (i)
343  {
344  case IndexAirlineIcaoCode: return m_airline.propertyByIndex(index.copyFrontRemoved());
345  case IndexColorFuselage: return m_colorFuselage.propertyByIndex(index.copyFrontRemoved()); ;
346  case IndexColorTail: return m_colorTail.propertyByIndex(index.copyFrontRemoved());
347  case IndexDescription: return QVariant::fromValue(m_description);
348  case IndexCombinedCode: return QVariant::fromValue(m_combinedCode);
349  case IndexIsMilitary: return QVariant::fromValue(m_military);
350  default: return CValueObject::propertyByIndex(index);
351  }
352  }
353 
355  {
356  if (index.isMyself())
357  {
358  (*this) = variant.value<CLivery>();
359  return;
360  }
361  if (IDatastoreObjectWithIntegerKey::canHandleIndex(index))
362  {
363  IDatastoreObjectWithIntegerKey::setPropertyByIndex(index, variant);
364  return;
365  }
366  const auto i = index.frontCasted<ColumnIndex>();
367  switch (i)
368  {
369  case IndexDescription: m_description = variant.toString(); break;
370  case IndexAirlineIcaoCode: m_airline.setPropertyByIndex(index.copyFrontRemoved(), variant); break;
371  case IndexColorFuselage: m_colorFuselage.setPropertyByIndex(index.copyFrontRemoved(), variant); break;
372  case IndexColorTail: m_colorTail.setPropertyByIndex(index.copyFrontRemoved(), variant); break;
373  case IndexCombinedCode: this->setCombinedCode(variant.toString()); break;
374  case IndexIsMilitary: this->setMilitary(variant.toBool()); break;
375  default: CValueObject::setPropertyByIndex(index, variant); break;
376  }
377  }
378 
379  int CLivery::comparePropertyByIndex(CPropertyIndexRef index, const CLivery &compareValue) const
380  {
381  if (index.isMyself()) { return this->getCombinedCode().compare(compareValue.getCombinedCode()); }
382  if (IDatastoreObjectWithIntegerKey::canHandleIndex(index))
383  {
384  return IDatastoreObjectWithIntegerKey::comparePropertyByIndex(index, compareValue);
385  }
386  const auto i = index.frontCasted<ColumnIndex>();
387  switch (i)
388  {
389  case IndexDescription: return m_description.compare(compareValue.getDescription(), Qt::CaseInsensitive);
390  case IndexAirlineIcaoCode:
391  return m_airline.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getAirlineIcaoCode());
392  case IndexColorFuselage:
393  return m_colorFuselage.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getColorFuselage());
394  case IndexColorTail:
395  return m_colorTail.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getColorTail());
396  case IndexCombinedCode: return this->getCombinedCode().compare(compareValue.getCombinedCode());
397  case IndexIsMilitary: return Compare::compare(this->isMilitary(), compareValue.isMilitary());
398  default: break;
399  }
400  Q_ASSERT_X(false, Q_FUNC_INFO, "No compare function");
401  return 0;
402  }
403 
404  void CLivery::updateMissingParts(const CLivery &otherLivery)
405  {
406  if (!this->hasValidDbKey() && otherLivery.hasValidDbKey())
407  {
408  // we have no DB data, but the other one has
409  // so we change roles. We take the DB object as base, and update our parts
410  CLivery copy(otherLivery);
411  copy.updateMissingParts(*this);
412  *this = copy;
413  return;
414  }
415 
416  if (!m_colorFuselage.isValid()) { this->setColorFuselage(otherLivery.getColorFuselage()); }
417  if (!m_colorTail.isValid()) { this->setColorTail(otherLivery.getColorTail()); }
418  if (m_combinedCode.isEmpty()) { this->setCombinedCode(otherLivery.getCombinedCode()); }
419  if (m_description.isEmpty()) { this->setDescription(otherLivery.getDescription()); }
420 
421  m_airline.updateMissingParts(otherLivery.getAirlineIcaoCode());
422  if (!this->hasValidDbKey())
423  {
424  this->setDbKey(otherLivery.getDbKey());
425  this->setUtcTimestamp(otherLivery.getUtcTimestamp());
426  }
427  }
428 
429  QString CLivery::asHtmlSummary(const QString &separator) const
430  {
431  return QStringLiteral("%1%2Airline: %3")
432  .arg(this->getCombinedCodePlusInfoAndId(), separator,
433  this->getAirlineIcaoCode().getDesignator().isEmpty() ?
434  "No airline" :
435  this->getAirlineIcaoCode().getCombinedStringWithKey())
436  .replace(" ", "&nbsp;");
437  }
438 
439  int CLivery::calculateScore(const CLivery &otherLivery, bool preferColorLiveries, CStatusMessageList *log) const
440  {
441  if (this->isDbEqual(otherLivery))
442  {
443  addLogDetailsToList(log, *this, QStringLiteral("Equal DB code: 100"));
444  return 100;
445  }
446 
447  // get a level
448  static const int sameAirlineIcaoLevel = CAirlineIcaoCode("DLH").calculateScore(CAirlineIcaoCode("DLH"));
449  Q_ASSERT_X(sameAirlineIcaoLevel == 60, Q_FUNC_INFO, "airline scoring changed");
450 
451  int score = 0;
452  const double colorMultiplier = 1.0 - this->getColorDistance(otherLivery);
453 
454  if (this->isColorLivery() && otherLivery.isColorLivery())
455  {
456  // 2 color liveries 25..85
457  score = 25;
458  score += 60 * colorMultiplier;
460  log, *this,
461  QStringLiteral("2 color liveries, color multiplier %1: %2").arg(colorMultiplier).arg(score));
462  }
463  else if (this->isAirlineLivery() && otherLivery.isAirlineLivery())
464  {
465  // 2 airline liveries 0..85
466  // 0..50 based on ICAO
467  // 0..25 based on color distance
468  // 0..10 based on mil.flag
469  // same ICAO at least means 30, max 50
470  score = qRound(0.5 * this->getAirlineIcaoCode().calculateScore(otherLivery.getAirlineIcaoCode(), log));
471  score += 25 * colorMultiplier;
473  log, *this,
474  QStringLiteral("2 airline liveries, color multiplier %1: %2").arg(colorMultiplier).arg(score));
475  if (this->isMilitary() == otherLivery.isMilitary())
476  {
478  log, *this,
479  QStringLiteral("Mil.flag '%1' matches: %2").arg(boolToYesNo(this->isMilitary())).arg(score));
480  score += 10;
481  }
482  }
483  else if ((this->isColorLivery() && otherLivery.isAirlineLivery()) ||
484  (otherLivery.isColorLivery() && this->isAirlineLivery()))
485  {
486  // 1 airline, 1 color livery
487  // 0 .. 50
488  // 25 is weaker as same ICAO code / 2 from above
489  score = preferColorLiveries ? 25 : 0;
490  score += 25 * colorMultiplier; // needs to be the same as in 2 airlines
492  log, *this,
493  QStringLiteral("Color/airline mixed, color multiplier %1: %2").arg(colorMultiplier).arg(score));
494  }
495  return score;
496  }
497 
498  bool CLivery::isNull() const { return m_airline.isNull() && m_combinedCode.isEmpty() && m_description.isEmpty(); }
499 
501  {
502  static const CLivery null;
503  return null;
504  }
505 } // namespace swift::misc::aviation
static const QString & aviation()
Aviation specific.
A sequence of log categories.
static CLogCategoryList fromQStringList(const QStringList &stringList)
Convert a string list, such as that returned by toQStringList(), into a CLogCategoryList.
Non-owning reference to a CPropertyIndex with a subset of its features.
Q_REQUIRED_RESULT CPropertyIndexRef copyFrontRemoved() const
Copy with first element removed.
CastType frontCasted() const
First element casted to given type, usually the PropertIndex enum.
bool isMyself() const
Myself index, used with nesting.
QVariant propertyByIndex(swift::misc::CPropertyIndexRef index) const
Property by index.
Definition: rgbcolor.cpp:169
QString hex(bool withHash=false) const
Hex value.
Definition: rgbcolor.cpp:100
double colorDistance(const CRgbColor &color) const
Color distance [0..1] http://stackoverflow.com/questions/4754506/color-similarity-distance-in-rgba-co...
Definition: rgbcolor.cpp:143
void setPropertyByIndex(swift::misc::CPropertyIndexRef index, const QVariant &variant)
Set property by index.
Definition: rgbcolor.cpp:183
int comparePropertyByIndex(CPropertyIndexRef index, const CRgbColor &compareValue) const
Compare for index.
Definition: rgbcolor.cpp:201
bool isValid() const
Valid?
Definition: rgbcolor.cpp:141
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition: sequence.h:305
Streamable status message, e.g.
constexpr static auto SeverityError
Status severities.
constexpr static auto SeverityWarning
Status severities.
Status messages, e.g. from Core -> GUI.
QDateTime getUtcTimestamp() const
Get timestamp.
void setUtcTimestamp(const QDateTime &timestamp)
Set timestamp.
Value object for ICAO classification.
bool isContainedInSimplifiedName(const QString &candidate) const
Does simplified name contain the candidate.
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
const QString & getDesignator() const
Get airline, e.g. "DLH".
CStatusMessageList validate() const
Validate data.
bool hasValidDesignator() const
Airline designator available?
static CAirlineIcaoCode fromDatabaseJson(const QJsonObject &json, const QString &prefix=QString())
From our DB JSON.
void updateMissingParts(const CAirlineIcaoCode &otherIcaoCode)
Update missing parts.
int calculateScore(const CAirlineIcaoCode &otherCode, CStatusMessageList *log=nullptr) const
Score against other code 0..100.
void setDesignator(const QString &icaoDesignator)
Set airline, e.g. "DLH".
int comparePropertyByIndex(CPropertyIndexRef index, const CAirlineIcaoCode &compareValue) const
Compare for index.
QString getVDesignator() const
Get airline, e.g. "DLH", but "VMVA" for virtual airlines.
bool hasName() const
Has (airline) name?
Value object encapsulating information about an airpot.
Definition: livery.h:29
bool isMilitary() const
Military livery.
Definition: livery.h:98
const CRgbColor & getColorTail() const
Get tail color.
Definition: livery.h:95
void setCombinedCode(const QString &code)
Combined code.
Definition: livery.h:107
static const QString & tempLiveryCode()
The code for a temporary livery.
Definition: livery.cpp:309
CLivery()=default
Default constructor.
bool setAirlineIcaoCode(const CAirlineIcaoCode &airlineIcao)
Airline ICAO code.
Definition: livery.cpp:79
CStatusMessageList validate() const
Validate data.
Definition: livery.cpp:126
const QString & getAirlineIcaoCodeDesignator() const
Corresponding airline designator, if any.
Definition: livery.h:68
void setColorTail(const CRgbColor &color)
Set tail color.
Definition: livery.h:113
bool hasAirlineName() const
Has airline name?
Definition: livery.cpp:157
QString convertToQString(bool i18n=false) const
Cast as QString.
Definition: livery.cpp:111
double getColorDistance(const CLivery &otherLivery) const
Color distance 0..1 (0 is best)
Definition: livery.cpp:180
ColumnIndex
Properties by index.
Definition: livery.h:33
bool isNull() const
Null livery?
Definition: livery.cpp:498
bool matchesCombinedCode(const QString &candidate) const
Matches combined code.
Definition: livery.cpp:99
static CLivery fromDatabaseJson(const QJsonObject &json, const QString &prefix=QString("liv_"))
Object from JSON.
Definition: livery.cpp:199
const CAirlineIcaoCode & getAirlineIcaoCode() const
Corresponding airline, if any.
Definition: livery.h:65
static const QString & colorLiveryMarker()
Color livery marker.
Definition: livery.cpp:303
QString asHtmlSummary(const QString &separator) const
As a brief HTML summary (e.g. used in tooltips)
Definition: livery.cpp:429
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
Definition: livery.cpp:334
QString getCombinedCodePlusInfoAndId() const
Combined code, info, plus id.
Definition: livery.cpp:69
static bool isValidCombinedCode(const QString &candidate)
Valid combined code string?
Definition: livery.cpp:280
bool setAirlineIcaoCodeDesignator(const QString &airlineIcaoDesignator)
Airline ICAO code designator.
Definition: livery.cpp:86
void setMilitary(bool isMilitary)
Military aircraft?
Definition: livery.h:128
static QString getStandardCode(const aviation::CAirlineIcaoCode &airline)
Standard code for airline.
Definition: livery.cpp:297
static CStatusMessage logMessage(const CLivery &livery, const QString &message, const QStringList &extraCategories={}, CStatusMessage::StatusSeverity s=CStatusMessage::SeverityInfo)
Specialized log message for matching / reverse lookup.
Definition: livery.cpp:315
bool hasValidAirlineDesignator() const
Airline available?
Definition: livery.cpp:155
bool hasColorTail() const
Tail color set?
Definition: livery.cpp:95
bool isAirlineOperating() const
Is airline operating?
Definition: livery.cpp:167
bool hasColorFuselage() const
Fuselage color set?
Definition: livery.cpp:93
bool hasCompleteData() const
Complete data?
Definition: livery.cpp:124
static const CLivery & null()
NULL object.
Definition: livery.cpp:500
bool isAirlineStandardLivery() const
Livery representing airline standard livery.
Definition: livery.cpp:172
const QString & getCombinedCode() const
Combined code.
Definition: livery.h:71
bool matchesColors(const CRgbColor &fuselage, const CRgbColor &tail) const
Matches colors.
Definition: livery.cpp:106
const QString & getDescription() const
Get description.
Definition: livery.h:83
void setColorFuselage(const CRgbColor &color)
Set fuselage color.
Definition: livery.h:110
bool isAirlineLivery() const
Livery representing airline.
Definition: livery.cpp:165
static CLivery fromDatabaseJsonCaching(const QJsonObject &json, AirlineIcaoIdMap &airlineIcaos, const QString &prefix=QString("liv_"))
Object from JSON caching.
Definition: livery.cpp:233
bool hasValidColors() const
Has valid (fuselage/tail) colors?
Definition: livery.cpp:97
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
Definition: livery.cpp:354
QString getCombinedCodePlusId() const
Combined code plus id.
Definition: livery.cpp:64
bool isContainedInSimplifiedAirlineName(const QString &candidate) const
Does simplified airline name contain the candidate.
Definition: livery.cpp:74
bool hasCombinedCode() const
Livery combined code available?
Definition: livery.cpp:159
bool isColorLivery() const
Color livery?
Definition: livery.cpp:178
int comparePropertyByIndex(CPropertyIndexRef index, const CLivery &compareValue) const
Compare for index.
Definition: livery.cpp:379
static const QString & standardLiveryMarker()
Standard livery marker string.
Definition: livery.cpp:291
int calculateScore(const CLivery &otherLivery, bool preferColorLiveries=false, CStatusMessageList *log=nullptr) const
Score by comparison to another livery 0..100.
Definition: livery.cpp:439
static void addLogDetailsToList(CStatusMessageList *log, const CLivery &livery, const QString &message, const QStringList &extraCategories={}, CStatusMessage::StatusSeverity s=CStatusMessage::SeverityInfo)
Specialized log for matching / reverse lookup.
Definition: livery.cpp:326
void setDescription(const QString &description)
Set description.
Definition: livery.h:125
void updateMissingParts(const CLivery &otherLivery)
Update missing parts.
Definition: livery.cpp:404
QString getCombinedCodePlusInfo() const
Combined code plus info.
Definition: livery.cpp:58
const CRgbColor & getColorFuselage() const
Get fuselage color.
Definition: livery.h:92
Class from which a derived class can inherit datastore-related functions.
Definition: datastore.h:70
bool isLoadedFromDb() const
Loaded from DB.
Definition: datastore.cpp:49
static bool existsKey(const QJsonObject &json, const QString &prefix=QString())
Is a key available?
Definition: datastore.cpp:88
void setDbKey(int key)
Set the DB key.
Definition: datastore.h:96
bool isDbEqual(const IDatastoreObjectWithIntegerKey &other) const
Same DB key and hence equal.
Definition: datastore.h:105
QString getDbKeyAsStringInParentheses(const QString &prefix={}) const
Db key in parentheses, e.g. "(3)".
Definition: datastore.cpp:36
void setKeyVersionTimestampFromDatabaseJson(const QJsonObject &json, const QString &prefix=QString())
Set key and timestamp values.
Definition: datastore.cpp:79
bool hasValidDbKey() const
Has valid DB key.
Definition: datastore.h:102
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
Definition: mixinindex.h:158
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
Definition: mixinindex.h:165
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:74
Free functions in swift::misc.
StatusSeverity
Status severities.
Definition: statusmessage.h:35
SWIFT_MISC_EXPORT const QString & boolToYesNo(bool v)
Bool to yes/no.
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
QJsonValue value(QLatin1StringView key) const const
int toInt(int defaultValue) const const
QString toString() const const
bool contains(const Key &key) const const
qsizetype count() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype length() const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toUpper() const const
QString trimmed() const const
CaseInsensitive
QVariant fromValue(T &&value)
bool toBool() const const
QString toString() const const
T value() const &const
#define SWIFT_DEFINE_VALUEOBJECT_MIXINS(Namespace, Class)
Explicit template definition of mixins for a CValueObject subclass.
Definition: valueobject.h:67
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26