swift
countrylist.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/countrylist.h"
5 
6 #include <QJsonValue>
7 #include <QRegularExpression>
8 #include <Qt>
9 
10 SWIFT_DEFINE_SEQUENCE_MIXINS(swift::misc, CCountry, CCountryList)
11 
12 namespace swift::misc
13 {
15 
17 
18  CCountry CCountryList::findByIsoCode(const QString &isoCode) const
19  {
20  const QString iso(isoCode.trimmed().toUpper());
21  if (!CCountry::isValidIsoCode(iso)) { return CCountry(); }
22  return IDatastoreObjectList::findByKey(isoCode);
23  }
24 
25  CCountry CCountryList::findBestMatchByCountryName(const QString &candidate) const
26  {
27  if (candidate.isEmpty()) { return CCountry(); }
28 
29  thread_local const QRegularExpression reg("^[a-z]+", QRegularExpression::CaseInsensitiveOption);
30  const QRegularExpressionMatch match = reg.match(candidate);
31  const QString cn(match.hasMatch() ? match.captured(0) : candidate);
32  const CCountryList countries =
33  this->findBy([&](const CCountry &country) { return country.matchesCountryName(cn); });
34 
35  if (countries.isEmpty()) { return this->findFirstByAlias(cn); }
36  if (countries.size() < 2) { return countries.frontOrDefault(); }
37 
38  // find best match by further reducing
39  for (const CCountry &c : countries)
40  {
41  if (c.getName() == cn) { return c; }
42  if (c.getName().startsWith(cn, Qt::CaseInsensitive)) { return c; }
43  if (cn.startsWith(c.getName(), Qt::CaseInsensitive)) { return c; }
44  }
45  return countries.front();
46  }
47 
48  CCountry CCountryList::findFirstByAlias(const QString &alias) const
49  {
50  if (alias.isEmpty()) { return CCountry(); }
51  const QString a(alias.toUpper().trimmed());
52  for (const CCountry &country : (*this))
53  {
54  if (country.matchesAlias(a)) { return country; }
55  }
56  return CCountry();
57  }
58 
59  QStringList CCountryList::toIsoNameList(bool sorted) const
60  {
61  QStringList sl;
62  for (const CCountry &country : (*this))
63  {
64  const QString s = country.getCombinedStringIsoName();
65  if (s.isEmpty()) { continue; }
66  sl.append(s);
67  }
68  if (sorted) { sl.sort(); }
69  return sl;
70  }
71 
72  QStringList CCountryList::toNameIsoList(bool sorted) const
73  {
74  QStringList sl;
75  for (const CCountry &country : (*this))
76  {
77  const QString s = country.getCombinedStringNameIso();
78  if (s.isEmpty()) { continue; }
79  sl.append(s);
80  }
81  if (sorted) { sl.sort(); }
82  return sl;
83  }
84 
85  QStringList CCountryList::toNameList(bool sorted) const
86  {
87  QStringList sl;
88  for (const CCountry &country : (*this))
89  {
90  const QString s = country.getName();
91  if (s.isEmpty()) { continue; }
92  sl.append(s);
93  }
94  if (sorted) { sl.sort(); }
95  return sl;
96  }
97 
98  QStringList CCountryList::toIsoList(bool sorted) const
99  {
100  QStringList sl;
101  for (const CCountry &country : (*this))
102  {
103  const QString s = country.getIsoCode();
104  if (s.length() != 2) { continue; }
105  sl.append(s);
106  }
107  if (sorted) { sl.sort(); }
108  return sl;
109  }
110 
111  QStringList CCountryList::toIso3List(bool sorted) const
112  {
113  QStringList sl;
114  for (const CCountry &country : (*this))
115  {
116  const QString s = country.getIso3Code();
117  if (s.length() != 3) { continue; }
118  sl.append(s);
119  }
120  if (sorted) { sl.sort(); }
121  return sl;
122  }
123 
125  {
126  CCountryList countries;
127  for (const QJsonValue &value : array)
128  {
129  CCountry country(CCountry::fromDatabaseJson(value.toObject()));
130  countries.push_back(country);
131  }
132  return countries;
133  }
134 } // namespace swift::misc
bool matchesCountryName(const QString &name) const
Matches country name.
Definition: country.cpp:77
static bool isValidIsoCode(const QString &isoCode)
Valid country iso code.
Definition: country.cpp:193
static CCountry fromDatabaseJson(const QJsonObject &json, const QString &prefix=QString())
From our database JSON format.
Definition: country.cpp:170
Value object encapsulating a list of countries.
Definition: countrylist.h:32
static CCountryList fromDatabaseJson(const QJsonArray &array)
From our database JSON format.
CCountry findFirstByAlias(const QString &alias) const
Find first by alias.
Definition: countrylist.cpp:48
CCountry findBestMatchByCountryName(const QString &candidate) const
Find "best match" by country.
Definition: countrylist.cpp:25
QStringList toIso3List(bool sorted=false) const
All ISO 3 codes.
CCountry findByIsoCode(const QString &isoCode) const
Find by ISO code.
Definition: countrylist.cpp:18
QStringList toIsoNameList(bool sorted=false) const
ISO/name string list.
Definition: countrylist.cpp:59
CCountryList()
Default constructor.
Definition: countrylist.cpp:14
QStringList toNameList(bool sorted=false) const
Name string list.
Definition: countrylist.cpp:85
QStringList toIsoList(bool sorted=false) const
All ISO codes.
Definition: countrylist.cpp:98
QStringList toNameIsoList(bool sorted=false) const
Name/ISO string list.
Definition: countrylist.cpp:72
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
const_reference frontOrDefault() const
Access the first element, or a default-initialized value if the sequence is empty.
Definition: sequence.h:239
CSequence findBy(Predicate p) const
Return a copy containing only those elements for which a given predicate returns true.
Definition: sequence.h:398
Q_REQUIRED_RESULT CSequence sorted(Predicate p) const
Return a copy sorted by a given comparator predicate.
Definition: sequence.h:583
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition: sequence.h:305
reference front()
Access the first element.
Definition: sequence.h:225
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Free functions in swift::misc.
#define SWIFT_DEFINE_SEQUENCE_MIXINS(Namespace, T, List)
Explicit template definition of mixins for a CSequence subclass.
Definition: sequence.h:63