swift
distributor.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 
5 
6 #include <QJsonValue>
7 #include <QStringBuilder>
8 #include <Qt>
9 #include <QtGlobal>
10 
11 #include "misc/logcategories.h"
12 #include "misc/statusmessage.h"
13 #include "misc/stringutils.h"
14 
15 SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::simulation, CDistributor)
16 
17 namespace swift::misc::simulation
18 {
20 
21  CDistributor::CDistributor(const QString &key) { this->setDbKey(unifyKeyOrAlias(key)); }
22 
23  CDistributor::CDistributor(const QString &id, const QString &description, const QString &alias1,
24  const QString &alias2, const CSimulatorInfo &simulator)
25  : m_description(description), m_alias1(alias1), m_alias2(alias2), m_simulator(simulator)
26  {
27  this->setDbKey(unifyKeyOrAlias(id));
28  }
29 
31  {
32  if (!this->getDbKey().isEmpty() && !this->getDescription().isEmpty())
33  {
34  return this->getDbKey() % u' ' % this->getDescription();
35  }
36  if (!this->getDbKey().isEmpty()) { return this->getDbKey(); }
37  return {};
38  }
39 
40  bool CDistributor::matchesKeyOrAlias(const QString &keyOrAlias) const
41  {
42  QString s(keyOrAlias.trimmed().toUpper());
43  if (s.isEmpty()) { return false; }
44  return (getDbKey() == s || getAlias1() == s || getAlias2() == s);
45  }
46 
47  bool CDistributor::matchesKeyOrAlias(const CDistributor &distributor) const
48  {
49  if (distributor.hasValidDbKey() && this->matchesKeyOrAlias(distributor.getDbKey())) { return true; }
50  if (distributor.hasAlias1() && this->matchesKeyOrAlias(distributor.getAlias1())) { return true; }
51  return (distributor.hasAlias2() && this->matchesKeyOrAlias(distributor.getAlias2()));
52  }
53 
54  bool CDistributor::matchesSimulator(const CSimulatorInfo &simulator) const
55  {
56  return m_simulator.matchesAny(simulator);
57  }
58 
60  {
61  if (index.isMyself()) { return QVariant::fromValue(*this); }
62  if (IDatastoreObjectWithStringKey::canHandleIndex(index))
63  {
64  return IDatastoreObjectWithStringKey::propertyByIndex(index);
65  }
66  if (IOrderable::canHandleIndex(index)) { return IOrderable::propertyByIndex(index); }
67 
68  const ColumnIndex i = index.frontCasted<ColumnIndex>();
69  switch (i)
70  {
71  case IndexAlias1: return QVariant::fromValue(m_alias1);
72  case IndexAlias2: return QVariant::fromValue(m_alias2);
73  case IndexDescription: return QVariant::fromValue(m_description);
74  case IndexSimulator: return m_simulator.propertyByIndex(index.copyFrontRemoved());
75  default: return CValueObject::propertyByIndex(index);
76  }
77  }
78 
79  void CDistributor::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
80  {
81  if (index.isMyself())
82  {
83  (*this) = variant.value<CDistributor>();
84  return;
85  }
86  if (IDatastoreObjectWithStringKey::canHandleIndex(index))
87  {
88  IDatastoreObjectWithStringKey::setPropertyByIndex(index, variant);
89  return;
90  }
91  if (IOrderable::canHandleIndex(index))
92  {
93  IOrderable::setPropertyByIndex(index, variant);
94  return;
95  }
96 
97  const ColumnIndex i = index.frontCasted<ColumnIndex>();
98  switch (i)
99  {
100  case IndexAlias1: m_alias1 = variant.value<QString>(); break;
101  case IndexAlias2: m_alias2 = variant.value<QString>(); break;
102  case IndexDescription: m_description = variant.value<QString>(); break;
103  case IndexSimulator: m_simulator.setPropertyByIndex(index.copyFrontRemoved(), variant); break;
104  default: CValueObject::setPropertyByIndex(index, variant); break;
105  }
106  }
107 
109  {
110  if (IDatastoreObjectWithStringKey::canHandleIndex(index))
111  {
112  return IDatastoreObjectWithStringKey::comparePropertyByIndex(index, compareValue);
113  }
114  if (IOrderable::canHandleIndex(index)) { return IOrderable::comparePropertyByIndex(index, compareValue); }
115 
116  const ColumnIndex i = index.frontCasted<ColumnIndex>();
117  switch (i)
118  {
119  case IndexAlias1: return m_alias1.compare(compareValue.m_alias1, Qt::CaseInsensitive);
120  case IndexAlias2: return m_alias2.compare(compareValue.m_alias2, Qt::CaseInsensitive);
121  case IndexDescription: return m_description.compare(compareValue.getDescription(), Qt::CaseInsensitive);
122  case IndexSimulator:
123  return m_simulator.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.m_simulator);
124  default: break;
125  }
126  Q_ASSERT_X(false, Q_FUNC_INFO, "Compare failed");
127  return 0;
128  }
129 
130  QString CDistributor::convertToQString(bool i18n) const
131  {
132  Q_UNUSED(i18n)
133  QString s = QStringLiteral("Id: '%1'").arg(m_dbKey);
134  if (this->hasAlias1()) { s.append(" ").append(m_alias1); }
135  if (this->hasAlias2()) { s.append(" ").append(m_alias2); }
136  return s;
137  }
138 
139  bool CDistributor::hasCompleteData() const { return !m_description.isEmpty() && !m_dbKey.isEmpty(); }
140 
142  {
143  static const CLogCategoryList cats(CLogCategoryList(this).withValidation());
144  CStatusMessageList msgs;
145  if (!hasValidDbKey())
146  {
147  msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, u"Distributor: missing id"));
148  }
149  if (!hasDescription())
150  {
151  msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, u"Distributor: missing description"));
152  }
153  return msgs;
154  }
155 
156  void CDistributor::updateMissingParts(const CDistributor &otherDistributor)
157  {
158  if (!this->hasValidDbKey() && otherDistributor.hasValidDbKey())
159  {
160  // we have no DB data, but the other one has
161  // so we change roles. We take the DB object as base, and update our parts
162  CDistributor copy(otherDistributor);
163  copy.updateMissingParts(*this);
164  *this = copy;
165  return;
166  }
167 
168  if (!this->hasAlias1()) { this->setAlias1(otherDistributor.getAlias1()); }
169  if (!this->hasAlias2()) { this->setAlias1(otherDistributor.getAlias2()); }
170  if (!this->hasDescription()) { this->setDescription(otherDistributor.getDescription()); }
171  }
172 
173  CDistributor CDistributor::fromDatabaseJson(const QJsonObject &json, const QString &prefix)
174  {
175  if (!existsKey(json, prefix))
176  {
177  // when using relationship, this can be null
178  return CDistributor();
179  }
180 
181  const QString description(json.value(prefix % u"description").toString());
182  if (description.isEmpty())
183  {
184  // stub, only key, maybe also timestamps
185  CDistributor distributorStub;
186  distributorStub.setKeyVersionTimestampFromDatabaseJson(json, prefix);
187  return distributorStub;
188  }
189 
190  const CSimulatorInfo simulator = CSimulatorInfo::fromDatabaseJson(json, prefix);
191  const QString alias1(json.value(prefix % u"alias1").toString());
192  const QString alias2(json.value(prefix % u"alias2").toString());
193  Q_ASSERT_X(!description.isEmpty(), Q_FUNC_INFO, "Missing description");
194  CDistributor distributor("", description, alias1, alias2, simulator);
195  distributor.setKeyVersionTimestampFromDatabaseJson(json, prefix);
196  distributor.setLoadedFromDb(true);
197  return distributor;
198  }
199 
200  const QString &CDistributor::standardFSX()
201  {
202  static const QString k("FSX");
203  return k;
204  }
205 
206  const QString &CDistributor::standardP3D()
207  {
208  static const QString k("P3D");
209  return k;
210  }
211 
212  const QString &CDistributor::standardFS9()
213  {
214  static const QString k("FS9");
215  return k;
216  }
217 
219  {
220  static const QString k("XP");
221  return k;
222  }
223 
225  {
226  static const QString k("FG");
227  return k;
228  }
229 
230  const QSet<QString> &CDistributor::standardAllFsFamily()
231  {
232  static const QSet<QString> fsFamily(
234  return fsFamily;
235  }
236 
237  const QSet<QString> &CDistributor::xplaneMostPopular()
238  {
239  static const QSet<QString> mp({ xplaneBlueBell(), xplaneXcsl() });
240  return mp;
241  }
242 
244  {
245  static const QString k("BB");
246  return k;
247  }
248 
249  const QString &CDistributor::xplaneXcsl()
250  {
251  static const QString k("XCSL");
252  return k;
253  }
254 
255  const QString &CDistributor::standardMsfs()
256  {
257  static const QString k("MSFS");
258  return k;
259  }
260 
262  {
263  static const QString k("MSFS2024");
264  return k;
265  }
266 
267  QString CDistributor::unifyKeyOrAlias(const QString &value)
268  {
269  return removeChars(value.trimmed().toUpper(), [](QChar c) { return !c.isLetterOrNumber(); });
270  }
271 
272 } // namespace swift::misc::simulation
A sequence of log categories.
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.
static bool canHandleIndex(CPropertyIndexRef index)
Can given index be handled.
Definition: orderable.cpp:33
int comparePropertyByIndex(CPropertyIndexRef index, const IOrderable &compareValue) const
Compare for index.
Definition: orderable.cpp:73
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
Definition: orderable.cpp:57
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
Definition: orderable.cpp:40
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
bool hasValidDbKey() const
Has valid DB key.
Definition: datastore.h:195
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
void setDbKey(const QString &key)
Set the DB key.
Definition: datastore.h:192
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
Value object encapsulating information of software distributor.
Definition: distributor.h:33
void setDescription(const QString &description)
Set description.
Definition: distributor.h:62
QString getIdAndDescription() const
Get id and description.
Definition: distributor.cpp:30
static const QString & standardFS9()
Hardcoded keys for standard models.
static const QSet< QString > & standardAllFsFamily()
Hardcoded keys for standard models.
static const QString & xplaneXcsl()
Hardcoded keys for standard models.
int comparePropertyByIndex(CPropertyIndexRef index, const CDistributor &compareValue) const
Compare for index.
QVariant propertyByIndex(swift::misc::CPropertyIndexRef index) const
Property by index.
Definition: distributor.cpp:59
const QString & getDescription() const
Get description.
Definition: distributor.h:56
void setPropertyByIndex(swift::misc::CPropertyIndexRef index, const QVariant &variant)
Set property by index.
Definition: distributor.cpp:79
static const QSet< QString > & xplaneMostPopular()
Hardcoded keys for standard models.
static const QString & standardMsfs()
Hardcoded keys for standard models.
static const QString & standardXPlane()
Hardcoded keys for standard models.
bool matchesKeyOrAlias(const QString &keyOrAlias) const
Matches key or alias.
Definition: distributor.cpp:40
static const QString & standardFSX()
Hardcoded keys for standard models.
static const QString & standardFlightGear()
Hardcoded keys for standard models.
void updateMissingParts(const CDistributor &otherDistributor)
Update missing parts.
CDistributor()
Default constructor.
Definition: distributor.cpp:19
bool hasDescription() const
Has description.
Definition: distributor.h:65
bool hasCompleteData() const
Complete data?
QString convertToQString(bool i18n=false) const
Cast as QString.
static CDistributor fromDatabaseJson(const QJsonObject &json, const QString &prefix=QString())
Object from JSON.
static const QString & standardP3D()
Hardcoded keys for standard models.
static const QString & standardMsfs2024()
Hardcoded keys for standard models.
const QString & getAlias2() const
Get alias2.
Definition: distributor.h:71
swift::misc::CStatusMessageList validate() const
Validate data.
void setAlias1(const QString &alias)
Set alias1.
Definition: distributor.h:74
static const QString & xplaneBlueBell()
Hardcoded keys for standard models.
const QString & getAlias1() const
Get alias1.
Definition: distributor.h:68
bool matchesSimulator(const CSimulatorInfo &simulator) const
Matches simulator.
Definition: distributor.cpp:54
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
int comparePropertyByIndex(CPropertyIndexRef index, const CSimulatorInfo &compareValue) const
Cast as QString.
bool matchesAny(const CSimulatorInfo &otherInfo) const
Matches any simulator.
static CSimulatorInfo fromDatabaseJson(const QJsonObject &json, const QString &prefix)
From database JSON.
QString removeChars(const QString &s, F predicate)
Return a string with characters removed that match the given predicate.
Definition: stringutils.h:35
#define SWIFT_DEFINE_VALUEOBJECT_MIXINS(Namespace, Class)
Explicit template definition of mixins for a CValueObject subclass.
Definition: valueobject.h:67