From 5799e31d27c0d093473693ba45b0a559c84f758a Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sat, 13 Jul 2019 03:41:17 +0200 Subject: [PATCH] XPlane sub directory check (model dirs in XPlane dir), unified with settings is valid --- .../simulation/settings/simulatorsettings.cpp | 55 ++++++++++++++++--- .../simulation/settings/simulatorsettings.h | 35 +++++------- .../simulation/xplane/xplaneutil.cpp | 33 ++++++++++- src/blackmisc/simulation/xplane/xplaneutil.h | 9 ++- 4 files changed, 99 insertions(+), 33 deletions(-) diff --git a/src/blackmisc/simulation/settings/simulatorsettings.cpp b/src/blackmisc/simulation/settings/simulatorsettings.cpp index 0ae61deeb..45261c905 100644 --- a/src/blackmisc/simulation/settings/simulatorsettings.cpp +++ b/src/blackmisc/simulation/settings/simulatorsettings.cpp @@ -63,8 +63,8 @@ namespace BlackMisc void CSimulatorSettings::setModelDirectories(const QStringList &modelDirectories) { m_modelDirectories = modelDirectories; - m_modelDirectories.removeAll({}); - m_modelDirectories.removeDuplicates(); + m_modelDirectories.removeAll({}); // empty values + m_modelDirectories.removeDuplicates(); // duplicates } void CSimulatorSettings::clearModelDirectories() @@ -256,6 +256,32 @@ namespace BlackMisc return this->setSettings(s, simulator); } + CStatusMessageList CMultiSimulatorSettings::setAndValidateSettings(const CSimulatorSettings &settings, const CSimulatorInfo &simulator) + { + this->setSettings(settings, simulator); + CStatusMessageList msgs; + switch (simulator.getSimulator()) + { + case CSimulatorInfo::FG: break; + case CSimulatorInfo::FS9: break; + case CSimulatorInfo::FSX: break; + case CSimulatorInfo::P3D: break; + case CSimulatorInfo::XPLANE: + { + if (settings.hasModelDirectories()) + { + const QString simDir = this->getSimulatorDirectoryOrDefault(simulator); + msgs = CXPlaneUtil::validateModelDirectories(simDir, settings.getModelDirectories()); + } + } + break; + default: + Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); + break; + } + return msgs; + } + CStatusMessage CMultiSimulatorSettings::setAndSaveSettings(const CSimulatorSettings &settings, const CSimulatorInfo &simulator) { Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); @@ -445,7 +471,7 @@ namespace BlackMisc bool CSimulatorMessagesSettings::relayThisStatusMessage(const CStatusMessage &message) const { if (message.isEmpty()) { return false; } - if (!this->isGloballyEnabled()) { return false; } + if (!this->isRelayGloballyEnabled()) { return false; } if (!this->isRelayTechnicalMessages()) { return false; } const int s = static_cast(message.getSeverity()); return (s >= m_technicalLogLevel); @@ -454,7 +480,7 @@ namespace BlackMisc bool CSimulatorMessagesSettings::relayThisTextMessage(const Network::CTextMessage &msg, const BlackMisc::Simulation::CSimulatedAircraft &aircraft) const { if (msg.isEmpty()) { return false; } - if (!this->isGloballyEnabled()) { return false; } + if (!this->isRelayGloballyEnabled()) { return false; } if (m_messageType == NoTextMessages) { return false; } const TextMessageType mt = static_cast(m_messageType); @@ -495,7 +521,7 @@ namespace BlackMisc { severity = CStatusMessage::severityToString(static_cast(m_technicalLogLevel)); } - return s.arg(boolToOnOff(m_globallyEnabled)).arg(m_messageType).arg(severity); + return s.arg(boolToOnOff(m_relayGloballyEnabled)).arg(m_messageType).arg(severity); } CVariant CSimulatorMessagesSettings::propertyByIndex(const CPropertyIndex &index) const @@ -505,8 +531,8 @@ namespace BlackMisc switch (i) { case IndexTechnicalLogSeverity: return CVariant::fromValue(m_technicalLogLevel); - case IndexTextMessageRelay: return CVariant::from(m_messageType); - case IndexGloballyEnabled: return CVariant::from(m_globallyEnabled); + case IndexRelayTextMessage: return CVariant::from(m_messageType); + case IndexRelayGloballyEnabled: return CVariant::from(m_relayGloballyEnabled); default: return CValueObject::propertyByIndex(index); } } @@ -518,8 +544,8 @@ namespace BlackMisc switch (i) { case IndexTechnicalLogSeverity: this->setTechnicalLogSeverity(static_cast(variant.toInt())); break; - case IndexTextMessageRelay: this->setRelayTextMessages(static_cast(variant.toInt())); break; - case IndexGloballyEnabled: this->setGloballyEnabled(variant.toBool()); break; + case IndexRelayTextMessage: this->setRelayTextMessages(static_cast(variant.toInt())); break; + case IndexRelayGloballyEnabled: this->setRelayGloballyEnabled(variant.toBool()); break; default: CValueObject::setPropertyByIndex(index, variant); break; } } @@ -747,6 +773,17 @@ namespace BlackMisc if (simulator == CSimulatorInfo::p3d()) { return m_simP3D.setAndSave(settings); } return m_simFsx.setAndSave(settings); } + + bool TSimulatorXP::isValid(const CSimulatorSettings &value, QString &reason) + { + const QString simDir = value.hasSimulatorDirectory() ? value.getSimulatorDirectory() + : CSpecializedSimulatorSettings::defaultSimulatorDirectory(CSimulatorInfo::XPLANE); + const CStatusMessageList msgs = CXPlaneUtil::validateModelDirectories(simDir, value.getModelDirectories()); + if (msgs.isSuccess()) { return true; } + reason = msgs.getErrorMessages().toSingleMessage().toQString(true); + return false; + } + } // ns } // ns } // ns diff --git a/src/blackmisc/simulation/settings/simulatorsettings.h b/src/blackmisc/simulation/settings/simulatorsettings.h index 5195fbd51..a6bfc59e6 100644 --- a/src/blackmisc/simulation/settings/simulatorsettings.h +++ b/src/blackmisc/simulation/settings/simulatorsettings.h @@ -380,7 +380,7 @@ namespace BlackMisc }; //! Trait for simulator settings - struct TSimulatorXP : public TSettingTrait + struct BLACKMISC_EXPORT TSimulatorXP : public TSettingTrait { //! \copydoc BlackMisc::TSettingTrait::key static const char *key() { return "settingssimulatorxplane"; } @@ -389,20 +389,7 @@ namespace BlackMisc static const QString &humanReadable() { static const QString name("XPlane settings"); return name; } //! \copydoc BlackMisc::TSettingTrait::isValid - static bool isValid(const CSimulatorSettings &value, QString &reason) - { - const QString simDir = value.hasSimulatorDirectory() ? value.getSimulatorDirectory() - : CSpecializedSimulatorSettings::defaultSimulatorDirectory(CSimulatorInfo::XPLANE); - for (const QString &modelDir : value.getModelDirectories()) - { - if (!CDirectoryUtils::isSubDirectoryOf(modelDir, simDir)) - { - reason = QStringLiteral("Model directory must be within the simulator directory structure"); - return false; - } - } - return true; - } + static bool isValid(const CSimulatorSettings &value, QString &reason); }; //! Trait for simulator settings @@ -457,6 +444,10 @@ namespace BlackMisc //! Clear the model directory CStatusMessage clearModelDirectories(const CSimulatorInfo &simulator); + //! Set settings per simulator, but do NOT save yet, but validate + //! \remark can be simulator specific + CStatusMessageList setAndValidateSettings(const CSimulatorSettings &settings, const CSimulatorInfo &simulator); + //! Set settings per simulator CStatusMessage setAndSaveSettings(const CSimulatorSettings &settings, const CSimulatorInfo &simulator); @@ -533,8 +524,8 @@ namespace BlackMisc enum ColumnIndex { IndexTechnicalLogSeverity = CPropertyIndex::GlobalIndexCSimulatorMessageSettings, - IndexTextMessageRelay, - IndexGloballyEnabled + IndexRelayTextMessage, + IndexRelayGloballyEnabled }; //! Enabled matching mode flags @@ -557,10 +548,10 @@ namespace BlackMisc void setTechnicalLogSeverity(CStatusMessage::StatusSeverity severity); //! Globally enable / disable - void setGloballyEnabled(bool enabled) { m_globallyEnabled = enabled; } + void setRelayGloballyEnabled(bool enabled) { m_relayGloballyEnabled = enabled; } //! Globally enabled? - bool isGloballyEnabled() const { return m_globallyEnabled; } + bool isRelayGloballyEnabled() const { return m_relayGloballyEnabled; } //! No technical messages void disableTechnicalMessages(); @@ -614,9 +605,9 @@ namespace BlackMisc void setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant); private: - int m_technicalLogLevel = CStatusMessage::SeverityError; //!< Simulator directory - int m_messageType = static_cast(TextMessagePrivate | TextMessageSupervisor); - bool m_globallyEnabled = true; //!< messsage relay enabled to simulator + int m_technicalLogLevel = CStatusMessage::SeverityError; //!< log level + int m_messageType = static_cast(TextMessagePrivate | TextMessageSupervisor); + bool m_relayGloballyEnabled = true; //!< messsage relay enabled to simulator BLACK_METACLASS( CSimulatorMessagesSettings, diff --git a/src/blackmisc/simulation/xplane/xplaneutil.cpp b/src/blackmisc/simulation/xplane/xplaneutil.cpp index 22525ceb9..5acf7e4e6 100644 --- a/src/blackmisc/simulation/xplane/xplaneutil.cpp +++ b/src/blackmisc/simulation/xplane/xplaneutil.cpp @@ -17,7 +17,7 @@ #include #if defined(Q_OS_WIN) -#include +#include #endif using namespace BlackMisc; @@ -28,6 +28,12 @@ namespace BlackMisc { namespace XPlane { + const CLogCategoryList &CXPlaneUtil::getLogCategories() + { + static const CLogCategoryList cats { CLogCategory::matching() }; + return cats; + } + // Returns the last path from filePath, which does exist on the file system QString getLastExistingPathFromFile(const QString &filePath) { @@ -277,6 +283,31 @@ namespace BlackMisc static const QStringList filter({"*.xpl"}); return filter; } + + CStatusMessageList CXPlaneUtil::validateModelDirectories(const QString &simDir, const QStringList &modelDirectories) + { + if (simDir.isEmpty()) + { + return CStatusMessage(getLogCategories(), CStatusMessage::SeverityWarning, u"no simulator directory", true); + } + + CStatusMessageList msgs; + if (modelDirectories.isEmpty()) { return msgs; } + const QDir sd(simDir); + const bool simDirExists = sd.exists(); + for (const QString &modelDir : modelDirectories) + { + const bool exists = simDirExists ? + CDirectoryUtils::isSameOrSubDirectoryOf(modelDir, sd) : + CDirectoryUtils::isSameOrSubDirectoryOfStringBased(modelDir, sd.absolutePath()); + const CStatusMessage m = exists ? + CStatusMessage(getLogCategories()).info(u"Model directory '%1' inside '%2'") << modelDir << sd.absolutePath() : + CStatusMessage(getLogCategories()).error(u"Model directory '%1' NOT inside '%2'") << modelDir << sd.absolutePath(); + msgs.push_back(m); + } + msgs.addValidationCategory(); + return msgs; + } } // namespace } // namespace } // namespace diff --git a/src/blackmisc/simulation/xplane/xplaneutil.h b/src/blackmisc/simulation/xplane/xplaneutil.h index 4879917b9..b6ac8210e 100644 --- a/src/blackmisc/simulation/xplane/xplaneutil.h +++ b/src/blackmisc/simulation/xplane/xplaneutil.h @@ -11,8 +11,9 @@ #ifndef BLACKMISC_SIMULATION_XPLANE_XPLANEUTIL_H #define BLACKMISC_SIMULATION_XPLANE_XPLANEUTIL_H +#include "blackmisc/logcategorylist.h" +#include "blackmisc/statusmessagelist.h" #include "blackmisc/blackmiscexport.h" - #include namespace BlackMisc @@ -28,6 +29,9 @@ namespace BlackMisc //! Constructor CXPlaneUtil() = delete; + //! Log categories + static const CLogCategoryList &getLogCategories(); + //! XPlane 9 directory static QString xplane9Dir(); @@ -99,6 +103,9 @@ namespace BlackMisc //! Filter filter for xpl files static const QStringList &xplFileFilter(); + //! Validate the model directories + static CStatusMessageList validateModelDirectories(const QString &simDir, const QStringList &modelDirectories); + private: //! Concatenates dirs for used OS static QString xplaneDir(const QString &xplaneInstallFile);