swift
databaseutils.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2016 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QElapsedTimer>
7 
8 #include "core/application.h"
9 #include "core/webdataservices.h"
10 #include "misc/compressutils.h"
11 #include "misc/fileutils.h"
12 #include "misc/logmessage.h"
13 
14 using namespace swift::misc;
15 using namespace swift::misc::json;
16 using namespace swift::misc::aviation;
17 using namespace swift::misc::simulation;
18 
19 namespace swift::core::db
20 {
21  const QStringList &CDatabaseUtils::getLogCategories()
22  {
23  static const QStringList cats { CLogCategories::modelCache(), CLogCategories::modelSetCache() };
24  return cats;
25  }
26 
27  CAircraftModel CDatabaseUtils::consolidateOwnAircraftModelWithDbData(const CAircraftModel &model, bool force,
28  bool *modified)
29  {
30  bool myModified = false;
31  CAircraftModel ownModel = CDatabaseUtils::consolidateModelWithDbData(model, force, &myModified);
32  // special case here, as we have some specific values for a local model
33 
34  if (myModified)
35  {
36  ownModel.updateMissingParts(model);
37  ownModel.setFileName(model.getFileName());
38  myModified = true;
39  }
40  if (ownModel.getModelType() != CAircraftModel::TypeOwnSimulatorModel)
41  {
42  ownModel.setModelType(CAircraftModel::TypeOwnSimulatorModel);
43  myModified = true;
44  }
45  if (modified) { *modified = myModified; }
46  return ownModel;
47  }
48 
49  CAircraftModel CDatabaseUtils::consolidateModelWithDbData(const CAircraftModel &model, bool force, bool *modified)
50  {
51  if (modified) { *modified = false; }
52  if (!model.hasModelString()) { return model; }
53  if (!hasDbAircraftData()) { return model; }
54 
56  return CDatabaseUtils::consolidateModelWithDbData(model, dbModel, force, modified);
57  }
58 
59  CAircraftModel CDatabaseUtils::consolidateModelWithDbData(const CAircraftModel &model,
60  const CAircraftModel &dbModel, bool force, bool *modified)
61  {
62  Q_ASSERT_X(sApp, Q_FUNC_INFO, "Missing application object");
63  Q_ASSERT_X(sApp->hasWebDataServices(), Q_FUNC_INFO, "No web services");
64 
65  if (modified) { *modified = false; }
66  if (!model.hasModelString()) { return model; }
67  if (!force && model.hasValidDbKey()) { return model; }
68  const int distributorOrder = model.getDistributorOrder(); // later restore that order
69 
70  if (dbModel.isLoadedFromDb())
71  {
72  // take the db model as original
73  if (modified) { *modified = true; }
74  CAircraftModel dbModelModified(dbModel);
75  dbModelModified.updateMissingParts(model);
76  dbModelModified.setDistributorOrder(distributorOrder);
77  dbModelModified.setSimulator(dbModel.getSimulator()); // DB simulator settings have priority
78  return dbModelModified;
79  }
80 
81  // we try our best to update by DB data here
82  // since we have no(!) DB model, we update each of it subobjects
83  CAircraftModel consolidatedModel(model); // copy over
84  if (!consolidatedModel.getLivery().hasValidDbKey())
85  {
86  const CLivery dbLivery(sApp->getWebDataServices()->smartLiverySelector(consolidatedModel.getLivery()));
87  if (dbLivery.hasValidDbKey())
88  {
89  if (modified) { *modified = true; }
90  consolidatedModel.setLivery(dbLivery);
91  }
92  }
93  if (!consolidatedModel.getAircraftIcaoCode().hasValidDbKey() && consolidatedModel.hasAircraftDesignator())
94  {
95  // try to find DB aircraft ICAO here
96  const CAircraftIcaoCode dbIcao(
98  if (dbIcao.hasValidDbKey())
99  {
100  if (modified) { *modified = true; }
101  consolidatedModel.setAircraftIcaoCode(dbIcao);
102  }
103  }
104 
105  const CDistributor dbDistributor(
107  if (dbDistributor.isLoadedFromDb())
108  {
109  if (modified) { *modified = true; }
110  consolidatedModel.setDistributor(dbDistributor);
111  }
112  consolidatedModel.updateLocalFileNames(model);
113  consolidatedModel.setDistributorOrder(distributorOrder);
114  return consolidatedModel;
115  }
116 
117  int CDatabaseUtils::consolidateModelsWithDbData(CAircraftModelList &models, bool force)
118  {
119  return CDatabaseUtils::consolidateModelsWithDbDataAllowsGuiRefresh(models, force, false);
120  }
121 
122  int CDatabaseUtils::fillInMissingAircraftAndLiveryEntities(CAircraftModelList &models)
123  {
124  // fill in those entities which have only an id (key), but no data yet
125  int c = 0;
126  for (CAircraftModel &model : models)
127  {
128  bool changed = false;
129  if (model.getLivery().hasValidDbKey() && !model.getLivery().hasCompleteData())
130  {
131  const CLivery livery = sApp->getWebDataServices()->getLiveryForDbKey(model.getLivery().getDbKey());
132  if (livery.isLoadedFromDb())
133  {
134  model.setLivery(livery);
135  changed = true;
136  }
137  }
138  if (model.getAircraftIcaoCode().hasValidDbKey() && !model.getAircraftIcaoCode().hasCompleteData())
139  {
140  const CAircraftIcaoCode icao =
141  sApp->getWebDataServices()->getAircraftIcaoCodeForDbKey(model.getAircraftIcaoCode().getDbKey());
142  if (icao.isLoadedFromDb())
143  {
144  model.setAircraftIcaoCode(icao);
145  changed = true;
146  }
147  }
148  if (model.getDistributor().hasValidDbKey() && !model.getDistributor().hasCompleteData())
149  {
150  const CDistributor distributor =
151  sApp->getWebDataServices()->getDistributorForDbKey(model.getDistributor().getDbKey());
152  if (distributor.isLoadedFromDb())
153  {
154  model.setDistributor(distributor);
155  changed = true;
156  }
157  }
158  if (changed) { c++; }
159  }
160  return c;
161  }
162 
163  CAircraftModelList CDatabaseUtils::consolidateModelsWithSimulatorModelsAllowsGuiRefresh(
164  const CAircraftModelList &models, const CAircraftModelList &simulatorModels, QStringList &removedModelStrings,
165  bool processEvents)
166  {
167  if (models.isEmpty() || simulatorModels.isEmpty()) { return models; }
168 
169  QElapsedTimer timer;
170  timer.start();
171  const QSet<QString> allOwnModelsModelStrings = simulatorModels.getModelStringSet();
172  CAircraftModelList consolidatedModels;
173  removedModelStrings.clear();
174 
175  int c = 0;
176  for (const CAircraftModel &model : models)
177  {
178  c++;
179  if (processEvents && c % 125 == 0)
180  {
181  if (!sApp || sApp->isShuttingDown()) { return models; }
182  sApp->processEventsFor(25);
183  }
184 
185  const QString ms(model.getModelString());
186  if (ms.isEmpty()) { continue; }
187  if (!allOwnModelsModelStrings.contains(ms))
188  {
189  removedModelStrings.push_back(ms);
190  continue;
191  }
192  CAircraftModel consolidated = simulatorModels.findFirstByModelStringAliasOrDefault(ms);
193  if (consolidated.hasModelString())
194  {
195  CDatabaseUtils::consolidateModelWithDbData(consolidated, true);
196  consolidatedModels.push_back(consolidated);
197  }
198  else { consolidatedModels.push_back(model); }
199  }
200  CLogMessage(static_cast<CDatabaseUtils *>(nullptr)).info(u"Consolidated %1 vs. %2 in %3 ms")
201  << models.size() << simulatorModels.size() << timer.elapsed() << "ms";
202  return consolidatedModels;
203  }
204 
206  CDatabaseUtils::updateModelsDirectoriesAllowsGuiRefresh(const CAircraftModelList &models,
207  const CAircraftModelList &simulatorModels,
208  QStringList &removedModelStrings, bool processEvents)
209  {
210  if (models.isEmpty() || simulatorModels.isEmpty()) { return models; }
211 
212  QElapsedTimer timer;
213  timer.start();
214  const QSet<QString> allOwnModelsModelStrings = simulatorModels.getModelStringSet();
215  CAircraftModelList consolidatedModels;
216  removedModelStrings.clear();
217 
218  int c = 0;
219  for (const CAircraftModel &model : models)
220  {
221  c++;
222  if (processEvents && c % 125 == 0)
223  {
224  if (!sApp || sApp->isShuttingDown()) { return models; }
225  sApp->processEventsFor(25);
226  }
227 
228  const QString ms(model.getModelString());
229  if (ms.isEmpty()) { continue; }
230  if (!allOwnModelsModelStrings.contains(ms))
231  {
232  removedModelStrings.push_back(ms);
233  continue;
234  }
235  CAircraftModel consolidated = simulatorModels.findFirstByModelStringAliasOrDefault(ms);
236  if (consolidated.hasModelString())
237  {
238  if (consolidated.hasExistingCorrespondingFile())
239  {
240  // update by existing one
241  consolidatedModels.push_back(consolidated);
242  }
243  else
244  {
245  // keep
246  consolidatedModels.push_back(model);
247  }
248  }
249  else { consolidatedModels.push_back(model); }
250  }
251  CLogMessage(static_cast<CDatabaseUtils *>(nullptr)).info(u"Updated directories %1 vs. %2 in %3 ms")
252  << models.size() << simulatorModels.size() << timer.elapsed() << "ms";
253  return consolidatedModels;
254  }
255 
256  int CDatabaseUtils::consolidateModelsWithDbDataAllowsGuiRefresh(CAircraftModelList &models, bool force,
257  bool processEvents)
258  {
259  QElapsedTimer timer;
260  timer.start();
261  int c = 0;
262  if (models.isEmpty()) { return c; }
263  for (CAircraftModel &model : models)
264  {
265  if (!force && model.isLoadedFromDb()) { continue; }
266  bool modified = false;
267  model = CDatabaseUtils::consolidateModelWithDbData(model, force, &modified);
268  if (modified || model.hasValidDbKey())
269  {
270  c++;
271  if (processEvents && c % 125 == 0) { sApp->processEventsFor(25); }
272  }
273  }
274  CLogMessage(static_cast<CDatabaseUtils *>(nullptr)).info(u"Consolidated %1 models in %2ms")
275  << models.size() << timer.elapsed();
276  return c;
277  }
278 
279  int CDatabaseUtils::consolidateModelsWithDbData(const CAircraftModelList &dbModels,
280  CAircraftModelList &simulatorModels, bool force)
281  {
282  if (dbModels.isEmpty() || simulatorModels.isEmpty()) { return 0; }
283 
284  QElapsedTimer timer;
285  timer.start();
286  const QSet<QString> dbModelsModelStrings = dbModels.getModelStringSet();
287 
288  int c = 0;
289  for (CAircraftModel &model : simulatorModels)
290  {
291  const QString ms(model.getModelString());
292  if (ms.isEmpty()) { continue; }
293  if (!dbModelsModelStrings.contains(ms)) { continue; }
294  bool modified = false;
295  const CAircraftModel consolidated = CDatabaseUtils::consolidateModelWithDbData(
296  model, dbModels.findFirstByModelStringAliasOrDefault(ms), force, &modified);
297  if (!modified) { continue; }
298  model = consolidated;
299  c++;
300  }
301  CLogMessage(static_cast<CDatabaseUtils *>(nullptr)).info(u"Consolidated %1 models in %2 ms")
302  << simulatorModels.size() << timer.elapsed();
303  return c;
304  }
305 
306  int CDatabaseUtils::consolidateModelsWithDbModelAndDistributor(CAircraftModelList &models, bool force)
307  {
308  int c = 0;
309  if (models.isEmpty()) { return c; }
310  for (CAircraftModel &model : models)
311  {
312  if (!force && model.hasValidDbKey()) { continue; }
313  const CAircraftModel dbModel(sApp->getWebDataServices()->getModelForModelString(model.getModelString()));
314  if (dbModel.hasValidDbKey())
315  {
316  model = dbModel;
317  c++;
318  continue;
319  }
320  const CDistributor distributor =
321  sApp->getWebDataServices()->smartDistributorSelector(model.getDistributor(), model);
322  if (distributor.isLoadedFromDb()) { model.setDistributor(distributor); }
323  }
324  return c;
325  }
326 
327  CAircraftModel CDatabaseUtils::consolidateModelWithDbDistributor(const CAircraftModel &model, bool force)
328  {
329  if (!force && model.getDistributor().isLoadedFromDb()) { return model; }
330  const CDistributor distributor =
332  if (!distributor.isLoadedFromDb()) { return model; }
333  CAircraftModel newModel(model);
334  newModel.setDistributor(distributor);
335  return newModel;
336  }
337 
338  int CDatabaseUtils::consolidateModelsWithDbDistributor(CAircraftModelList &models, bool force)
339  {
340  int c = 0;
341  if (models.isEmpty()) { return c; }
342  for (CAircraftModel &model : models)
343  {
344  if (model.hasValidDbKey() || model.getDistributor().hasValidDbKey()) { continue; }
345  model = CDatabaseUtils::consolidateModelWithDbDistributor(model, force);
346  if (model.getDistributor().hasValidDbKey()) { c++; }
347  }
348  return c;
349  }
350 
351  CAircraftModelList CDatabaseUtils::updateSimulatorForFsFamily(const CAircraftModelList &ownModels,
352  CStatusMessageList *updateInfo, int maxToStash,
353  IProgressIndicator *progressIndicator,
354  bool processEvents)
355  {
356  if (!sApp || !sApp->getWebDataServices() || sApp->isShuttingDown()) { return CAircraftModelList(); }
358  CAircraftModelList stashModels;
359  if (dbFsFamilyModels.isEmpty() || ownModels.isEmpty()) { return stashModels; }
360  const QSet<QString> dbKeys = dbFsFamilyModels.getModelStringSet();
361  const int maxModelsCount = (maxToStash >= 0) ? maxToStash : ownModels.size();
362  if (maxModelsCount < 1) { return stashModels; }
363 
364  int c = 0; // counter
365  for (const CAircraftModel &ownModel : ownModels)
366  {
367  c++;
368 
369  // process events
370  if (processEvents && c % 500 == 0)
371  {
372  if (progressIndicator)
373  {
374  const int percentage = c * 100 / maxModelsCount;
375  progressIndicator->updateProgressIndicatorAndProcessEvents(percentage);
376  }
377  else { sApp->processEventsFor(10); }
378  }
379 
380  // values to be skipped
381  if (maxToStash >= 0 && stashModels.size() > maxToStash) { break; }
382  if (!dbKeys.contains(ownModel.getModelString())) { continue; }
383  if (ownModel.matchesSimulatorFlag(CSimulatorInfo::XPLANE)) { continue; }
384 
385  // in DB
386  CAircraftModel dbModel = dbFsFamilyModels.findFirstByModelStringAliasOrDefault(ownModel.getModelString());
387  if (!dbModel.isLoadedFromDb()) { continue; }
388 
389  // update simulator and add
390  CSimulatorInfo simulator(dbModel.getSimulator());
391  const CSimulatorInfo dbModelSimulator(simulator);
392  const CSimulatorInfo delta = simulator.add(ownModel.getSimulator());
393  if (delta.getSimulator() == CSimulatorInfo::None) { continue; }
394 
395  dbModel.setSimulator(simulator);
396  stashModels.push_back(dbModel); // changed DB model
397  if (updateInfo)
398  {
399  const CStatusMessage m =
400  CStatusMessage(static_cast<CDatabaseUtils *>(nullptr)).info(u"%1 -> %2 (%3) for '%4'")
401  << dbModelSimulator.toQString(true) << simulator.toQString(true) << delta.toQString(true)
402  << dbModel.getModelStringAndDbKey();
403  updateInfo->push_back(m);
404  }
405  }
406  progressIndicator->updateProgressIndicatorAndProcessEvents(100);
407  return stashModels;
408  }
409 
410  QJsonDocument CDatabaseUtils::databaseJsonToQJsonDocument(const QString &content)
411  {
412  static const QString compressed("swift:");
413  if (content.isEmpty()) { return QJsonDocument(); }
414  QByteArray byteData;
415  if (json::looksLikeJson(content))
416  {
417  // uncompressed
418  byteData = content.toUtf8();
419  }
420  else if (content.startsWith(compressed) && content.length() > compressed.length() + 3)
421  {
422  do {
423  // "swift:1234:base64encoded
424  const int cl = compressed.length();
425  const int contentIndex = content.indexOf(':', cl);
426  if (contentIndex < cl) break; // should not happen, malformed
427  const QString ls = content.mid(cl, contentIndex - cl); // content length
428  bool ok;
429  const qint32 size = ls.toInt(&ok);
430  if (!ok) break; // malformed size
431  if (size < 1) break;
432 
433  QByteArray ba;
434  ba.append(content.mid(contentIndex).toUtf8());
435  ba = QByteArray::fromBase64(ba);
436  ba.insert(0, CCompressUtils::lengthHeader(size)); // adding 4 bytes length header
437  byteData = qUncompress(ba);
438  }
439  while (false);
440  }
441 
442  if (byteData.isEmpty()) { return QJsonDocument(); }
443  return QJsonDocument::fromJson(byteData);
444  }
445 
446  QJsonDocument CDatabaseUtils::readQJsonDocumentFromDatabaseFile(const QString &filename)
447  {
448  const QString raw = CFileUtils::readFileToString(filename);
449  if (raw.isEmpty()) { return QJsonDocument(); }
450  return CDatabaseUtils::databaseJsonToQJsonDocument(raw);
451  }
452 
453  QJsonObject CDatabaseUtils::readQJsonObjectFromDatabaseFile(const QString &filename)
454  {
455  const QString raw = CFileUtils::readFileToString(filename);
456  if (raw.isEmpty()) { return QJsonObject(); }
457 
458  // allow also compressed format
459  const QJsonDocument jsonDoc = CDatabaseUtils::databaseJsonToQJsonDocument(raw);
460  return jsonDoc.object();
461  }
462 
463  QJsonObject CDatabaseUtils::readQJsonObjectFromDatabaseFile(const QString &directory, const QString &filename)
464  {
465  return CDatabaseUtils::readQJsonObjectFromDatabaseFile(CFileUtils::appendFilePaths(directory, filename));
466  }
467 
468  bool CDatabaseUtils::hasDbAircraftData()
469  {
471  }
472 
473  const QUrlQuery &CDatabaseUtils::getCompressedQuery()
474  {
475  static const QUrlQuery q("compressed=true");
476  return q;
477  }
478 
479  QHttpPart CDatabaseUtils::getJsonTextMultipart(const QJsonObject &json, bool compress)
480  {
481  const QByteArray bytes(QJsonDocument(json).toJson(QJsonDocument::Compact));
482  return CDatabaseUtils::getJsonTextMultipart(bytes, compress);
483  }
484 
485  QHttpPart CDatabaseUtils::getJsonTextMultipart(const QString &json, bool compress)
486  {
487  const QByteArray bytes(json.toUtf8());
488  return CDatabaseUtils::getJsonTextMultipart(bytes, compress);
489  }
490 
491  QHttpPart CDatabaseUtils::getJsonTextMultipart(const QJsonArray &json, bool compress)
492  {
493  const QByteArray bytes(QJsonDocument(json).toJson(QJsonDocument::Compact));
494  return CDatabaseUtils::getJsonTextMultipart(bytes, compress);
495  }
496 
497  QHttpPart CDatabaseUtils::getJsonTextMultipart(const QByteArray &bytes, bool compress)
498  {
499  static const QString name("form-data; name=\"swiftjson\"");
500  static const QVariant header(name);
501  QHttpPart textPart;
502  textPart.setHeader(QNetworkRequest::ContentDispositionHeader, header);
503  if (compress)
504  {
505  QByteArray ba = qCompress(bytes);
506  ba.remove(0, 4); // remove the non standard header
507  textPart.setBody(ba);
508  }
509  else { textPart.setBody(bytes); }
510  return textPart;
511  }
512 
513  QHttpPart CDatabaseUtils::getMultipartWithDebugFlag()
514  {
515  QHttpPart textPartDebug;
516  textPartDebug.setHeader(QNetworkRequest::ContentDispositionHeader,
517  QVariant("form-data; name=\"XDEBUG_SESSION_START\""));
518  textPartDebug.setBody(QString("ECLIPSE_DBGP").toUtf8());
519  return textPartDebug;
520  }
521 
522  ChangedAutoPublishData CDatabaseUtils::autoPublishDataChanged(const QString &modelString,
524  const CSimulatorInfo &simulator)
525  {
526  ChangedAutoPublishData changed;
527  if (!sApp || sApp->isShuttingDown() || !sApp->getWebDataServices()) { return changed; }
528  const CAircraftModel model = sApp->getWebDataServices()->getModelForModelString(modelString);
529  return CDatabaseUtils::autoPublishDataChanged(model, cg, simulator);
530  }
531 
532  ChangedAutoPublishData CDatabaseUtils::autoPublishDataChanged(const CAircraftModel &model,
534  const CSimulatorInfo &simulator)
535  {
536  ChangedAutoPublishData changed;
537  changed.modelKnown = model.hasValidDbKey();
538  if (!changed.modelKnown) { return changed; }
539  changed.changedCG = !(cg == model.getCG());
540  changed.changedSim = !(model.getSimulator().matchesAll(simulator));
541  return changed;
542  }
543 } // namespace swift::core::db
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
static void processEventsFor(int milliseconds)
Process all events for some time.
bool hasWebDataServices() const
Web data services available?
bool isShuttingDown() const
Is application shutting down?
CWebDataServices * getWebDataServices() const
Get the web data services.
swift::misc::aviation::CAircraftIcaoCode smartAircraftIcaoSelector(const swift::misc::aviation::CAircraftIcaoCode &icao) const
Use an ICAO object to select the best complete ICAO object from DB for it.
swift::misc::simulation::CAircraftModelList getModels() const
Models.
swift::misc::simulation::CDistributorList getDistributors() const
Distributors.
swift::misc::simulation::CAircraftModel getModelForModelString(const QString &modelString) const
Model for model string if any.
swift::misc::aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int key) const
ICAO code for id.
swift::misc::aviation::CLivery getLiveryForDbKey(int id) const
Livery for id.
bool hasDbAircraftData() const
Are all DB data for an aircraft entity available?
swift::misc::simulation::CDistributor getDistributorForDbKey(const QString &key) const
Distributor for key.
swift::misc::simulation::CDistributor smartDistributorSelector(const swift::misc::simulation::CDistributor &distributor) const
Use distributor object to select the best complete distributor from DB.
swift::misc::aviation::CLivery smartLiverySelector(const swift::misc::aviation::CLivery &livery) const
Use a livery as template and select the best complete livery from DB for it.
Implementing class features a progress bar or something similar.
Definition: progress.h:16
void updateProgressIndicatorAndProcessEvents(int percentage)
Same as updateProgressIndicator but processing events.
Definition: progress.h:25
Read information about data from Database.
Definition: databaseutils.h:24
static QByteArray lengthHeader(qint32 size)
Length header.
static QString appendFilePaths(const QString &path1, const QString &path2)
Append file paths.
Definition: fileutils.cpp:95
static QString readFileToString(const QString &fileNameAndPath)
Read file into string.
Definition: fileutils.cpp:68
static const QString & modelSetCache()
Model set cache.
static const QString & modelCache()
Model cache.
Class for emitting a log message.
Definition: logmessage.h:27
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition: sequence.h:305
void clear()
Removes all elements in the sequence.
Definition: sequence.h:288
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Streamable status message, e.g.
Status messages, e.g. from Core -> GUI.
Value object for ICAO classification.
Value object encapsulating information about an airpot.
Definition: livery.h:29
bool isLoadedFromDb() const
Loaded from DB.
Definition: datastore.cpp:49
bool hasValidDbKey() const
Has valid DB key.
Definition: datastore.h:102
bool isLoadedFromDb() const
Loaded from DB.
Definition: datastore.h:204
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:74
Physical unit length (length)
Definition: length.h:18
Aircraft model (used by another pilot, my models on disk)
Definition: aircraftmodel.h:71
bool setDistributorOrder(int order)
Set the distributor order.
bool hasExistingCorrespondingFile() const
Does the corresponding file exist?
void setModelType(ModelType type)
Set type.
const aviation::CLivery & getLivery() const
Get livery.
void updateLocalFileNames(const CAircraftModel &model)
Update file names from local model.
CSimulatorInfo getSimulator() const
Simulator info.
const QString & getModelString() const
Model key, either queried or loaded from simulator model.
void setFileName(const QString &fileName)
File name.
const physical_quantities::CLength & getCG() const
Get center of gravity.
bool hasAircraftDesignator() const
Has aircraft designator?
void setSimulator(const CSimulatorInfo &simulator)
Set simulator info.
int getDistributorOrder() const
Get distributor`s order value.
const CDistributor & getDistributor() const
Get distributor.
const aviation::CAircraftIcaoCode & getAircraftIcaoCode() const
Aircraft ICAO code.
ModelType getModelType() const
Model type.
QString getModelStringAndDbKey() const
Model string and DB key (if available)
bool hasModelString() const
Non empty model string?
void setLivery(const aviation::CLivery &livery)
Livery.
void setDistributor(const CDistributor &distributor)
Set distributor.
bool setAircraftIcaoCode(const aviation::CAircraftIcaoCode &aircraftIcaoCode)
Set aircraft ICAO code.
const QString & getFileName() const
File name (corresponding data for simulator, only available if representing simulator model.
void updateMissingParts(const CAircraftModel &otherModel, bool dbModelPriority=true)
Update missing parts from another model.
Value object encapsulating a list of aircraft models.
QSet< QString > getModelStringSet() const
Model strings as set.
CAircraftModel findFirstByModelStringAliasOrDefault(const QString &modelString, Qt::CaseSensitivity sensitivity=Qt::CaseInsensitive) const
Find first by model string.
CAircraftModelList findFsFamilyModels() const
All models of the FS (FSX, P3D, FS9, MSFS) family.
Value object encapsulating information of software distributor.
Definition: distributor.h:33
CDistributor smartDistributorSelector(const CDistributor &distributorPattern) const
Best match by given pattern.
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
CSimulatorInfo add(const CSimulatorInfo &other)
Add simulator.
bool matchesAll(const CSimulatorInfo &otherInfo) const
Matches all simulators.
Simulator getSimulator() const
Simulator.
Classes interacting with the swift database (aka "datastore").
Free functions in swift::misc.