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