swift
simulatorsettings.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 <QStringBuilder>
7 
8 #include "config/buildconfig.h"
13 #include "misc/stringutils.h"
14 #include "misc/verify.h"
15 
16 using namespace swift::config;
17 using namespace swift::misc::physical_quantities;
18 using namespace swift::misc::simulation::fscommon;
19 using namespace swift::misc::simulation::xplane;
20 using namespace swift::misc::simulation::flightgear;
21 
22 SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::simulation::settings, CSimulatorSettings)
23 SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::simulation::settings, CFsxP3DSettings)
24 SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::simulation::settings, CSimulatorMessagesSettings)
25 
26 namespace swift::misc::simulation::settings
27 {
28  const QString &CSimulatorSettings::cgSourceAsString(CSimulatorSettings::CGSource source)
29  {
30  static const QString sf("simulator 1st");
31  static const QString dbf("DB 1st");
32  static const QString so("simulator only");
33  static const QString dbo("DB only");
34 
35  switch (source)
36  {
37  case CGFromSimulatorFirst: return sf;
38  case CGFromDBFirst: return dbf;
39  case CGFromSimulatorOnly: return so;
40  case CGFromDBOnly: return dbo;
41  default: break;
42  }
43  static const QString u("unknown");
44  return u;
45  }
46 
47  CSimulatorSettings::CSimulatorSettings() {}
48 
49  void CSimulatorSettings::setSimulatorDirectory(const QString &simulatorDirectory)
50  {
51  m_simulatorDirectory = simulatorDirectory.trimmed();
52  }
53 
54  const QString &CSimulatorSettings::getSimulatorDirectory() const { return m_simulatorDirectory; }
55 
56  void CSimulatorSettings::setModelDirectories(const QStringList &modelDirectories)
57  {
58  m_modelDirectories = modelDirectories;
59  m_modelDirectories.removeAll({}); // empty values
60  m_modelDirectories.removeDuplicates(); // duplicates
61  }
62 
63  void CSimulatorSettings::clearModelDirectories() { m_modelDirectories.clear(); }
64 
65  void CSimulatorSettings::setModelDirectory(const QString &modelDirectory)
66  {
67  m_modelDirectories = QStringList({ modelDirectory });
68  }
69 
70  bool CSimulatorSettings::addModelDirectory(const QString &modelDirectory)
71  {
72  const Qt::CaseSensitivity cs =
73  CBuildConfig::isRunningOnWindowsNtPlatform() ? Qt::CaseInsensitive : Qt::CaseSensitive;
74  if (m_modelDirectories.contains(modelDirectory, cs)) { return false; }
75  m_modelDirectories.push_back(modelDirectory);
76  m_modelDirectories.removeAll({});
77  m_modelDirectories.removeDuplicates();
78  return true;
79  }
80 
81  const QStringList &CSimulatorSettings::getModelDirectories() const { return m_modelDirectories; }
82 
83  void CSimulatorSettings::setModelExcludeDirectories(const QStringList &excludeDirectories)
84  {
85  m_excludeDirectoryPatterns = excludeDirectories;
86  m_excludeDirectoryPatterns.removeAll({});
87  m_excludeDirectoryPatterns.removeDuplicates();
88  }
89 
90  const QStringList &CSimulatorSettings::getModelExcludeDirectoryPatterns() const
91  {
92  return m_excludeDirectoryPatterns;
93  }
94 
95  bool CSimulatorSettings::setComIntegrated(bool integrated)
96  {
97  if (integrated == m_comIntegration) { return false; }
98  m_comIntegration = integrated;
99  return true;
100  }
101 
102  bool CSimulatorSettings::setCGSource(CSimulatorSettings::CGSource source)
103  {
104  const int s = static_cast<int>(source);
105  if (m_cgSource == s) { return false; }
106  m_cgSource = s;
107  return true;
108  }
109 
110  bool CSimulatorSettings::setRecordOwnAircraftGnd(bool record)
111  {
112  if (record == m_recordGnd) { return false; }
113  m_recordGnd = record;
114  return true;
115  }
116 
117  bool CSimulatorSettings::setRecordedGndRadius(const CLength &radius)
118  {
119  if (radius == m_recordedGndRadius) { return false; }
120  m_recordedGndRadius = radius;
121  return true;
122  }
123 
124  void CSimulatorSettings::resetPaths()
125  {
126  m_excludeDirectoryPatterns.clear();
127  m_modelDirectories.clear();
128  m_simulatorDirectory.clear();
129  }
130 
131  QString CSimulatorSettings::convertToQString(bool i18n) const { return convertToQString(", ", i18n); }
132 
133  QString CSimulatorSettings::convertToQString(const QString &separator, bool i18n) const
134  {
135  Q_UNUSED(i18n)
136  return u"model directories: " % m_modelDirectories.join(',') % separator % u"exclude directories: " %
137  m_excludeDirectoryPatterns.join(',');
138  }
139 
140  QVariant CSimulatorSettings::propertyByIndex(CPropertyIndexRef index) const
141  {
142  if (index.isMyself()) { return QVariant::fromValue(*this); }
143  const ColumnIndex i = index.frontCasted<ColumnIndex>();
144  switch (i)
145  {
146  case IndexSimulatorDirectory: return QVariant::fromValue(m_simulatorDirectory);
147  case IndexModelDirectories: return QVariant::fromValue(m_modelDirectories);
148  case IndexModelExcludeDirectoryPatterns: return QVariant::fromValue(m_excludeDirectoryPatterns);
149  case IndexComIntegration: return QVariant::fromValue(m_comIntegration);
150  case IndexRecordOwnAircraftGnd: return QVariant::fromValue(m_recordGnd);
151  case IndexCGSource: return QVariant::fromValue(m_cgSource);
152  case IndexRecordOwnAircraftGndRadius: return m_recordedGndRadius.propertyByIndex(index.copyFrontRemoved());
153  default: return CValueObject::propertyByIndex(index);
154  }
155  }
156 
157  void CSimulatorSettings::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
158  {
159  if (index.isMyself())
160  {
161  (*this) = variant.value<CSimulatorSettings>();
162  return;
163  }
164  const ColumnIndex i = index.frontCasted<ColumnIndex>();
165  switch (i)
166  {
167  case IndexSimulatorDirectory: this->setSimulatorDirectory(variant.toString()); break;
168  case IndexModelDirectories: this->setSimulatorDirectory(variant.toString()); break;
169  case IndexComIntegration: this->setComIntegrated(variant.toBool()); break;
170  case IndexRecordOwnAircraftGnd: this->setRecordOwnAircraftGnd(variant.toBool()); break;
171  case IndexModelExcludeDirectoryPatterns: m_excludeDirectoryPatterns = variant.value<QStringList>(); break;
172  case IndexCGSource: m_cgSource = variant.toInt(); break;
173  case IndexRecordOwnAircraftGndRadius:
174  m_recordedGndRadius.setPropertyByIndex(index.copyFrontRemoved(), variant);
175  break;
176  default: CValueObject::setPropertyByIndex(index, variant); break;
177  }
178  }
179 
180  CMultiSimulatorSettings::CMultiSimulatorSettings(QObject *parent) : QObject(parent)
181  {
182  // void
183  }
184 
186  {
187  if (!simulator.isSingleSimulator())
188  {
189  // mostly happening with emulated driver, VERIFY for better debugging
190  SWIFT_VERIFY_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
191  return CSimulatorSettings();
192  }
193  switch (simulator.getSimulator())
194  {
195  case CSimulatorInfo::FG: return m_simSettingsFG.get();
196  case CSimulatorInfo::FS9: return m_simSettingsFs9.get();
197  case CSimulatorInfo::FSX: return m_simSettingsFsx.get();
198  case CSimulatorInfo::P3D: return m_simSettingsP3D.get();
199  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.get();
200  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.get();
201  case CSimulatorInfo::XPLANE: return m_simSettingsXP.get();
202 
203  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
204  }
205  return CSimulatorSettings();
206  }
207 
209  {
210  return CSpecializedSimulatorSettings(this->getSettings(simulator), simulator);
211  }
212 
214  const CSimulatorInfo &simulator)
215  {
216  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
217  switch (simulator.getSimulator())
218  {
219  case CSimulatorInfo::FG: return m_simSettingsFG.set(settings);
220  case CSimulatorInfo::FS9: return m_simSettingsFs9.set(settings);
221  case CSimulatorInfo::FSX: return m_simSettingsFsx.set(settings);
222  case CSimulatorInfo::P3D: return m_simSettingsP3D.set(settings);
223  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.set(settings);
224  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.set(settings);
225  case CSimulatorInfo::XPLANE: return m_simSettingsXP.set(settings);
226  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
227  }
228  return CStatusMessage({ CLogCategories::settings() }, CStatusMessage::SeverityError, u"wrong simulator");
229  }
230 
232  const CSimulatorInfo &simulator)
233  {
234  CSimulatorSettings s = this->getSettings(simulator);
235  if (!s.addModelDirectory(modelDirectory))
236  {
238  u"directory already existing");
239  }
240  return this->setSettings(s, simulator);
241  }
242 
244  {
245  CSimulatorSettings s = this->getSettings(simulator);
247  return this->setSettings(s, simulator);
248  }
249 
251  const CSimulatorInfo &simulator)
252  {
253  this->setSettings(settings, simulator);
254  CStatusMessageList msgs;
255  switch (simulator.getSimulator())
256  {
257  case CSimulatorInfo::FG: break;
258  case CSimulatorInfo::FS9: break;
259  case CSimulatorInfo::FSX: break;
260  case CSimulatorInfo::P3D: break;
261  case CSimulatorInfo::MSFS: break;
262  case CSimulatorInfo::MSFS2024: break;
263  case CSimulatorInfo::XPLANE:
264  {
265  if (settings.hasModelDirectories())
266  {
267  const QString simDir = this->getSimulatorDirectoryOrDefault(simulator);
268  msgs = CXPlaneUtil::validateModelDirectories(simDir, settings.getModelDirectories());
269  }
270  }
271  break;
272  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
273  }
274  return msgs;
275  }
276 
278  const CSimulatorInfo &simulator)
279  {
280  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
281  switch (simulator.getSimulator())
282  {
283  case CSimulatorInfo::FG: return m_simSettingsFG.setAndSave(settings);
284  case CSimulatorInfo::FS9: return m_simSettingsFs9.setAndSave(settings);
285  case CSimulatorInfo::FSX: return m_simSettingsFsx.setAndSave(settings);
286  case CSimulatorInfo::P3D: return m_simSettingsP3D.setAndSave(settings);
287  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.setAndSave(settings);
288  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.setAndSave(settings);
289  case CSimulatorInfo::XPLANE: return m_simSettingsXP.setAndSave(settings);
290  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
291  }
292  return CStatusMessage({ CLogCategories::settings() }, CStatusMessage::SeverityError, u"wrong simulator");
293  }
294 
296  const CSimulatorInfo &simulator)
297  {
298  return this->setAndSaveSettings(settings.getGenericSettings(), simulator);
299  }
300 
302  {
303  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
304  switch (simulator.getSimulator())
305  {
306  case CSimulatorInfo::FG: return m_simSettingsFG.save();
307  case CSimulatorInfo::FS9: return m_simSettingsFs9.save();
308  case CSimulatorInfo::FSX: return m_simSettingsFsx.save();
309  case CSimulatorInfo::P3D: return m_simSettingsP3D.save();
310  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.save();
311  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.save();
312  case CSimulatorInfo::XPLANE: return m_simSettingsXP.save();
313  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
314  }
315  return CStatusMessage({ CLogCategories::settings() }, CStatusMessage::SeverityError, u"wrong simulator");
316  }
317 
319  {
320  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
322  }
323 
325  {
326  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
328  }
329 
331  {
332  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
333  return s.getModelDirectoriesOrDefault();
334  }
335 
337  {
338  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
340  }
341 
343  {
344  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
346  }
347 
348  QStringList
350  {
351  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
353  }
354 
355  QStringList
357  {
358  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
360  }
361 
363  {
364  CSimulatorSettings s = this->getSettings(simulator);
365  s.resetPaths();
366  this->setAndSaveSettings(s, simulator);
367  }
368 
369  const QStringList &CMultiSimulatorSettings::defaultModelDirectories(const CSimulatorInfo &simulator) const
370  {
372  }
373 
374  void CMultiSimulatorSettings::onFsxSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::fsx()); }
375 
376  void CMultiSimulatorSettings::onP3DSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::p3d()); }
377 
378  void CMultiSimulatorSettings::onFs9SettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::fs9()); }
379 
380  void CMultiSimulatorSettings::onMsfsSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::msfs()); }
381 
382  void CMultiSimulatorSettings::onMsfs2024SettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::msfs2024()); }
383 
384  void CMultiSimulatorSettings::onXPSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::xplane()); }
385 
386  void CMultiSimulatorSettings::onFGSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::fg()); }
387 
388  void CMultiSimulatorSettings::emitSettingsChanged(const CSimulatorInfo &simInfo)
389  {
390  emit this->settingsChanged(simInfo);
391  }
392 
394  {
395  m_technicalLogLevel = static_cast<int>(severity);
396  }
397 
398  void CSimulatorMessagesSettings::disableTechnicalMessages() { m_technicalLogLevel = -1; }
399 
401  {
402  if (m_technicalLogLevel < 0) { return false; }
403  return (m_technicalLogLevel <= CStatusMessage::SeverityError);
404  }
405 
407  {
408  if (m_technicalLogLevel < 0) { return false; }
409  return (m_technicalLogLevel <= CStatusMessage::SeverityWarning);
410  }
411 
413  {
414  if (m_technicalLogLevel < 0) { return false; }
415  return (m_technicalLogLevel <= CStatusMessage::SeverityInfo);
416  }
417 
418  bool CSimulatorMessagesSettings::isRelayTechnicalMessages() const { return (m_technicalLogLevel >= 0); }
419 
420  void CSimulatorMessagesSettings::setRelayTextMessages(CSimulatorMessagesSettings::TextMessageType messageType)
421  {
422  m_messageType = static_cast<int>(messageType);
423  }
424 
426  {
427  return this->getRelayedTextMessageTypes().testFlag(TextMessageSupervisor);
428  }
429 
431  {
432  return this->getRelayedTextMessageTypes().testFlag(TextMessagePrivate);
433  }
434 
436  {
437  return this->getRelayedTextMessageTypes().testFlag(TextMessagesUnicom);
438  }
439 
441  {
442  return this->getRelayedTextMessageTypes().testFlag(TextMessagesCom1);
443  }
444 
446  {
447  return this->getRelayedTextMessageTypes().testFlag(TextMessagesCom2);
448  }
449 
451  {
452  if (message.isEmpty()) { return false; }
453  if (!this->isRelayGloballyEnabled()) { return false; }
454  if (!this->isRelayTechnicalMessages()) { return false; }
455  const int s = static_cast<int>(message.getSeverity());
456  return (s >= m_technicalLogLevel);
457  }
458 
459  bool
461  const swift::misc::simulation::CSimulatedAircraft &aircraft) const
462  {
463  if (msg.isEmpty()) { return false; }
464  if (!this->isRelayGloballyEnabled()) { return false; }
465  if (m_messageType == NoTextMessages) { return false; }
466 
467  const TextMessageType mt = static_cast<TextMessageType>(m_messageType);
468  if (msg.isPrivateMessage() && mt.testFlag(TextMessagePrivate)) { return true; }
469  if (msg.isSupervisorMessage() && (mt.testFlag(TextMessagePrivate) || mt.testFlag(TextMessageSupervisor)))
470  {
471  return true;
472  }
473  if (msg.isSendToUnicom() && mt.testFlag(TextMessagesUnicom)) { return true; }
474 
475  if (msg.isRadioMessage())
476  {
477  const CFrequency f(msg.getFrequency());
478  if (mt.testFlag(TextMessagesCom1))
479  {
480  if (aircraft.getCom1System().isActiveFrequencySameFrequency(f)) { return true; }
481  }
482  if (mt.testFlag(TextMessagesCom2))
483  {
484  if (aircraft.getCom2System().isActiveFrequencySameFrequency(f)) { return true; }
485  }
486  }
487  return false;
488  }
489 
490  CSimulatorMessagesSettings::TextMessageType CSimulatorMessagesSettings::getRelayedTextMessageTypes() const
491  {
492  return static_cast<CSimulatorMessagesSettings::TextMessageType>(m_messageType);
493  }
494 
496  {
497  Q_UNUSED(i18n)
498  static const QString s("Enabled %1, text messages: %2, severity: %3");
499  QString severity;
500  if (this->isRelayTechnicalMessages()) { severity = QStringLiteral("No tech. msgs"); }
501  else
502  {
503  severity =
504  CStatusMessage::severityToString(static_cast<CStatusMessage::StatusSeverity>(m_technicalLogLevel));
505  }
506  return s.arg(boolToOnOff(m_relayGloballyEnabled)).arg(m_messageType).arg(severity);
507  }
508 
510  {
511  if (index.isMyself()) { return QVariant::fromValue(*this); }
512  const ColumnIndex i = index.frontCasted<ColumnIndex>();
513  switch (i)
514  {
515  case IndexTechnicalLogSeverity: return QVariant::fromValue(m_technicalLogLevel);
516  case IndexRelayTextMessage: return QVariant::fromValue(m_messageType);
517  case IndexRelayGloballyEnabled: return QVariant::fromValue(m_relayGloballyEnabled);
518  default: return CValueObject::propertyByIndex(index);
519  }
520  }
521 
523  {
524  if (index.isMyself())
525  {
526  (*this) = variant.value<CSimulatorMessagesSettings>();
527  return;
528  }
529  const ColumnIndex i = index.frontCasted<ColumnIndex>();
530  switch (i)
531  {
532  case IndexTechnicalLogSeverity:
533  this->setTechnicalLogSeverity(static_cast<CStatusMessage::StatusSeverity>(variant.toInt()));
534  break;
535  case IndexRelayTextMessage:
536  this->setRelayTextMessages(static_cast<CSimulatorMessagesSettings::TextMessageType>(variant.toInt()));
537  break;
538  case IndexRelayGloballyEnabled: this->setRelayGloballyEnabled(variant.toBool()); break;
539  default: CValueObject::setPropertyByIndex(index, variant); break;
540  }
541  }
542 
544  {
546  }
547 
549  {
550  static const QString empty;
551  if (!m_genericSettings.hasSimulatorDirectory()) { return empty; }
554  {
555  return empty;
556  }
558  }
559 
561  {
565  }
566 
568  {
571  }
572 
574  {
575  if (!m_genericSettings.hasSimulatorDirectory()) { return QStringList(); }
576  const QString s(m_genericSettings.getSimulatorDirectory());
577  QStringList dirs;
578  switch (m_simulator.getSimulator())
579  {
580  case CSimulatorInfo::FG: dirs = QStringList(CFlightgearUtil::modelDirectoriesFromSimDir(s)); break;
581  case CSimulatorInfo::FS9: dirs = QStringList({ CFsDirectories::fs9AircraftDirFromSimDir(s) }); break;
582  case CSimulatorInfo::FSX:
583  dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(
584  CFsDirectories::fsxSimObjectsDirFromSimDir(s));
585  break;
586  case CSimulatorInfo::P3D:
587  {
588  const QString versionHint = CFsDirectories::guessP3DVersion(s);
589  dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(
590  CFsDirectories::p3dSimObjectsDirFromSimDir(s), versionHint);
591  }
592  break;
593  case CSimulatorInfo::XPLANE: dirs = QStringList({ CXPlaneUtil::modelDirectoriesFromSimDir(s) }); break;
594  case CSimulatorInfo::MSFS: dirs = QStringList({ CFsDirectories::msfsSimObjectsDir() }); break;
595  case CSimulatorInfo::MSFS2024: dirs = QStringList({ CFsDirectories::msfs2024SimObjectsDir() }); break;
596  default: break;
597  }
598 
599  dirs.removeAll({}); // remove empty
600  dirs.removeDuplicates();
601  return dirs;
602  }
603 
605  {
607  {
609  }
611  }
612 
614  {
615  static const QStringList empty;
616  if (!m_genericSettings.hasModelDirectories()) { return empty; }
617  const QStringList defaultDirectories = CSpecializedSimulatorSettings::defaultModelDirectories(m_simulator);
618  if (CFileUtils::sameDirectories(m_genericSettings.getModelDirectories(), defaultDirectories)) { return empty; }
620  }
621 
623  {
625  }
626 
628  {
629  static const QString empty;
630  if (this->getModelDirectoriesOrDefault().isEmpty()) { return empty; }
631  return this->getModelDirectoriesOrDefault().constFirst();
632  }
633 
635  {
637  }
638 
640  {
641  static const QStringList empty;
642  if (!m_genericSettings.hasModelExcludeDirectoryPatterns()) { return empty; }
645  {
646  return empty;
647  }
649  }
650 
652  {
656  }
657 
659  {
660  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
661  static const QStringList e;
662  switch (simulator.getSimulator())
663  {
664  case CSimulatorInfo::FG:
665  {
666  return CFlightgearUtil::flightgearModelDirectories();
667  }
668  case CSimulatorInfo::FS9:
669  {
670  if (CFsDirectories::fs9AircraftDir().isEmpty()) { return e; }
671  static const QStringList md({ CFsDirectories::fs9AircraftDir() });
672  return md;
673  }
674  case CSimulatorInfo::FSX:
675  {
676  if (CFsDirectories::fsxSimObjectsDir().isEmpty()) { return e; }
677  static const QStringList md = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
678  return md;
679  }
680  case CSimulatorInfo::P3D:
681  {
682  static const QString p3d = CFsDirectories::p3dSimObjectsDir();
683  if (p3d.isEmpty()) { return e; }
684  static const QString versionHint = CFsDirectories::guessP3DVersion(p3d);
685  static const QStringList md = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(p3d, versionHint);
686  return md;
687  }
688  case CSimulatorInfo::MSFS:
689  {
690  static const QString msfs = CFileUtils::normalizeFilePathToQtStandard(CFsDirectories::msfsPackagesDir());
691  if (msfs.isEmpty()) { return e; }
692  static const QStringList md { msfs };
693  return md;
694  }
695  case CSimulatorInfo::MSFS2024:
696  {
697  static const QString msfs2024 =
698  CFileUtils::normalizeFilePathToQtStandard(CFsDirectories::msfs2024PackagesDir());
699  if (msfs2024.isEmpty()) { return e; }
700  static const QStringList md { msfs2024 };
701  return md;
702  }
703  case CSimulatorInfo::XPLANE:
704  {
705  return CXPlaneUtil::xplaneModelDirectories();
706  }
707  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
708  }
709  return e;
710  }
711 
713  {
714  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
715  static const QString empty;
716  switch (simulator.getSimulator())
717  {
718  case CSimulatorInfo::FG: return CFlightgearUtil::flightgearRootDir();
719  case CSimulatorInfo::FS9: return CFsDirectories::fs9Dir();
720  case CSimulatorInfo::FSX: return CFsDirectories::fsxDir();
721  case CSimulatorInfo::P3D: return CFsDirectories::p3dDir();
722  case CSimulatorInfo::MSFS: return CFsDirectories::msfsDir();
723  case CSimulatorInfo::MSFS2024: return CFsDirectories::msfs2024Dir();
724  case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneRootDir();
725  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
726  }
727  return empty;
728  }
729 
730  const QStringList &
732  {
733  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
734  static const QStringList empty;
735  switch (simulator.getSimulator())
736  {
737  case CSimulatorInfo::FG: return CFlightgearUtil::flightgearModelExcludeDirectoryPatterns();
738  case CSimulatorInfo::FS9: return CFsDirectories::fs9AircraftObjectsExcludeDirectoryPatterns();
739  case CSimulatorInfo::FSX: return CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns();
740  case CSimulatorInfo::P3D: return CFsDirectories::p3dSimObjectsExcludeDirectoryPatterns();
741  case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneModelExcludeDirectoryPatterns();
742  case CSimulatorInfo::MSFS: return CFsDirectories::msfs20SimObjectsExcludeDirectoryPatterns();
743  case CSimulatorInfo::MSFS2024: return CFsDirectories::msfs2024SimObjectsExcludeDirectoryPatterns();
744  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
745  }
746  return empty;
747  }
748 
750  {
752  CXPlaneUtil::xplanePluginPathName());
753  }
754 
755  QString CFsxP3DSettings::convertToQString(bool i18n) const
756  {
757  Q_UNUSED(i18n)
758  return u"SimulatedObject: " % boolToYesNo(m_useSimulatedObjectAdding) % u" SB offsets: " %
759  boolToYesNo(m_useSbOffsets);
760  }
761 
763  {
764  Q_UNUSED(index)
765  return {};
766  }
767 
768  void CFsxP3DSettings::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
769  {
770  Q_UNUSED(index)
771  Q_UNUSED(variant)
772  }
773 
775  {
776  Q_ASSERT_X(sim.isFsxP3DFamily(), Q_FUNC_INFO, "Only for FSX/P3D");
777  if (sim == CSimulatorInfo::p3d()) { return m_simP3D.get(); }
778  return m_simFsx.get();
779  }
780 
782  const CSimulatorInfo &simulator)
783  {
784  Q_ASSERT_X(simulator.isFsxP3DFamily(), Q_FUNC_INFO, "Only for FSX/P3D");
785  if (simulator == CSimulatorInfo::p3d()) { return m_simP3D.set(settings); }
786  return m_simFsx.set(settings);
787  }
788 
790  const CSimulatorInfo &simulator)
791  {
792  Q_ASSERT_X(simulator.isFsxP3DFamily(), Q_FUNC_INFO, "Only for FSX/P3D");
793  if (simulator == CSimulatorInfo::p3d()) { return m_simP3D.setAndSave(settings); }
794  return m_simFsx.setAndSave(settings);
795  }
796 
797  bool TSimulatorXP::isValid(const CSimulatorSettings &value, QString &reason)
798  {
799  const QString simDir = value.hasSimulatorDirectory() ?
800  value.getSimulatorDirectory() :
802  const CStatusMessageList msgs = CXPlaneUtil::validateModelDirectories(simDir, value.getModelDirectories());
803  if (msgs.isSuccess()) { return true; }
804  reason = msgs.getErrorMessages().toSingleMessage().toQString(true);
805  return false;
806  }
807 
808 } // namespace swift::misc::simulation::settings
static constexpr bool isRunningOnWindowsNtPlatform()
Running on Windows NT platform?
static bool sameDirectories(const QStringList &dirs1, const QStringList &dirs2, Qt::CaseSensitivity cs=osFileNameCaseSensitivity())
Same directories, order in list does not matter and lists are cleaned up.
Definition: fileutils.cpp:206
static QString appendFilePathsAndFixUnc(const QString &path1, const QString &path2)
Append file paths.
Definition: fileutils.cpp:108
static QString normalizeFilePathToQtStandard(const QString &filePath)
Normalize file path to Qt standard, e.g by turning \ to /.
Definition: fileutils.cpp:179
static const QString & settings()
Settings.
bool isEmpty() const
Message empty.
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.
Streamable status message, e.g.
constexpr static auto SeverityError
Status severities.
static const QString & severityToString(StatusSeverity severity)
Severity as string.
StatusSeverity getSeverity() const
Message severity.
constexpr static auto SeverityInfo
Status severities.
constexpr static auto SeverityWarning
Status severities.
Status messages, e.g. from Core -> GUI.
CStatusMessage toSingleMessage() const
Merge into a single message.
CStatusMessageList getErrorMessages() const
Get all error messages.
bool isSuccess() const
All messages are marked as success.
bool isActiveFrequencySameFrequency(const physical_quantities::CFrequency &comFrequency) const
Is active frequency the same frequency.
Definition: comsystem.cpp:53
ColumnIndex
Base class enums.
Definition: mixinindex.h:44
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
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:76
Value object encapsulating information of a text message.
Definition: textmessage.h:31
bool isPrivateMessage() const
Is private message?
Definition: textmessage.cpp:53
bool isEmpty() const
Empty message.
Definition: textmessage.h:90
bool isSendToUnicom() const
Send to UNICOM?
bool isRadioMessage() const
Is radio message?
const physical_quantities::CFrequency & getFrequency() const
Get frequency.
Definition: textmessage.h:96
bool isSupervisorMessage() const
Supervisor message?
Definition: textmessage.cpp:58
Physical unit length (length)
Definition: length.h:18
Comprehensive information of an aircraft.
const aviation::CComSystem & getCom2System() const
Get COM2 system.
const aviation::CComSystem & getCom1System() const
Get COM1 system.
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
bool isSingleSimulator() const
Single simulator selected.
Simulator getSimulator() const
Simulator.
static const CSimulatorInfo & msfs()
Const simulator info objects.
bool isFsxP3DFamily() const
FSX family, i.e. FSX or P3D?
static const CSimulatorInfo & fs9()
Const simulator info objects.
static const CSimulatorInfo & fsx()
Const simulator info objects.
static const CSimulatorInfo & p3d()
Const simulator info objects.
static const CSimulatorInfo & xplane()
Const simulator info objects.
static const CSimulatorInfo & msfs2024()
Const simulator info objects.
static const CSimulatorInfo & fg()
Const simulator info objects.
QString convertToQString(bool i18n=false) const
Cast as QString.
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
CFsxP3DSettings getSettings(const CSimulatorInfo &sim) const
Settings per simulator.
CStatusMessage setSettings(const CFsxP3DSettings &settings, const CSimulatorInfo &simulator)
Set settings per simulator.
CStatusMessage setAndSaveSettings(const CFsxP3DSettings &settings, const CSimulatorInfo &simulator)
Set settings per simulator.
CStatusMessage addModelDirectory(const QString &modelDirectory, const CSimulatorInfo &simulator)
Set model directory per simulator.
QString getFirstModelDirectoryOrDefault(const CSimulatorInfo &simulator) const
First model directoy.
void resetToDefaults(const CSimulatorInfo &simulator)
Reset to defaults.
CStatusMessage setAndSaveSettings(const CSimulatorSettings &settings, const CSimulatorInfo &simulator)
Set settings per simulator.
CStatusMessage saveSettings(const CSimulatorInfo &simulator)
Set settings per simulator.
CSpecializedSimulatorSettings getSpecializedSettings(const CSimulatorInfo &simulator) const
Specialized simulator settings.
CStatusMessageList setAndValidateSettings(const CSimulatorSettings &settings, const CSimulatorInfo &simulator)
Set settings per simulator, but do NOT save yet, but validate.
CStatusMessage setSettings(const CSimulatorSettings &settings, const CSimulatorInfo &simulator)
Set settings per simulator.
QStringList getModelDirectoriesIfNotDefault(const CSimulatorInfo &simulator) const
Model directory or or empty if default.
QString getSimulatorDirectoryIfNotDefault(const CSimulatorInfo &simulator) const
Simulator directory or empty if default dir.
QStringList getModelDirectoriesOrDefault(const CSimulatorInfo &simulator) const
Model directory or default model path per simulator.
const QStringList & defaultModelDirectories(const CSimulatorInfo &simulator) const
Default model path per simulator.
CSimulatorSettings getSettings(const CSimulatorInfo &simulator) const
Settings per simulator.
QStringList getModelExcludeDirectoryPatternsOrDefault(const CSimulatorInfo &simulator) const
Model exclude patterns per simulator.
QStringList getModelExcludeDirectoryPatternsIfNotDefault(const CSimulatorInfo &simulator) const
Model exclude patterns or empty if default.
CStatusMessage clearModelDirectories(const CSimulatorInfo &simulator)
Clear the model directory.
QString getSimulatorDirectoryOrDefault(const CSimulatorInfo &simulator) const
Simulator directory or default model path per simulator.
void settingsChanged(const swift::misc::simulation::CSimulatorInfo &simulator)
Simulator settings have been changed.
Settings regarding message handling. Driver independent part, related to network.
bool isRelayErrorsMessages() const
Relay (technical) error messages.
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
void setRelayGloballyEnabled(bool enabled)
Globally enable / disable.
bool isRelayWarningMessages() const
Relay (technical) warning messages.
QString convertToQString(bool i18n=false) const
Cast as QString.
CSimulatorMessagesSettings::TextMessageType getRelayedTextMessageTypes() const
Relayed text messages.
bool isRelayInfoMessages() const
Relay (technical) info messages.
bool relayThisTextMessage(const network::CTextMessage &msg, const CSimulatedAircraft &aircraft) const
Relay given text message.
bool relayThisStatusMessage(const CStatusMessage &message) const
Relay this particular message.
bool isRelaySupervisorTextMessages() const
Relay supervisor messages.
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
void setTechnicalLogSeverity(CStatusMessage::StatusSeverity severity)
Log severity.
void setRelayTextMessages(CSimulatorMessagesSettings::TextMessageType messageType)
Relay the following message types.
Settings for simulator Driver independent parts (such as directories), also used in model loaders.
void clearModelDirectories()
Clear the model directories.
bool hasSimulatorDirectory() const
Setting has simulator setting.
bool addModelDirectory(const QString &modelDirectory)
Add (if not exists) model directory.
bool hasModelDirectories() const
Having model directories?
bool hasModelExcludeDirectoryPatterns() const
Having model exclude directoy patterns?
CGSource
Where we get the CG (aka vertical offset) from.
const QStringList & getModelExcludeDirectoryPatterns() const
Model exclude directoy patterns.
const QString & getSimulatorDirectory() const
Simulator directory.
const QStringList & getModelDirectories() const
Model directory.
Allows to have specific utility functions for each simulator.
const QStringList & getModelExcludeDirectoryPatternsIfNotDefault() const
Model exclude patterns or empty if default.
static const QStringList & defaultModelDirectories(const CSimulatorInfo &simulator)
Default model path per simulator.
const QStringList & getDefaultModelDirectories() const
Model exclude patterns or empty if default.
const QStringList & getModelExcludeDirectoryPatternsOrDefault() const
Model exclude patterns or empty if default.
QStringList getModelDirectoriesFromSimulatorDirectoy() const
Model directories.
const QString & getSimulatorDirectoryIfNotDefault() const
Simulator directory or empty if default dir.
QStringList getModelDirectoriesOrDefault() const
Model directories or default.
const CSimulatorSettings & getGenericSettings() const
Get the generic settings.
const QStringList & getModelDirectoriesIfNotDefault() const
Model directories or empty if default.
QStringList getModelDirectoriesFromSimulatorDirectoryOrDefault() const
Model directories, then from simulator directory, then default.
const QStringList & getDefaultModelExcludeDirectoryPatterns() const
Default model exclude patterns.
static const QStringList & defaultModelExcludeDirectoryPatterns(const CSimulatorInfo &simulator)
Default model exclude patterns per simulator.
const QString & getSimulatorDirectoryOrDefault() const
Simulator directory or default path.
static const QString & defaultSimulatorDirectory(const CSimulatorInfo &simulator)
Default simulator path per simulator.
const QString & getDefaultSimulatorDirectory() const
Default simulator path per simulator.
QString getPluginDirOrDefault() const
Plugin directory or default plugin dir.
SWIFT_MISC_EXPORT const QString & boolToOnOff(bool v)
Bool to on/off.
StatusSeverity
Status severities.
Definition: statusmessage.h:35
SWIFT_MISC_EXPORT const QString & boolToYesNo(bool v)
Bool to yes/no.
static bool isValid(const CSimulatorSettings &value, QString &reason)
Validator function. Return true if the argument is valid, false otherwise. Default implementation jus...
#define SWIFT_DEFINE_VALUEOBJECT_MIXINS(Namespace, Class)
Explicit template definition of mixins for a CValueObject subclass.
Definition: valueobject.h:67
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26