diff --git a/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp b/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp index 55c9c8e61..c432176e4 100644 --- a/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp +++ b/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp @@ -21,6 +21,11 @@ namespace BlackMisc { namespace FsCommon { + CAircraftCfgParser::~CAircraftCfgParser() + { + // that should be safe as long as the worker uses deleteLater (which it does) + if (this->m_parserWorker) { this->m_parserWorker->waitForFinished(); } + } bool CAircraftCfgParser::changeRootDirectory(const QString &directory) { @@ -28,7 +33,6 @@ namespace BlackMisc if (directory.isEmpty() || !existsDir(directory)) { return false; } m_rootDirectory = directory; - return true; } @@ -36,55 +40,61 @@ namespace BlackMisc { if (mode == ModeAsync) { - if (m_parserWorker && !m_parserWorker->isFinished()) return; - + if (m_parserWorker && !m_parserWorker->isFinished()) { return; } auto rootDirectory = m_rootDirectory; auto excludedDirectories = m_excludedDirectories; - m_parserWorker = BlackMisc::CWorker::fromTask(this, "CAircraftCfgParser::changeDirectory", - [this, rootDirectory, excludedDirectories]() + [this, rootDirectory, excludedDirectories]() { - auto aircraftCfgEntriesList = parseImpl(rootDirectory, excludedDirectories); - QMetaObject::invokeMethod(this, "ps_updateCfgEntriesList", - Q_ARG(BlackMisc::Simulation::FsCommon::CAircraftCfgEntriesList, aircraftCfgEntriesList)); + bool ok; + auto aircraftCfgEntriesList = parseImpl(rootDirectory, excludedDirectories, &ok); + if (!ok) { return; } + bool c = QMetaObject::invokeMethod(this, "ps_updateCfgEntriesList", + Q_ARG(BlackMisc::Simulation::FsCommon::CAircraftCfgEntriesList, aircraftCfgEntriesList)); + Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot invoke ps_updateCfgEntriesList"); + Q_UNUSED(c); }); } else if (mode == ModeBlocking) { - m_parsedCfgEntriesList = parseImpl(m_rootDirectory, m_excludedDirectories); - } - else - { - + bool ok; + m_parsedCfgEntriesList = parseImpl(m_rootDirectory, m_excludedDirectories, &ok); + emit parsingFinished(ok); } } void CAircraftCfgParser::ps_updateCfgEntriesList(const CAircraftCfgEntriesList &cfgEntriesList) { m_parsedCfgEntriesList = cfgEntriesList; - emit parsingFinished(); + emit parsingFinished(true); } - CAircraftCfgEntriesList CAircraftCfgParser::parseImpl(const QString &directory, const QStringList &excludeDirectories) + CAircraftCfgEntriesList CAircraftCfgParser::parseImpl(const QString &directory, const QStringList &excludeDirectories, bool *ok) { + *ok = false; if (m_cancelParsing) { return CAircraftCfgEntriesList(); } // excluded? for (const auto &excludeDir : excludeDirectories) { + if (m_cancelParsing) { return CAircraftCfgEntriesList(); } if (directory.contains(excludeDir, Qt::CaseInsensitive)) { CLogMessage(this).debug() << "Skipping directory " << directory; + *ok = true; return CAircraftCfgEntriesList(); } } // set directory with name filters, get aircraft.cfg and sub directories QDir dir(directory, "aircraft.cfg", QDir::Name, QDir::Files | QDir::AllDirs); - if (!dir.exists()) return CAircraftCfgEntriesList(); // can happen if there are shortcuts or linked dirs not available + if (!dir.exists()) + { + *ok = true; + return CAircraftCfgEntriesList(); // can happen if there are shortcuts or linked dirs not available + } QString currentDir = dir.absolutePath(); - CAircraftCfgEntriesList result; // Dirs last is crucial,since I will break recursion on "aircraft.cfg" level @@ -97,7 +107,17 @@ namespace BlackMisc QString nextDir = file.absoluteFilePath(); if (currentDir.startsWith(nextDir, Qt::CaseInsensitive)) { continue; } // do not go up if (dir == currentDir) { continue; } // do not recursively call same directory - result.push_back(parseImpl(nextDir, excludeDirectories)); + + bool dirOk; + const CAircraftCfgEntriesList subList(parseImpl(nextDir, excludeDirectories, &dirOk)); + if (dirOk) + { + result.push_back(subList); + } + else + { + CLogMessage(this).warning("Parsing failed for %1") << nextDir; + } } else { @@ -200,7 +220,6 @@ namespace BlackMisc file.close(); // store all entries - for (const CAircraftCfgEntries &e : tempEntries) { if (e.getTitle().isEmpty()) @@ -213,9 +232,14 @@ namespace BlackMisc newEntries.setAtcType(atcType); result.push_back(newEntries); } + *ok = true; return result; // do not go any deeper in file tree, we found aircraft.cfg } } + + // all files finished, + // normally reached when no aircraft.cfg is found + *ok = true; return result; } @@ -260,16 +284,13 @@ namespace BlackMisc QString content(line.mid(index + 1).trimmed()); - // fix "" strings, some are malformed and just contain " at beginning, end + // fix "" strings, some are malformed and just contain " at beginning, not at the end if (content.endsWith('"')) { content.remove(content.size() - 1 , 1); } if (content.startsWith('"')) { content.remove(0 , 1); } // fix C style linebreaks content.replace("\\n", " "); content.replace("\\t", " "); - - // return - return content; } diff --git a/src/blackmisc/simulation/fscommon/aircraftcfgparser.h b/src/blackmisc/simulation/fscommon/aircraftcfgparser.h index 1d41ce231..1f5d5f743 100644 --- a/src/blackmisc/simulation/fscommon/aircraftcfgparser.h +++ b/src/blackmisc/simulation/fscommon/aircraftcfgparser.h @@ -24,14 +24,12 @@ namespace BlackMisc { namespace FsCommon { - //! Utility, parsing the aircraft.cfg files class BLACKMISC_EXPORT CAircraftCfgParser : public QObject { Q_OBJECT public: - //! Parser mode enum ParserMode { @@ -48,7 +46,7 @@ namespace BlackMisc { } //! Virtual destructor - virtual ~CAircraftCfgParser() {} + virtual ~CAircraftCfgParser(); //! Change the directory bool changeRootDirectory(const QString &directory); @@ -69,20 +67,15 @@ namespace BlackMisc CAircraftCfgEntriesList getAircraftCfgEntriesList() const { return m_parsedCfgEntriesList; } signals: - //! Parsing is finished - void parsingFinished(); + void parsingFinished(bool success); private slots: - void ps_updateCfgEntriesList(const BlackMisc::Simulation::FsCommon::CAircraftCfgEntriesList &cfgEntriesList); - - CAircraftCfgEntriesList parseImpl(const QString &directory, const QStringList &excludeDirectories = {}); + CAircraftCfgEntriesList parseImpl(const QString &directory, const QStringList &excludeDirectories, bool *ok); private: - //! Section within file - enum FileSection { General, @@ -104,12 +97,9 @@ namespace BlackMisc QString m_rootDirectory; //!< root directory parsing aircraft.cfg files QStringList m_excludedDirectories; - CAircraftCfgEntriesList m_parsedCfgEntriesList; - QPointer m_parserWorker; - + QPointer m_parserWorker; //!< worker will destroy itself, so weak pointer std::atomic m_cancelParsing = { false }; - }; } // namespace } // namespace diff --git a/src/blackmisc/simulation/fscommon/aircraftmatcher.cpp b/src/blackmisc/simulation/fscommon/aircraftmatcher.cpp index 90bd9e31e..3cd4418bf 100644 --- a/src/blackmisc/simulation/fscommon/aircraftmatcher.cpp +++ b/src/blackmisc/simulation/fscommon/aircraftmatcher.cpp @@ -51,7 +51,7 @@ namespace BlackMisc void CAircraftMatcher::setModelMappingProvider(std::unique_ptr mappings) { m_mappingsProvider = std::move(mappings); - if (m_matchingMode.testFlag(ModelMapping)) initMappings(); + if (m_matchingMode.testFlag(ModelMapping)) { initMappings(); } } void CAircraftMatcher::setMatchingModes(MatchingMode matchingModes) @@ -157,9 +157,9 @@ namespace BlackMisc // finish CLogMessage(this).info("Mapping system: %1 definitions for %2 installed models") << m_modelMappings.size() << m_installedModels.size(); - emit initializationFinished(); m_initInProgress = false; m_initialized = true; + emit initializationFinished(); } void CAircraftMatcher::initMappings() diff --git a/src/blackmisc/simulation/fscommon/aircraftmatcher.h b/src/blackmisc/simulation/fscommon/aircraftmatcher.h index a93f4cca9..8810f999b 100644 --- a/src/blackmisc/simulation/fscommon/aircraftmatcher.h +++ b/src/blackmisc/simulation/fscommon/aircraftmatcher.h @@ -42,12 +42,10 @@ namespace BlackMisc Q_OBJECT signals: - //! Full init completed void initializationFinished(); public: - //! Enabled matching mode flags enum MatchingModeFlag { diff --git a/src/blackmisc/worker.cpp b/src/blackmisc/worker.cpp index 8280cf259..d539ff348 100644 --- a/src/blackmisc/worker.cpp +++ b/src/blackmisc/worker.cpp @@ -23,9 +23,10 @@ namespace BlackMisc worker->setObjectName(name); worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, "ps_runTask"); + bool s = QMetaObject::invokeMethod(worker, "ps_runTask"); + Q_ASSERT_X(s, Q_FUNC_INFO, "cannot invoke"); + Q_UNUSED(s); thread->start(); - return worker; } diff --git a/src/plugins/simulator/fscommon/simulator_fscommon.cpp b/src/plugins/simulator/fscommon/simulator_fscommon.cpp index 744226ad3..c869ff6de 100644 --- a/src/plugins/simulator/fscommon/simulator_fscommon.cpp +++ b/src/plugins/simulator/fscommon/simulator_fscommon.cpp @@ -40,14 +40,18 @@ namespace BlackSimPlugin { // hack to init mapper connect(&m_modelMatcher, &CAircraftMatcher::initializationFinished, this, &CSimulatorFsCommon::ps_mapperInitialized); - auto modelMappingsProvider = std::unique_ptr{ BlackMisc::make_unique(true) }; + auto modelMappingsProvider = std::unique_ptr { BlackMisc::make_unique(true) }; m_modelMatcher.setModelMappingProvider(std::move(modelMappingsProvider)); CVariant aircraftCfg = getPluginData(this, "aircraft_cfg"); if (aircraftCfg.isValid()) { m_modelMatcher.setInstalledModels(aircraftCfg.value().toAircraftModelList()); + m_modelMatcher.init(); } + // + // reading from settings would go here + // else { connect(&m_aircraftCfgParser, &CAircraftCfgParser::parsingFinished, this, &CSimulatorFsCommon::ps_aircraftCfgParsingFinished); @@ -55,8 +59,7 @@ namespace BlackSimPlugin } } - CSimulatorFsCommon::~CSimulatorFsCommon() - { } + CSimulatorFsCommon::~CSimulatorFsCommon() { } void CSimulatorFsCommon::ps_mapperInitialized() { @@ -209,8 +212,15 @@ namespace BlackSimPlugin CSimulatorCommon::enableDebugMessages(driver, interpolator); } - void CSimulatorFsCommon::ps_aircraftCfgParsingFinished() + void CSimulatorFsCommon::unload() { + this->m_aircraftCfgParser.cancelParsing(); + CSimulatorCommon::unload(); + } + + void CSimulatorFsCommon::ps_aircraftCfgParsingFinished(bool success) + { + if (!success) { return; } setPluginData(this, "aircraft_cfg", CVariant::from(m_aircraftCfgParser.getAircraftCfgEntriesList())); m_modelMatcher.setInstalledModels(m_aircraftCfgParser.getAircraftCfgEntriesList().toAircraftModelList()); diff --git a/src/plugins/simulator/fscommon/simulator_fscommon.h b/src/plugins/simulator/fscommon/simulator_fscommon.h index cc06043ea..09eb1e96e 100644 --- a/src/plugins/simulator/fscommon/simulator_fscommon.h +++ b/src/plugins/simulator/fscommon/simulator_fscommon.h @@ -76,6 +76,9 @@ namespace BlackSimPlugin //! \copydoc ISimulator::enableDebuggingMessages virtual void enableDebugMessages(bool driver, bool interpolator) override; + //! \copydoc ISimulator::unload + virtual void unload() override; + protected: //! Constructor CSimulatorFsCommon(const BlackMisc::Simulation::CSimulatorPluginInfo &info, @@ -99,7 +102,9 @@ namespace BlackSimPlugin BlackMisc::Aviation::CComSystem m_simCom2; //!< cockpit COM2 state in simulator BlackMisc::Aviation::CTransponder m_simTransponder; //!< cockpit xpdr state in simulator + // parser / matcher BlackMisc::Simulation::FsCommon::CAircraftCfgParser m_aircraftCfgParser; //!< aircraft.cfg parser + BlackMisc::Simulation::FsCommon::CAircraftMatcher m_modelMatcher; //!< Model matcher //! Set own model void setOwnAircraftModel(const BlackMisc::Simulation::CAircraftModel &model); @@ -110,15 +115,12 @@ namespace BlackSimPlugin //! Reverse lookup void reverseLookupIcaoData(BlackMisc::Simulation::CAircraftModel &model); - BlackMisc::Simulation::FsCommon::CAircraftMatcher m_modelMatcher; //!< Model matcher - protected slots: - //! Mapper has been initialized void ps_mapperInitialized(); //! aircraft.cfg files parsing is finished - void ps_aircraftCfgParsingFinished(); + void ps_aircraftCfgParsingFinished(bool success); }; } // namespace