swift
country.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/country.h"
5 
6 #include <QJsonValue>
7 #include <QStringBuilder>
8 #include <Qt>
9 #include <QtGlobal>
10 
11 #include "misc/icons.h"
12 #include "misc/stringutils.h"
13 
15 
16 namespace swift::misc
17 {
18  CCountry::CCountry(const QString &iso, const QString &name)
19  : IDatastoreObjectWithStringKey(iso.trimmed().toUpper()), m_name(name.trimmed())
20  {
21  this->setSimplifiedNameIfNotSame();
22  }
23 
25  {
26  // if (m_dbKey.length() == 2)
27  //{
28  // // relative to images
29  // return CIcon(u"flags/" % m_dbKey.toLower() % u".png", this->convertToQString());
30  // }
31  // else
32  {
33  return CIcons::StandardIconEmpty;
34  }
35  }
36 
37  void CCountry::setIsoCode(const QString &iso)
38  {
39  const QString code(iso.trimmed().toUpper());
40  m_dbKey = (code.length() == 2) ? code : "";
41  }
42 
43  void CCountry::setIso3Code(const QString &iso)
44  {
45  const QString code(iso.trimmed().toUpper());
46  m_iso3 = (code.length() == 3) ? code : "";
47  }
48 
49  bool CCountry::hasIsoCode() const { return m_dbKey.length() == 2; }
50 
51  bool CCountry::hasIso3Code() const { return m_iso3.length() == 3; }
52 
53  void CCountry::setAlias1(const QString &alias) { m_alias1 = alias.trimmed().toUpper(); }
54 
55  void CCountry::setAlias2(const QString &alias) { m_alias2 = alias.trimmed().toUpper(); }
56 
58  {
59  if (!this->hasIsoCode()) { return QString(); }
60  QString s(m_dbKey);
61  if (m_name.isEmpty()) { return s; }
62  return u" (" % m_name % u')';
63  }
64 
66  {
67  if (!this->isValid()) { return QString(); }
68  return m_name % u" - " % m_dbKey;
69  }
70 
71  void CCountry::setName(const QString &countryName)
72  {
73  m_name = countryName.trimmed();
74  this->setSimplifiedNameIfNotSame();
75  }
76 
77  bool CCountry::matchesCountryName(const QString &name) const
78  {
79  if (name.isEmpty() || m_name.isEmpty()) { return false; }
80  if (caseInsensitiveStringCompare(name, this->getDbKey())) { return true; } // exact ISO match
81  if (caseInsensitiveStringCompare(name, this->getIso3Code())) { return true; } // exact ISO3 match
82  if (name.length() < 5)
83  {
84  // contains would be too fuzzy for short names
85  return caseInsensitiveStringCompare(name, m_name) || caseInsensitiveStringCompare(name, m_simplifiedName);
86  }
87  else
88  {
89  return m_name.contains(name, Qt::CaseInsensitive) || m_simplifiedName.contains(name, Qt::CaseInsensitive);
90  }
91  }
92 
93  bool CCountry::matchesAlias(const QString &alias) const
94  {
95  return caseInsensitiveStringCompare(alias, m_alias1) || caseInsensitiveStringCompare(alias, m_alias2);
96  }
97 
98  bool CCountry::isValid() const { return m_dbKey.length() == 2 && !m_name.isEmpty(); }
99 
100  QString CCountry::convertToQString(bool i18n) const
101  {
102  Q_UNUSED(i18n);
103  return this->getCombinedStringIsoName();
104  }
105 
107  {
108  if (index.isMyself()) { return QVariant::fromValue(*this); }
109  ColumnIndex i = index.frontCasted<ColumnIndex>();
110  switch (i)
111  {
112  case IndexIsoCode: return QVariant::fromValue(m_dbKey);
113  case IndexIso3Code: return QVariant::fromValue(getIso3Code());
114  case IndexName: return QVariant::fromValue(m_name);
115  case IndexIsoName: return QVariant::fromValue(getCombinedStringIsoName());
116  case IndexAlias1: return QVariant::fromValue(this->getAlias1());
117  case IndexAlias2: return QVariant::fromValue(this->getAlias2());
118  case IndexHistoric: return QVariant::fromValue(this->isHistoric());
119  default:
120  return (IDatastoreObjectWithStringKey::canHandleIndex(index)) ?
121  IDatastoreObjectWithStringKey::propertyByIndex(index) :
123  }
124  }
125 
126  void CCountry::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
127  {
128  if (index.isMyself())
129  {
130  (*this) = variant.value<CCountry>();
131  return;
132  }
133  const ColumnIndex i = index.frontCasted<ColumnIndex>();
134  switch (i)
135  {
136  case IndexIsoCode: this->setIsoCode(variant.toString()); break;
137  case IndexIso3Code: this->setIso3Code(variant.toString()); break;
138  case IndexName: this->setName(variant.toString()); break;
139  case IndexAlias1: this->setAlias1(variant.toString()); break;
140  case IndexAlias2: this->setAlias1(variant.toString()); break;
141  case IndexHistoric: this->setHistoric(variant.toBool()); break;
142  default:
143  IDatastoreObjectWithStringKey::canHandleIndex(index) ?
144  IDatastoreObjectWithStringKey::setPropertyByIndex(index, variant) :
145  CValueObject::setPropertyByIndex(index, variant);
146  break;
147  }
148  }
149 
150  int CCountry::comparePropertyByIndex(CPropertyIndexRef index, const CCountry &compareValue) const
151  {
152  if (index.isMyself()) { return getIsoCode().compare(compareValue.getIsoCode(), Qt::CaseInsensitive); }
153  if (IDatastoreObjectWithStringKey::canHandleIndex(index))
154  {
155  return IDatastoreObjectWithStringKey::comparePropertyByIndex(index, compareValue);
156  }
157  const ColumnIndex i = index.frontCasted<ColumnIndex>();
158  switch (i)
159  {
160  case IndexIsoCode: return getIsoCode().compare(compareValue.getIsoCode(), Qt::CaseInsensitive);
161  case IndexIso3Code: return getIso3Code().compare(compareValue.getIsoCode(), Qt::CaseInsensitive);
162  case IndexName: return getName().compare(compareValue.getName(), Qt::CaseInsensitive);
163  case IndexAlias1: return this->getAlias1().compare(compareValue.getAlias1(), Qt::CaseInsensitive);
164  case IndexAlias2: return this->getAlias2().compare(compareValue.getAlias2(), Qt::CaseInsensitive);
165  default: break;
166  }
167  return CValueObject::comparePropertyByIndex(index, compareValue);
168  }
169 
170  CCountry CCountry::fromDatabaseJson(const QJsonObject &json, const QString &prefix)
171  {
172  if (!existsKey(json, prefix))
173  {
174  // when using relationship, this can be null
175  return CCountry();
176  }
177  const QString iso(json.value(prefix % u"id").toString());
178  const QString name(json.value(prefix % u"country").toString());
179  const QString alias1(json.value(prefix % u"alias1").toString());
180  const QString alias2(json.value(prefix % u"alias2").toString());
181  const QString iso3(json.value(prefix % u"iso3").toString());
182  const QString historic(json.value(prefix % u"historic").toString());
183  CCountry country(iso, name);
184  country.setLoadedFromDb(true);
185  country.setAlias1(alias1);
186  country.setAlias2(alias2);
187  country.setIso3Code(iso3);
188  country.setHistoric(stringToBool(historic));
189  country.setKeyVersionTimestampFromDatabaseJson(json, prefix);
190  return country;
191  }
192 
193  bool CCountry::isValidIsoCode(const QString &isoCode) { return isoCode.length() == 2; }
194 
195  void CCountry::setSimplifiedNameIfNotSame()
196  {
197  const QString simplified = simplifyAccents(m_name);
198  m_simplifiedName = m_name == simplified ? "" : simplified;
199  }
200 } // namespace swift::misc
QString getCombinedStringIsoName() const
Combined string ISO/name.
Definition: country.cpp:57
const QString & getName() const
Country name.
Definition: country.h:73
const QString & getIso3Code() const
Get 3 letter iso code.
Definition: country.h:58
CCountry()=default
Constructor.
const QString & getAlias1() const
Alias 1.
Definition: country.h:79
bool isValid() const
Valid?
Definition: country.cpp:98
bool hasIso3Code() const
ISO 3 letter code?
Definition: country.cpp:51
bool hasIsoCode() const
ISO code?
Definition: country.cpp:49
bool matchesCountryName(const QString &name) const
Matches country name.
Definition: country.cpp:77
int comparePropertyByIndex(CPropertyIndexRef index, const CCountry &compareValue) const
Compare for index.
Definition: country.cpp:150
void setName(const QString &countryName)
Set country name.
Definition: country.cpp:71
void setIsoCode(const QString &iso)
Country ISO code (US, DE, GB, PL)
Definition: country.cpp:37
const QString & getIsoCode() const
DB ISO code.
Definition: country.h:55
void setIso3Code(const QString &iso)
Country ISO code (USA, DEU, GBR, POL)
Definition: country.cpp:43
static bool isValidIsoCode(const QString &isoCode)
Valid country iso code.
Definition: country.cpp:193
QString getCombinedStringNameIso() const
Combined string name/ISO.
Definition: country.cpp:65
bool matchesAlias(const QString &alias) const
Matches alias.
Definition: country.cpp:93
CIcons::IconIndex toIcon() const
Representing icon.
Definition: country.cpp:24
QString convertToQString(bool i18n=false) const
Cast as QString.
Definition: country.cpp:100
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
Definition: country.cpp:106
void setAlias1(const QString &alias)
Alias 1.
Definition: country.cpp:53
ColumnIndex
Properties by index.
Definition: country.h:31
bool isHistoric() const
Historic / non-existing country (e.g. Soviet Union)
Definition: country.h:91
const QString & getAlias2() const
Alias 2.
Definition: country.h:85
static CCountry fromDatabaseJson(const QJsonObject &json, const QString &prefix=QString())
From our database JSON format.
Definition: country.cpp:170
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
Definition: country.cpp:126
void setAlias2(const QString &alias)
Alias 2.
Definition: country.cpp:55
void setHistoric(bool historic)
Historic country?
Definition: country.h:94
IconIndex
Index for each icon, allows to send them via DBus, efficiently store them, etc.
Definition: icons.h:32
Non-owning reference to a CPropertyIndex with a subset of its features.
CastType frontCasted() const
First element casted to given type, usually the PropertIndex enum.
bool isMyself() const
Myself index, used with nesting.
void setLoadedFromDb(bool loaded)
Mark as loaded from DB.
Definition: datastore.h:207
static bool existsKey(const QJsonObject &json, const QString &prefix=QString())
Is a key available?
Definition: datastore.cpp:188
const QString & getDbKey() const
Get DB key.
Definition: datastore.h:180
void setKeyVersionTimestampFromDatabaseJson(const QJsonObject &json, const QString &prefix=QString())
Set key and timestamp values.
Definition: datastore.cpp:180
int comparePropertyByIndex(CPropertyIndexRef index, const Derived &compareValue) const
Compare for index.
Definition: mixinindex.h:187
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 bool caseInsensitiveStringCompare(const QString &c1, const QString &c2)
Case insensitive string compare.
SWIFT_MISC_EXPORT QString simplifyAccents(const QString &candidate)
Remove accents / diacritic marks from a string.
SWIFT_MISC_EXPORT bool stringToBool(const QString &boolString)
Convert string to bool.
#define SWIFT_DEFINE_VALUEOBJECT_MIXINS(Namespace, Class)
Explicit template definition of mixins for a CValueObject subclass.
Definition: valueobject.h:67