swift
airlineicaocode.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 
6 #include <QDir>
7 #include <QStringBuilder>
8 #include <Qt>
9 #include <QtGlobal>
10 
11 #include "misc/aviation/callsign.h"
12 #include "misc/comparefunctions.h"
14 #include "misc/icons.h"
15 #include "misc/logcategories.h"
16 #include "misc/propertyindexref.h"
17 #include "misc/setbuilder.h"
18 #include "misc/statusmessage.h"
19 #include "misc/stringutils.h"
20 #include "misc/swiftdirectories.h"
21 #include "misc/verify.h"
22 
23 using namespace swift::misc;
24 using namespace swift::misc::db;
25 
26 SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::aviation, CAirlineIcaoCode)
27 
28 namespace swift::misc::aviation
29 {
30  CAirlineIcaoCode::CAirlineIcaoCode(const QString &airlineDesignator)
31  : m_designator(airlineDesignator.trimmed().toUpper())
32  {
33  if (m_designator.length() == 4) { this->setDesignator(m_designator); }
34  }
35 
36  CAirlineIcaoCode::CAirlineIcaoCode(const QString &airlineDesignator, const QString &airlineName,
37  const CCountry &country, const QString &telephony, bool virtualAirline,
38  bool operating)
39  : m_designator(airlineDesignator.trimmed().toUpper()), m_name(airlineName), m_telephonyDesignator(telephony),
40  m_country(country), m_isVa(virtualAirline), m_isOperating(operating)
41  {
42  if (m_designator.length() == 4) { this->setDesignator(m_designator); }
43  }
44 
46  {
47  if (!this->isVirtualAirline()) { return m_designator; }
48  return u'V' % m_designator;
49  }
50 
52  {
53  return this->isLoadedFromDb() ? this->getVDesignator() % this->getDbKeyAsStringInParentheses(" ") :
54  this->getVDesignator();
55  }
56 
57  void CAirlineIcaoCode::setDesignator(const QString &icaoDesignator)
58  {
59  m_designator = icaoDesignator.trimmed().toUpper();
60  if (m_designator.length() == 4 && m_designator.startsWith("V"))
61  {
62  // a virtual designator was provided
63  this->setVirtualAirline(true);
64  m_designator = m_designator.right(3);
65  }
66  }
67 
69  {
70  return (this->isLoadedFromDb()) ?
71  this->getDesignator() % QStringLiteral(" ") % this->getDbKeyAsStringInParentheses() :
72  this->getDesignator();
73  }
74 
76  {
77  return this->getDesignator() % (this->hasName() ? (u' ' % this->getName()) : QString()) %
78  (this->hasValidCountry() ? (u' ' % this->getCountryIso()) : QString());
79  }
80 
82 
83  bool CAirlineIcaoCode::hasValidCountry() const { return m_country.isValid(); }
84 
85  bool CAirlineIcaoCode::hasValidDesignator() const { return isValidAirlineDesignator(m_designator); }
86 
87  bool CAirlineIcaoCode::hasIataCode() const { return !m_iataCode.isEmpty(); }
88 
89  bool CAirlineIcaoCode::matchesDesignator(const QString &designator) const
90  {
91  if (designator.isEmpty() || m_designator.isEmpty()) { return false; }
92  return caseInsensitiveStringCompare(m_designator, designator.trimmed());
93  }
94 
95  bool CAirlineIcaoCode::matchesVDesignator(const QString &designator) const
96  {
97  if (designator.isEmpty() || m_designator.isEmpty()) { return false; }
98  return caseInsensitiveStringCompare(this->getVDesignator(), designator.trimmed());
99  }
100 
101  bool CAirlineIcaoCode::matchesIataCode(const QString &iata) const
102  {
103  if (iata.isEmpty() || m_iataCode.isEmpty()) { return false; }
104  return caseInsensitiveStringCompare(m_iataCode, iata.trimmed());
105  }
106 
107  bool CAirlineIcaoCode::matchesDesignatorOrIataCode(const QString &candidate) const
108  {
109  if (candidate.isEmpty()) { return false; }
110  return this->matchesDesignator(candidate) || this->matchesIataCode(candidate);
111  }
112 
113  bool CAirlineIcaoCode::matchesVDesignatorOrIataCode(const QString &candidate) const
114  {
115  if (candidate.isEmpty()) { return false; }
116  return this->matchesVDesignator(candidate) || this->matchesIataCode(candidate);
117  }
118 
119  bool CAirlineIcaoCode::matchesTelephonyDesignator(const QString &candidate) const
120  {
121  if (candidate.isEmpty() || m_telephonyDesignator.isEmpty()) { return false; }
122  return caseInsensitiveStringCompare(m_telephonyDesignator, candidate.trimmed());
123  }
124 
125  bool CAirlineIcaoCode::matchesNamesOrTelephonyDesignator(const QString &candidate) const
126  {
127  const QString cand(candidate.toUpper().trimmed());
128  if (this->getName().contains(cand, Qt::CaseInsensitive) ||
129  this->getTelephonyDesignator().contains(cand, Qt::CaseInsensitive))
130  {
131  return true;
132  }
133  return this->isContainedInSimplifiedName(candidate);
134  }
135 
136  bool CAirlineIcaoCode::isContainedInSimplifiedName(const QString &candidate) const
137  {
138  if (candidate.isEmpty() || !this->hasName()) { return false; }
139  auto simplifiedName =
140  makeRange(getName().begin(), getName().end()).findBy([](QChar c) { return c.isLetter(); });
141  auto it = std::search(simplifiedName.begin(), simplifiedName.end(), candidate.begin(), candidate.end(),
142  [](QChar a, QChar b) { return a.toUpper() == b.toUpper(); });
143  return it != simplifiedName.end();
144  }
145 
146  bool CAirlineIcaoCode::hasSimplifiedName() const { return this->hasName() && !this->getSimplifiedName().isEmpty(); }
147 
149  {
150  return this->hasValidDesignator() && this->hasValidCountry() && this->hasName();
151  }
152 
154  {
155  // if (this->hasValidDbKey() && CAirlineIcaoCode::iconIds().contains(this->getDbKey()))
156  //{
157  // static const QString p("airlines/%1_%2.png");
158  // const QString n(p.arg(this->getDbKey(), 5, 10, QChar('0')).arg(this->getDesignator()));
159  // return CIcon(n, this->convertToQString());
160  // }
161  return CIcons::StandardIconEmpty;
162  }
163 
164  QString CAirlineIcaoCode::convertToQString(bool i18n) const
165  {
166  Q_UNUSED(i18n);
167  const QString s = this->getDesignatorDbKey() % (this->hasName() ? u' ' % m_name : QString()) % u" Op: " %
168  boolToYesNo(this->isOperating()) % u" VA: " % boolToYesNo(this->isVirtualAirline()) %
169  u" Mil: " % boolToYesNo(this->isMilitary());
170  return s.trimmed();
171  }
172 
174  {
175  if (index.isMyself()) { return QVariant::fromValue(*this); }
176  if (IDatastoreObjectWithIntegerKey::canHandleIndex(index))
177  {
178  return IDatastoreObjectWithIntegerKey::propertyByIndex(index);
179  }
180  const ColumnIndex i = index.frontCasted<ColumnIndex>();
181  switch (i)
182  {
183  case IndexAirlineDesignator: return QVariant::fromValue(m_designator);
184  case IndexIataCode: return QVariant::fromValue(m_iataCode);
185  case IndexAirlineCountryIso: return QVariant::fromValue(this->getCountryIso());
186  case IndexAirlineCountry: return m_country.propertyByIndex(index.copyFrontRemoved());
187  case IndexAirlineName: return QVariant::fromValue(m_name);
188  case IndexTelephonyDesignator: return QVariant::fromValue(m_telephonyDesignator);
189  case IndexIsVirtualAirline: return QVariant::fromValue(m_isVa);
190  case IndexIsOperating: return QVariant::fromValue(m_isOperating);
191  case IndexIsMilitary: return QVariant::fromValue(m_isMilitary);
192  case IndexDesignatorNameCountry: return QVariant::fromValue(this->getDesignatorNameCountry());
193  case IndexGroupDesignator: return QVariant::fromValue(this->getGroupDesignator());
194  case IndexGroupName: return QVariant::fromValue(this->getGroupName());
195  case IndexGroupId: return QVariant::fromValue(this->getGroupId());
196  default: return CValueObject::propertyByIndex(index);
197  }
198  }
199 
200  void CAirlineIcaoCode::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
201  {
202  if (index.isMyself())
203  {
204  (*this) = variant.value<CAirlineIcaoCode>();
205  return;
206  }
207  if (IDatastoreObjectWithIntegerKey::canHandleIndex(index))
208  {
209  IDatastoreObjectWithIntegerKey::setPropertyByIndex(index, variant);
210  return;
211  }
212  const ColumnIndex i = index.frontCasted<ColumnIndex>();
213  switch (i)
214  {
215  case IndexAirlineDesignator: this->setDesignator(variant.value<QString>()); break;
216  case IndexIataCode: this->setIataCode(variant.value<QString>()); break;
217  case IndexAirlineCountry: this->setCountry(variant.value<CCountry>()); break;
218  case IndexAirlineName: this->setName(variant.value<QString>()); break;
219  case IndexTelephonyDesignator: this->setTelephonyDesignator(variant.value<QString>()); break;
220  case IndexIsVirtualAirline: this->setVirtualAirline(variant.toBool()); break;
221  case IndexIsOperating: this->setOperating(variant.toBool()); break;
222  case IndexIsMilitary: this->setMilitary(variant.toBool()); break;
223  case IndexGroupDesignator: this->setGroupDesignator(variant.toString()); break;
224  case IndexGroupName: this->setGroupName(variant.toString()); break;
225  case IndexGroupId: this->setGroupId(variant.toInt()); break;
226  default: CValueObject::setPropertyByIndex(index, variant); break;
227  }
228  }
229 
231  {
232  if (index.isMyself()) { return m_designator.compare(compareValue.getDesignator(), Qt::CaseInsensitive); }
233  if (IDatastoreObjectWithIntegerKey::canHandleIndex(index))
234  {
235  return IDatastoreObjectWithIntegerKey::comparePropertyByIndex(index, compareValue);
236  }
237  const ColumnIndex i = index.frontCasted<ColumnIndex>();
238  switch (i)
239  {
240  case IndexAirlineDesignator: return m_designator.compare(compareValue.getDesignator());
241  case IndexIataCode: return m_iataCode.compare(compareValue.getIataCode());
242  case IndexAirlineCountry:
243  return m_country.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCountry());
244  case IndexDesignatorNameCountry:
245  return m_country.getName().compare(compareValue.getCountry().getName(), Qt::CaseInsensitive);
246  case IndexAirlineName: return m_name.compare(compareValue.getName(), Qt::CaseInsensitive);
247  case IndexTelephonyDesignator:
248  return m_telephonyDesignator.compare(compareValue.getTelephonyDesignator(), Qt::CaseInsensitive);
249  case IndexIsVirtualAirline: return Compare::compare(this->isVirtualAirline(), compareValue.isVirtualAirline());
250  case IndexIsOperating: return Compare::compare(this->isOperating(), compareValue.isOperating());
251  case IndexIsMilitary: return Compare::compare(this->isMilitary(), compareValue.isMilitary());
252  case IndexGroupDesignator:
253  return m_groupDesignator.compare(compareValue.getGroupDesignator(), Qt::CaseInsensitive);
254  case IndexGroupName: return m_groupName.compare(compareValue.getGroupName(), Qt::CaseInsensitive);
255  case IndexGroupId: return Compare::compare(m_groupId, compareValue.getGroupId());
256  default: break;
257  }
258  Q_ASSERT_X(false, Q_FUNC_INFO, "No compare function");
259  return 0;
260  }
261 
263  {
264  static const CLogCategoryList cats(CLogCategoryList(this).withValidation());
265  CStatusMessageList msgs;
266  if (!hasValidDesignator())
267  {
268  msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, u"Airline: missing designator"));
269  }
270  if (!hasValidCountry())
271  {
272  msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, u"Airline: missing country"));
273  }
274  if (!hasName()) { msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, u"Airline: no name")); }
275  return msgs;
276  }
277 
278  bool CAirlineIcaoCode::isValidAirlineDesignator(const QString &airline)
279  {
280  // allow 2 chars for special codes like "VV"
281  if (airline.length() < 2 || airline.length() > 5) { return false; }
282  const auto chars = makeRange(airline.begin(), airline.end());
283  if (chars.containsBy([](QChar c) { return !c.isUpper() && !c.isDigit(); })) { return false; }
284  return true;
285  }
286 
287  bool CAirlineIcaoCode::isValidIataCode(const QString &iataCode)
288  {
289  if (iataCode.length() != 2) { return false; }
290  return isValidAirlineDesignator(iataCode); // allow some chars as in IACO
291  }
292 
294  {
295  static const QSet<QString> valid({ "VV", "VM" });
296  return valid;
297  }
298 
299  QString CAirlineIcaoCode::normalizeDesignator(const QString &candidate)
300  {
301  QString n(candidate.trimmed().toUpper());
302  n = n.left(indexOfChar(n, [](QChar c) { return c.isSpace(); }));
303  return removeChars(n, [](QChar c) { return !c.isLetterOrNumber(); });
304  }
305 
306  CStatusMessage CAirlineIcaoCode::logMessage(const CAirlineIcaoCode &icaoCode, const QString &message,
307  const QStringList &extraCategories, CStatusMessage::StatusSeverity s)
308  {
309  static const CLogCategoryList cats({ CLogCategories::aviation() });
310  const CStatusMessage m(cats.with(CLogCategoryList::fromQStringList(extraCategories)), s,
311  icaoCode.hasValidDesignator() ?
312  icaoCode.getVDesignatorDbKey() + ": " + message.trimmed() :
313  message.trimmed());
314  return m;
315  }
316 
318  const QString &message, const QStringList &extraCategories,
320  {
321  if (!log) { return; }
322  if (message.isEmpty()) { return; }
323  log->push_back(logMessage(icao, message, extraCategories, s));
324  }
325 
327  {
328  return (this->hasValidDesignator() ? this->getVDesignator() : QString()) %
329  (this->hasName() ? u' ' % m_name : QString()) % this->getDbKeyAsStringInParentheses(" ");
330  }
331 
333  {
334  if (this->hasValidDbKey()) { return *this; }
335  if (callsign.isEmpty()) { return *this; }
336  const QString callsignAirline = callsign.getAirlinePrefix();
337  if (callsignAirline.isEmpty()) { return *this; }
338  if (callsignAirline == m_designator) { return *this; }
339 
340  const CAirlineIcaoCode callsignIcao(callsignAirline);
341  if (m_designator.isEmpty()) { return callsignIcao; }
342 
343  // here we have 2 possible codes
344  if (callsignIcao.isVirtualAirline())
345  {
346 
347  if (callsignIcao.getDesignator().endsWith(m_designator))
348  {
349  // callsign ICAO is virtual airline of myself, this is more accurate
350  return callsignIcao;
351  }
352  }
353  return *this;
354  }
355 
357  {
358  if (!this->hasValidDbKey()) { return this->getName(); }
359  return this->hasName() ? QString(this->getName()).append(" ").append(this->getDbKeyAsStringInParentheses()) :
361  }
362 
364  {
365  if (!this->hasValidDbKey() && otherIcaoCode.hasValidDbKey())
366  {
367  // we have no DB data, but the other one has
368  // so we change roles. We take the DB object as base, and update our parts
369  CAirlineIcaoCode copy(otherIcaoCode);
370  copy.updateMissingParts(*this);
371  *this = copy;
372  return;
373  }
374 
375  if (!this->hasValidDesignator()) { this->setDesignator(otherIcaoCode.getDesignator()); }
376  if (!this->hasValidCountry()) { this->setCountry(otherIcaoCode.getCountry()); }
377  if (!this->hasName()) { this->setName(otherIcaoCode.getName()); }
378  if (!this->hasTelephonyDesignator()) { this->setTelephonyDesignator(otherIcaoCode.getTelephonyDesignator()); }
379  if (!this->hasValidDbKey())
380  {
381  this->setDbKey(otherIcaoCode.getDbKey());
382  this->setUtcTimestamp(otherIcaoCode.getUtcTimestamp());
383  }
384  }
385 
386  QString CAirlineIcaoCode::asHtmlSummary() const { return this->getCombinedStringWithKey(); }
387 
389  {
390  if (this->isDbEqual(otherCode))
391  {
392  addLogDetailsToList(log, *this, QStringLiteral("DB equal score: 100"));
393  return 100;
394  }
395  const bool bothFromDb = this->isLoadedFromDb() && otherCode.isLoadedFromDb();
396  int score = 0;
397  if (otherCode.hasValidDesignator() && this->getDesignator() == otherCode.getDesignator())
398  {
399  score += 60;
400  addLogDetailsToList(log, *this, QStringLiteral("Same designator: %1").arg(score));
401  }
402 
403  // only for DB values we check VA
404  if (bothFromDb && this->isVirtualAirline() == otherCode.isVirtualAirline())
405  {
406  score += 20;
407  addLogDetailsToList(log, *this, QStringLiteral("VA equality: %1").arg(score));
408  }
409 
410  // consider the various names
411  if (this->hasName() && this->getName() == otherCode.getName())
412  {
413  score += 20;
414  addLogDetailsToList(log, *this, QStringLiteral("Same name '%1': %2").arg(this->getName()).arg(score));
415  }
416  else if (this->hasTelephonyDesignator() && this->getTelephonyDesignator() == otherCode.getTelephonyDesignator())
417  {
418  score += 15;
420  log, *this, QStringLiteral("Same telephony '%1': %2").arg(this->getTelephonyDesignator()).arg(score));
421  }
422  else if (this->hasSimplifiedName() && this->getSimplifiedName() == otherCode.getSimplifiedName())
423  {
424  score += 10;
426  log, *this, QStringLiteral("Same simplified name '%1': %2").arg(this->getSimplifiedName()).arg(score));
427  }
428  return score;
429  }
430 
432  {
433  return m_designator.isNull() && m_iataCode.isNull() && m_telephonyDesignator.isNull();
434  }
435 
437  {
438  static const CAirlineIcaoCode null;
439  return null;
440  }
441 
442  CAirlineIcaoCode CAirlineIcaoCode::fromDatabaseJson(const QJsonObject &json, const QString &prefix)
443  {
444  if (!existsKey(json, prefix))
445  {
446  // when using relationship, this can be null (e.g. for color liveries)
447  return CAirlineIcaoCode();
448  }
449 
450  QString designator(json.value(prefix % u"designator").toString());
452  {
453  designator = CAirlineIcaoCode::normalizeDesignator(designator);
454  }
455 
456  const QString iata(json.value(prefix % u"iata").toString());
457  const QString telephony(json.value(prefix % u"callsign").toString());
458  const QString name(json.value(prefix % u"name").toString());
459  const QString countryIso(json.value(prefix % u"country").toString());
460  const QString countryName(json.value(prefix % u"countryname").toString());
461  const QString groupName(json.value(prefix % u"groupname").toString());
462  const QString groupDesignator(json.value(prefix % u"groupdesignator").toString());
463  const int groupId(json.value(prefix % u"groupid").toInt(-1));
464  const bool va = CDatastoreUtility::dbBoolStringToBool(json.value(prefix % u"va").toString());
465  const bool operating = CDatastoreUtility::dbBoolStringToBool(json.value(prefix % u"operating").toString());
466  const bool military = CDatastoreUtility::dbBoolStringToBool(json.value(prefix % u"military").toString());
467 
468  CAirlineIcaoCode code(designator, name, CCountry(countryIso, countryName), telephony, va, operating);
469  code.setIataCode(iata);
470  code.setMilitary(military);
471  code.setGroupDesignator(groupDesignator);
472  code.setGroupId(groupId);
473  code.setGroupName(groupName);
474  code.setKeyVersionTimestampFromDatabaseJson(json, prefix);
475  return code;
476  }
477 } // namespace swift::misc::aviation
const QString & getName() const
Country name.
Definition: country.h:73
bool isValid() const
Valid?
Definition: country.cpp:98
int comparePropertyByIndex(CPropertyIndexRef index, const CCountry &compareValue) const
Compare for index.
Definition: country.cpp:150
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
Definition: country.cpp:106
IconIndex
Index for each icon, allows to send them via DBus, efficiently store them, etc.
Definition: icons.h:32
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.
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.
Status messages, e.g. from Core -> GUI.
QDateTime getUtcTimestamp() const
Get timestamp.
void setUtcTimestamp(const QDateTime &timestamp)
Set timestamp.
Value object for ICAO classification.
const QString & getGroupDesignator() const
Group designator.
QString getCombinedStringWithKey() const
Comined string with key.
void setMilitary(bool military)
Military, air force or such?
bool isVirtualAirline() const
Virtual airline.
static bool isValidAirlineDesignator(const QString &airline)
Valid designator?
static QSet< QString > specialValidDesignators()
Some special valid designator which do not fit standard rule (e.g. 3-letter code)
void setTelephonyDesignator(const QString &telephony)
Telephony designator such as "Speedbird".
void setOperating(bool operating)
Operating airline?
CAirlineIcaoCode()=default
Default constructor.
const QString & getCountryIso() const
Get country, e.g. "FR".
const QString & getIataCode() const
IATA code.
bool isContainedInSimplifiedName(const QString &candidate) const
Does simplified name contain the candidate.
QString getVDesignatorDbKey() const
Get VDesignator plus key.
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
bool matchesDesignator(const QString &designator) const
Matches designator string?
bool isMilitary() const
Military, air force or such?
static const CAirlineIcaoCode & null()
NULL object.
QString getSimplifiedName() const
Get a simplified upper case name for searching by removing all characters except A-Z.
const QString & getTelephonyDesignator() const
Telephony designator such as "Speedbird".
QString getDesignatorDbKey() const
Designator and DB key.
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
QString convertToQString(bool i18n=false) const
Cast as QString.
void setVirtualAirline(bool va)
Virtual airline.
const QString & getDesignator() const
Get airline, e.g. "DLH".
CStatusMessageList validate() const
Validate data.
static QString normalizeDesignator(const QString &candidate)
Normalize string as airline designator.
bool hasTelephonyDesignator() const
Telephony designator?
void setIataCode(const QString &iataCode)
Set IATA code.
bool hasCompleteData() const
Complete 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.
void setName(const QString &name)
Set name.
bool matchesTelephonyDesignator(const QString &candidate) const
Matches telephony designator (aka callsign, not to be confused with CCallsign)
void setCountry(const CCountry &country)
Set country.
QString asHtmlSummary() const
As a brief HTML summary (e.g. used in tooltips)
bool matchesVDesignator(const QString &designator) const
Matches v-designator string?
CIcons::IconIndex toIcon() const
As icon, not implemented by all classes.
void setGroupDesignator(const QString &designator)
Group designator.
int calculateScore(const CAirlineIcaoCode &otherCode, CStatusMessageList *log=nullptr) const
Score against other code 0..100.
static bool isValidIataCode(const QString &iataCode)
Valid IATA code?
bool matchesNamesOrTelephonyDesignator(const QString &candidate) const
Relaxed check by name or telephony designator (aka callsign, not to be confused with CCallsign)
bool matchesVDesignatorOrIataCode(const QString &candidate) const
Matches IATA code or v-designator?
bool matchesDesignatorOrIataCode(const QString &candidate) const
Matches IATA code or designator?
void setDesignator(const QString &icaoDesignator)
Set airline, e.g. "DLH".
const QString & getGroupName() const
Group name.
const CCountry & getCountry() const
Get country, e.g. "FRANCE".
bool matchesIataCode(const QString &iata) const
Matches IATA code?
static CStatusMessage logMessage(const CAirlineIcaoCode &icaoCode, const QString &message, const QStringList &extraCategories={}, CStatusMessage::StatusSeverity s=CStatusMessage::SeverityInfo)
Specialized log message for matching / reverse lookup.
static void addLogDetailsToList(CStatusMessageList *log, const CAirlineIcaoCode &icao, const QString &message, const QStringList &extraCategories={}, CStatusMessage::StatusSeverity s=CStatusMessage::SeverityInfo)
Specialized log for matching / reverse lookup.
int comparePropertyByIndex(CPropertyIndexRef index, const CAirlineIcaoCode &compareValue) const
Compare for index.
void setGroupName(const QString &name)
Group name.
QString getDesignatorNameCountry() const
Combined string designator, name, country.
QString getVDesignator() const
Get airline, e.g. "DLH", but "VMVA" for virtual airlines.
const QString & getName() const
Get name, e.g. "Lufthansa".
CAirlineIcaoCode thisOrCallsignCode(const CCallsign &callsign) const
What is better, the callsign airline code or this code. Return the better one.
QString getNameWithKey() const
Name plus key, e.g. "Lufthansa (3421)".
bool hasSimplifiedName() const
Has simplified airline name?
bool hasName() const
Has (airline) name?
Value object encapsulating information of a callsign.
Definition: callsign.h:30
bool isEmpty() const
Is empty?
Definition: callsign.h:63
QString getAirlinePrefix() const
Airline suffix (e.g. DLH1234 -> DLH) if applicable.
Definition: callsign.cpp:219
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
Free functions in swift::misc.
SWIFT_MISC_EXPORT QString simplifyNameForSearch(const QString &name)
Get a simplified upper case name for searching by removing all characters except A-Z.
T::const_iterator begin(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
Definition: lockfree.h:332
QString removeChars(const QString &s, F predicate)
Return a string with characters removed that match the given predicate.
Definition: stringutils.h:35
auto makeRange(I begin, I2 end) -> CRange< I >
Returns a CRange constructed from begin and end iterators of deduced types.
Definition: range.h:316
SWIFT_MISC_EXPORT bool caseInsensitiveStringCompare(const QString &c1, const QString &c2)
Case insensitive string compare.
int indexOfChar(const QString &s, F predicate)
Index of first character in the string matching the given predicate, or -1 if not found.
Definition: stringutils.h:78
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
Definition: lockfree.h:338
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