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  void CSimulatorSettings::setSimulatorDirectory(const QString &simulatorDirectory)
48  {
49  m_simulatorDirectory = simulatorDirectory.trimmed();
50  }
51 
52  const QString &CSimulatorSettings::getSimulatorDirectory() const { return m_simulatorDirectory; }
53 
54  void CSimulatorSettings::setModelDirectories(const QStringList &modelDirectories)
55  {
56  m_modelDirectories = modelDirectories;
57  m_modelDirectories.removeAll({}); // empty values
58  m_modelDirectories.removeDuplicates(); // duplicates
59  }
60 
61  void CSimulatorSettings::clearModelDirectories() { m_modelDirectories.clear(); }
62 
63  void CSimulatorSettings::setModelDirectory(const QString &modelDirectory)
64  {
65  m_modelDirectories = QStringList({ modelDirectory });
66  }
67 
68  bool CSimulatorSettings::addModelDirectory(const QString &modelDirectory)
69  {
70  const Qt::CaseSensitivity cs =
72  if (m_modelDirectories.contains(modelDirectory, cs)) { return false; }
73  m_modelDirectories.push_back(modelDirectory);
74  m_modelDirectories.removeAll({});
75  m_modelDirectories.removeDuplicates();
76  return true;
77  }
78 
79  const QStringList &CSimulatorSettings::getModelDirectories() const { return m_modelDirectories; }
80 
81  void CSimulatorSettings::setModelExcludeDirectories(const QStringList &excludeDirectories)
82  {
83  m_excludeDirectoryPatterns = excludeDirectories;
84  m_excludeDirectoryPatterns.removeAll({});
85  m_excludeDirectoryPatterns.removeDuplicates();
86  }
87 
88  const QStringList &CSimulatorSettings::getModelExcludeDirectoryPatterns() const
89  {
90  return m_excludeDirectoryPatterns;
91  }
92 
93  bool CSimulatorSettings::setComIntegrated(bool integrated)
94  {
95  if (integrated == m_comIntegration) { return false; }
96  m_comIntegration = integrated;
97  return true;
98  }
99 
100  bool CSimulatorSettings::setCGSource(CSimulatorSettings::CGSource source)
101  {
102  const int s = static_cast<int>(source);
103  if (m_cgSource == s) { return false; }
104  m_cgSource = s;
105  return true;
106  }
107 
108  bool CSimulatorSettings::setRecordOwnAircraftGnd(bool record)
109  {
110  if (record == m_recordGnd) { return false; }
111  m_recordGnd = record;
112  return true;
113  }
114 
115  bool CSimulatorSettings::setRecordedGndRadius(const CLength &radius)
116  {
117  if (radius == m_recordedGndRadius) { return false; }
118  m_recordedGndRadius = radius;
119  return true;
120  }
121 
122  void CSimulatorSettings::resetPaths()
123  {
124  m_excludeDirectoryPatterns.clear();
125  m_modelDirectories.clear();
126  m_simulatorDirectory.clear();
127  }
128 
129  QString CSimulatorSettings::convertToQString(bool i18n) const { return convertToQString(", ", i18n); }
130 
131  QString CSimulatorSettings::convertToQString(const QString &separator, bool i18n) const
132  {
133  Q_UNUSED(i18n)
134  return u"model directories: " % m_modelDirectories.join(',') % separator % u"exclude directories: " %
135  m_excludeDirectoryPatterns.join(',');
136  }
137 
138  QVariant CSimulatorSettings::propertyByIndex(CPropertyIndexRef index) const
139  {
140  if (index.isMyself()) { return QVariant::fromValue(*this); }
141  const auto i = index.frontCasted<ColumnIndex>();
142  switch (i)
143  {
144  case IndexSimulatorDirectory: return QVariant::fromValue(m_simulatorDirectory);
145  case IndexModelDirectories: return QVariant::fromValue(m_modelDirectories);
146  case IndexModelExcludeDirectoryPatterns: return QVariant::fromValue(m_excludeDirectoryPatterns);
147  case IndexComIntegration: return QVariant::fromValue(m_comIntegration);
148  case IndexRecordOwnAircraftGnd: return QVariant::fromValue(m_recordGnd);
149  case IndexCGSource: return QVariant::fromValue(m_cgSource);
150  case IndexRecordOwnAircraftGndRadius: return m_recordedGndRadius.propertyByIndex(index.copyFrontRemoved());
151  default: return CValueObject::propertyByIndex(index);
152  }
153  }
154 
155  void CSimulatorSettings::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
156  {
157  if (index.isMyself())
158  {
159  (*this) = variant.value<CSimulatorSettings>();
160  return;
161  }
162  const auto i = index.frontCasted<ColumnIndex>();
163  switch (i)
164  {
165  case IndexSimulatorDirectory: this->setSimulatorDirectory(variant.toString()); break;
166  case IndexModelDirectories: this->setModelDirectories(variant.toStringList()); break;
167  case IndexComIntegration: this->setComIntegrated(variant.toBool()); break;
168  case IndexRecordOwnAircraftGnd: this->setRecordOwnAircraftGnd(variant.toBool()); break;
169  case IndexModelExcludeDirectoryPatterns: m_excludeDirectoryPatterns = variant.value<QStringList>(); break;
170  case IndexCGSource: m_cgSource = variant.toInt(); break;
171  case IndexRecordOwnAircraftGndRadius:
172  m_recordedGndRadius.setPropertyByIndex(index.copyFrontRemoved(), variant);
173  break;
174  default: CValueObject::setPropertyByIndex(index, variant); break;
175  }
176  }
177 
178  CMultiSimulatorSettings::CMultiSimulatorSettings(QObject *parent) : QObject(parent)
179  {
180  // void
181  }
182 
184  {
185  if (!simulator.isSingleSimulator())
186  {
187  // mostly happening with emulated driver, VERIFY for better debugging
188  SWIFT_VERIFY_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
189  return {};
190  }
191  switch (simulator.getSimulator())
192  {
193  case CSimulatorInfo::FG: return m_simSettingsFG.get();
194  case CSimulatorInfo::FS9: return m_simSettingsFs9.get();
195  case CSimulatorInfo::FSX: return m_simSettingsFsx.get();
196  case CSimulatorInfo::P3D: return m_simSettingsP3D.get();
197  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.get();
198  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.get();
199  case CSimulatorInfo::XPLANE: return m_simSettingsXP.get();
200 
201  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
202  }
203  return {};
204  }
205 
207  {
208  return { this->getSettings(simulator), simulator };
209  }
210 
212  const CSimulatorInfo &simulator)
213  {
214  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
215  switch (simulator.getSimulator())
216  {
217  case CSimulatorInfo::FG: return m_simSettingsFG.set(settings);
218  case CSimulatorInfo::FS9: return m_simSettingsFs9.set(settings);
219  case CSimulatorInfo::FSX: return m_simSettingsFsx.set(settings);
220  case CSimulatorInfo::P3D: return m_simSettingsP3D.set(settings);
221  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.set(settings);
222  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.set(settings);
223  case CSimulatorInfo::XPLANE: return m_simSettingsXP.set(settings);
224  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
225  }
226  return CStatusMessage({ CLogCategories::settings() }, CStatusMessage::SeverityError, u"wrong simulator");
227  }
228 
230  const CSimulatorInfo &simulator)
231  {
232  CSimulatorSettings s = this->getSettings(simulator);
233  if (!s.addModelDirectory(modelDirectory))
234  {
236  u"directory already existing");
237  }
238  return this->setSettings(s, simulator);
239  }
240 
242  {
243  CSimulatorSettings s = this->getSettings(simulator);
245  return this->setSettings(s, simulator);
246  }
247 
249  const CSimulatorInfo &simulator)
250  {
251  this->setSettings(settings, simulator);
252  CStatusMessageList msgs;
253  switch (simulator.getSimulator())
254  {
255  case CSimulatorInfo::FG: break;
256  case CSimulatorInfo::FS9: break;
257  case CSimulatorInfo::FSX: break;
258  case CSimulatorInfo::P3D: break;
259  case CSimulatorInfo::MSFS: break;
260  case CSimulatorInfo::MSFS2024: break;
261  case CSimulatorInfo::XPLANE:
262  {
263  if (settings.hasModelDirectories())
264  {
265  const QString simDir = this->getSimulatorDirectoryOrDefault(simulator);
266  msgs = CXPlaneUtil::validateModelDirectories(simDir, settings.getModelDirectories());
267  }
268  }
269  break;
270  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
271  }
272  return msgs;
273  }
274 
276  const CSimulatorInfo &simulator)
277  {
278  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
279  switch (simulator.getSimulator())
280  {
281  case CSimulatorInfo::FG: return m_simSettingsFG.setAndSave(settings);
282  case CSimulatorInfo::FS9: return m_simSettingsFs9.setAndSave(settings);
283  case CSimulatorInfo::FSX: return m_simSettingsFsx.setAndSave(settings);
284  case CSimulatorInfo::P3D: return m_simSettingsP3D.setAndSave(settings);
285  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.setAndSave(settings);
286  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.setAndSave(settings);
287  case CSimulatorInfo::XPLANE: return m_simSettingsXP.setAndSave(settings);
288  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
289  }
290  return CStatusMessage({ CLogCategories::settings() }, CStatusMessage::SeverityError, u"wrong simulator");
291  }
292 
294  const CSimulatorInfo &simulator)
295  {
296  return this->setAndSaveSettings(settings.getGenericSettings(), simulator);
297  }
298 
300  {
301  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
302  switch (simulator.getSimulator())
303  {
304  case CSimulatorInfo::FG: return m_simSettingsFG.save();
305  case CSimulatorInfo::FS9: return m_simSettingsFs9.save();
306  case CSimulatorInfo::FSX: return m_simSettingsFsx.save();
307  case CSimulatorInfo::P3D: return m_simSettingsP3D.save();
308  case CSimulatorInfo::MSFS: return m_simSettingsMsfs.save();
309  case CSimulatorInfo::MSFS2024: return m_simSettingsMsfs2024.save();
310  case CSimulatorInfo::XPLANE: return m_simSettingsXP.save();
311  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
312  }
313  return CStatusMessage({ CLogCategories::settings() }, CStatusMessage::SeverityError, u"wrong simulator");
314  }
315 
317  {
318  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
320  }
321 
323  {
324  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
326  }
327 
329  {
330  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
331  return s.getModelDirectoriesOrDefault();
332  }
333 
335  {
336  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
338  }
339 
341  {
342  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
344  }
345 
348  {
349  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
351  }
352 
355  {
356  const CSpecializedSimulatorSettings s = this->getSpecializedSettings(simulator);
358  }
359 
361  {
362  CSimulatorSettings s = this->getSettings(simulator);
363  s.resetPaths();
364  this->setAndSaveSettings(s, simulator);
365  }
366 
368  {
370  }
371 
372  void CMultiSimulatorSettings::onFsxSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::fsx()); }
373 
374  void CMultiSimulatorSettings::onP3DSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::p3d()); }
375 
376  void CMultiSimulatorSettings::onFs9SettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::fs9()); }
377 
378  void CMultiSimulatorSettings::onMsfsSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::msfs()); }
379 
380  void CMultiSimulatorSettings::onMsfs2024SettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::msfs2024()); }
381 
382  void CMultiSimulatorSettings::onXPSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::xplane()); }
383 
384  void CMultiSimulatorSettings::onFGSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::fg()); }
385 
386  void CMultiSimulatorSettings::emitSettingsChanged(const CSimulatorInfo &simInfo)
387  {
388  emit this->settingsChanged(simInfo);
389  }
390 
392  {
393  m_technicalLogLevel = static_cast<int>(severity);
394  }
395 
396  void CSimulatorMessagesSettings::disableTechnicalMessages() { m_technicalLogLevel = -1; }
397 
399  {
400  if (m_technicalLogLevel < 0) { return false; }
401  return (m_technicalLogLevel <= CStatusMessage::SeverityError);
402  }
403 
405  {
406  if (m_technicalLogLevel < 0) { return false; }
407  return (m_technicalLogLevel <= CStatusMessage::SeverityWarning);
408  }
409 
411  {
412  if (m_technicalLogLevel < 0) { return false; }
413  return (m_technicalLogLevel <= CStatusMessage::SeverityInfo);
414  }
415 
416  bool CSimulatorMessagesSettings::isRelayTechnicalMessages() const { return (m_technicalLogLevel >= 0); }
417 
418  void CSimulatorMessagesSettings::setRelayTextMessages(CSimulatorMessagesSettings::TextMessageType messageType)
419  {
420  m_messageType = static_cast<int>(messageType);
421  }
422 
424  {
425  return this->getRelayedTextMessageTypes().testFlag(TextMessageSupervisor);
426  }
427 
429  {
430  return this->getRelayedTextMessageTypes().testFlag(TextMessagePrivate);
431  }
432 
434  {
435  return this->getRelayedTextMessageTypes().testFlag(TextMessagesUnicom);
436  }
437 
439  {
440  return this->getRelayedTextMessageTypes().testFlag(TextMessagesCom1);
441  }
442 
444  {
445  return this->getRelayedTextMessageTypes().testFlag(TextMessagesCom2);
446  }
447 
449  {
450  if (message.isEmpty()) { return false; }
451  if (!this->isRelayGloballyEnabled()) { return false; }
452  if (!this->isRelayTechnicalMessages()) { return false; }
453  const int s = static_cast<int>(message.getSeverity());
454  return (s >= m_technicalLogLevel);
455  }
456 
457  bool
459  const swift::misc::simulation::CSimulatedAircraft &aircraft) const
460  {
461  if (msg.isEmpty()) { return false; }
462  if (!this->isRelayGloballyEnabled()) { return false; }
463  if (m_messageType == NoTextMessages) { return false; }
464 
465  const TextMessageType mt = static_cast<TextMessageType>(m_messageType);
466  if (msg.isPrivateMessage() && mt.testFlag(TextMessagePrivate)) { return true; }
467  if (msg.isSupervisorMessage() && (mt.testFlag(TextMessagePrivate) || mt.testFlag(TextMessageSupervisor)))
468  {
469  return true;
470  }
471  if (msg.isSendToUnicom() && mt.testFlag(TextMessagesUnicom)) { return true; }
472 
473  if (msg.isRadioMessage())
474  {
475  const CFrequency f(msg.getFrequency());
476  if (mt.testFlag(TextMessagesCom1))
477  {
478  if (aircraft.getCom1System().isActiveFrequencySameFrequency(f)) { return true; }
479  }
480  if (mt.testFlag(TextMessagesCom2))
481  {
482  if (aircraft.getCom2System().isActiveFrequencySameFrequency(f)) { return true; }
483  }
484  }
485  return false;
486  }
487 
488  CSimulatorMessagesSettings::TextMessageType CSimulatorMessagesSettings::getRelayedTextMessageTypes() const
489  {
490  return static_cast<CSimulatorMessagesSettings::TextMessageType>(m_messageType);
491  }
492 
494  {
495  Q_UNUSED(i18n)
496  static const QString s("Enabled %1, text messages: %2, severity: %3");
497  QString severity;
498  if (this->isRelayTechnicalMessages()) { severity = QStringLiteral("No tech. msgs"); }
499  else
500  {
501  severity =
502  CStatusMessage::severityToString(static_cast<CStatusMessage::StatusSeverity>(m_technicalLogLevel));
503  }
504  return s.arg(boolToOnOff(m_relayGloballyEnabled)).arg(m_messageType).arg(severity);
505  }
506 
508  {
509  if (index.isMyself()) { return QVariant::fromValue(*this); }
510  const auto i = index.frontCasted<ColumnIndex>();
511  switch (i)
512  {
513  case IndexTechnicalLogSeverity: return QVariant::fromValue(m_technicalLogLevel);
514  case IndexRelayTextMessage: return QVariant::fromValue(m_messageType);
515  case IndexRelayGloballyEnabled: return QVariant::fromValue(m_relayGloballyEnabled);
516  default: return CValueObject::propertyByIndex(index);
517  }
518  }
519 
521  {
522  if (index.isMyself())
523  {
524  (*this) = variant.value<CSimulatorMessagesSettings>();
525  return;
526  }
527  const auto i = index.frontCasted<ColumnIndex>();
528  switch (i)
529  {
530  case IndexTechnicalLogSeverity:
531  this->setTechnicalLogSeverity(static_cast<CStatusMessage::StatusSeverity>(variant.toInt()));
532  break;
533  case IndexRelayTextMessage:
534  this->setRelayTextMessages(static_cast<CSimulatorMessagesSettings::TextMessageType>(variant.toInt()));
535  break;
536  case IndexRelayGloballyEnabled: this->setRelayGloballyEnabled(variant.toBool()); break;
537  default: CValueObject::setPropertyByIndex(index, variant); break;
538  }
539  }
540 
542  {
544  }
545 
547  {
548  static const QString empty;
549  if (!m_genericSettings.hasSimulatorDirectory()) { return empty; }
552  {
553  return empty;
554  }
556  }
557 
559  {
563  }
564 
566  {
569  }
570 
572  {
573  if (!m_genericSettings.hasSimulatorDirectory()) { return {}; }
575  QStringList dirs;
576  switch (m_simulator.getSimulator())
577  {
578  case CSimulatorInfo::FG: dirs = QStringList(CFlightgearUtil::modelDirectoriesFromSimDir(s)); break;
579  case CSimulatorInfo::FS9: dirs = QStringList({ CFsDirectories::fs9AircraftDirFromSimDir(s) }); break;
580  case CSimulatorInfo::FSX:
581  dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(
582  CFsDirectories::fsxSimObjectsDirFromSimDir(s));
583  break;
584  case CSimulatorInfo::P3D:
585  {
586  const QString versionHint = CFsDirectories::guessP3DVersion(s);
587  dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(
588  CFsDirectories::p3dSimObjectsDirFromSimDir(s), versionHint);
589  }
590  break;
591  case CSimulatorInfo::XPLANE: dirs = QStringList({ CXPlaneUtil::modelDirectoriesFromSimDir(s) }); break;
592  case CSimulatorInfo::MSFS: dirs = QStringList({ CFsDirectories::msfsSimObjectsDir() }); break;
593  case CSimulatorInfo::MSFS2024: dirs = QStringList({ CFsDirectories::msfs2024SimObjectsDir() }); break;
594  default: break;
595  }
596 
597  dirs.removeAll({}); // remove empty
598  dirs.removeDuplicates();
599  return dirs;
600  }
601 
603  {
605  {
607  }
609  }
610 
612  {
613  static const QStringList empty;
614  if (!m_genericSettings.hasModelDirectories()) { return empty; }
616  if (CFileUtils::sameDirectories(m_genericSettings.getModelDirectories(), defaultDirectories)) { return empty; }
618  }
619 
621  {
623  }
624 
626  {
627  static const QString empty;
628  if (this->getModelDirectoriesOrDefault().isEmpty()) { return empty; }
629  return this->getModelDirectoriesOrDefault().constFirst();
630  }
631 
633  {
635  }
636 
638  {
639  static const QStringList empty;
640  if (!m_genericSettings.hasModelExcludeDirectoryPatterns()) { return empty; }
643  {
644  return empty;
645  }
647  }
648 
650  {
654  }
655 
657  {
658  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
659  static const QStringList e;
660  switch (simulator.getSimulator())
661  {
662  case CSimulatorInfo::FG:
663  {
664  return CFlightgearUtil::flightgearModelDirectories();
665  }
666  case CSimulatorInfo::FS9:
667  {
668  if (CFsDirectories::fs9AircraftDir().isEmpty()) { return e; }
669  static const QStringList md({ CFsDirectories::fs9AircraftDir() });
670  return md;
671  }
672  case CSimulatorInfo::FSX:
673  {
674  if (CFsDirectories::fsxSimObjectsDir().isEmpty()) { return e; }
675  static const QStringList md = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
676  return md;
677  }
678  case CSimulatorInfo::P3D:
679  {
680  static const QString p3d = CFsDirectories::p3dSimObjectsDir();
681  if (p3d.isEmpty()) { return e; }
682  static const QString versionHint = CFsDirectories::guessP3DVersion(p3d);
683  static const QStringList md = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(p3d, versionHint);
684  return md;
685  }
686  case CSimulatorInfo::MSFS:
687  {
688  static const QString msfs = CFileUtils::normalizeFilePathToQtStandard(CFsDirectories::msfsPackagesDir());
689  if (msfs.isEmpty()) { return e; }
690  static const QStringList md { msfs };
691  return md;
692  }
693  case CSimulatorInfo::MSFS2024:
694  {
695  static const QString msfs2024 =
696  CFileUtils::normalizeFilePathToQtStandard(CFsDirectories::msfs2024PackagesDir());
697  if (msfs2024.isEmpty()) { return e; }
698  static const QStringList md { msfs2024 };
699  return md;
700  }
701  case CSimulatorInfo::XPLANE:
702  {
703  return CXPlaneUtil::xplaneModelDirectories();
704  }
705  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
706  }
707  return e;
708  }
709 
711  {
712  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
713  static const QString empty;
714  switch (simulator.getSimulator())
715  {
716  case CSimulatorInfo::FG: return CFlightgearUtil::flightgearRootDir();
717  case CSimulatorInfo::FS9: return CFsDirectories::fs9Dir();
718  case CSimulatorInfo::FSX: return CFsDirectories::fsxDir();
719  case CSimulatorInfo::P3D: return CFsDirectories::p3dDir();
720  case CSimulatorInfo::MSFS: return CFsDirectories::msfsDir();
721  case CSimulatorInfo::MSFS2024: return CFsDirectories::msfs2024Dir();
722  case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneRootDir();
723  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
724  }
725  return empty;
726  }
727 
728  const QStringList &
730  {
731  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
732  static const QStringList empty;
733  switch (simulator.getSimulator())
734  {
735  case CSimulatorInfo::FG: return CFlightgearUtil::flightgearModelExcludeDirectoryPatterns();
736  case CSimulatorInfo::FS9: return CFsDirectories::fs9AircraftObjectsExcludeDirectoryPatterns();
737  case CSimulatorInfo::FSX: return CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns();
738  case CSimulatorInfo::P3D: return CFsDirectories::p3dSimObjectsExcludeDirectoryPatterns();
739  case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneModelExcludeDirectoryPatterns();
740  case CSimulatorInfo::MSFS: return CFsDirectories::msfs20SimObjectsExcludeDirectoryPatterns();
741  case CSimulatorInfo::MSFS2024: return CFsDirectories::msfs2024SimObjectsExcludeDirectoryPatterns();
742  default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break;
743  }
744  return empty;
745  }
746 
748  {
750  CXPlaneUtil::xplanePluginPathName());
751  }
752 
754  {
755  Q_UNUSED(i18n)
756  return u"SimulatedObject: " % boolToYesNo(m_useSimulatedObjectAdding) % u" SB offsets: " %
757  boolToYesNo(m_useSbOffsets);
758  }
759 
761  {
762  Q_UNUSED(index)
763  return {};
764  }
765 
767  {
768  Q_UNUSED(index)
769  Q_UNUSED(variant)
770  }
771 
773  {
774  Q_ASSERT_X(sim.isFsxP3DFamily(), Q_FUNC_INFO, "Only for FSX/P3D");
775  if (sim == CSimulatorInfo::p3d()) { return m_simP3D.get(); }
776  return m_simFsx.get();
777  }
778 
780  const CSimulatorInfo &simulator)
781  {
782  Q_ASSERT_X(simulator.isFsxP3DFamily(), Q_FUNC_INFO, "Only for FSX/P3D");
783  if (simulator == CSimulatorInfo::p3d()) { return m_simP3D.set(settings); }
784  return m_simFsx.set(settings);
785  }
786 
788  const CSimulatorInfo &simulator)
789  {
790  Q_ASSERT_X(simulator.isFsxP3DFamily(), Q_FUNC_INFO, "Only for FSX/P3D");
791  if (simulator == CSimulatorInfo::p3d()) { return m_simP3D.setAndSave(settings); }
792  return m_simFsx.setAndSave(settings);
793  }
794 
796  {
797  const QString simDir = value.hasSimulatorDirectory() ?
798  value.getSimulatorDirectory() :
800  const CStatusMessageList msgs = CXPlaneUtil::validateModelDirectories(simDir, value.getModelDirectories());
801  if (msgs.isSuccess()) { return true; }
802  reason = msgs.getErrorMessages().toSingleMessage().toQString(true);
803  return false;
804  }
805 
806 } // 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:158
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
Definition: mixinindex.h:165
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:74
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.
const T & constFirst() const const
qsizetype removeAll(const AT &t)
QString arg(Args &&... args) const const
bool isEmpty() const const
QString trimmed() const const
qsizetype removeDuplicates()
CaseSensitivity
QVariant fromValue(T &&value)
bool toBool() const const
int toInt(bool *ok) const const
QString toString() const const
QStringList toStringList() const const
T value() const &const
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