From f3ec7a8a689f76e05d95d7458ee67c857c97afaf Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sat, 8 Jun 2019 21:41:22 +0200 Subject: [PATCH] Ref T660, utility functions * check if model is in path * addAsValidOrInvalidModel * set corresponding simulator for validation * display validation of empty model set --- .../components/dbownmodelsetcomponent.cpp | 4 +- .../views/aircraftmodelvalidationdialog.cpp | 8 ++- .../views/aircraftmodelvalidationdialog.h | 7 ++- src/blackgui/views/aircraftmodelview.cpp | 16 +++--- src/blackgui/views/aircraftmodelview.h | 9 ++-- src/blackmisc/simulation/aircraftmodel.cpp | 13 +++++ src/blackmisc/simulation/aircraftmodel.h | 3 ++ .../simulation/aircraftmodellist.cpp | 50 +++++++++++-------- src/blackmisc/simulation/aircraftmodellist.h | 5 ++ .../simulation/aircraftmodelutils.cpp | 19 +++++-- src/blackmisc/simulation/aircraftmodelutils.h | 2 +- .../simulation/backgroundvalidation.cpp | 11 ++-- 12 files changed, 99 insertions(+), 48 deletions(-) diff --git a/src/blackgui/components/dbownmodelsetcomponent.cpp b/src/blackgui/components/dbownmodelsetcomponent.cpp index 3fadf489c..54e231eb3 100644 --- a/src/blackgui/components/dbownmodelsetcomponent.cpp +++ b/src/blackgui/components/dbownmodelsetcomponent.cpp @@ -70,7 +70,7 @@ namespace BlackGui ui->tvp_OwnModelSet->menuAddItems(CAircraftModelView::MenuLoadAndSave | CAircraftModelView::MenuRefresh | CAircraftModelView::MenuOrderable); ui->tvp_OwnModelSet->setSorting(CAircraftModel::IndexOrderString); ui->tvp_OwnModelSet->initAsOrderable(); - ui->tvp_OwnModelSet->setSimulatorForLoading(ui->comp_SimulatorSelector->getValue()); + ui->tvp_OwnModelSet->setCorrespondingSimulator(ui->comp_SimulatorSelector->getValue()); ui->comp_SimulatorSelector->setMode(CSimulatorSelector::RadioButtons); ui->comp_SimulatorSelector->setRememberSelectionAndSetToLastSelection(); const CSimulatorInfo simulator = ui->comp_SimulatorSelector->getValue(); @@ -428,7 +428,7 @@ namespace BlackGui m_simulator = simulator; ui->comp_SimulatorSelector->setValue(simulator); - ui->tvp_OwnModelSet->setSimulatorForLoading(simulator); + ui->tvp_OwnModelSet->setCorrespondingSimulator(simulator); ui->le_Simulator->setText(simulator.toQString(true)); this->synchronizeCache(simulator); this->updateViewToCurrentModels(); diff --git a/src/blackgui/views/aircraftmodelvalidationdialog.cpp b/src/blackgui/views/aircraftmodelvalidationdialog.cpp index 87bb720a1..50cb122f2 100644 --- a/src/blackgui/views/aircraftmodelvalidationdialog.cpp +++ b/src/blackgui/views/aircraftmodelvalidationdialog.cpp @@ -36,6 +36,12 @@ namespace BlackGui CAircraftModelValidationDialog::~CAircraftModelValidationDialog() { } + void CAircraftModelValidationDialog::setModels(const CAircraftModelList &models, const CSimulatorInfo &simulator) + { + m_models = models; + m_simulator = simulator; + } + void CAircraftModelValidationDialog::triggerValidation(int delayMs) { QPointer myself(this); @@ -57,7 +63,7 @@ namespace BlackGui const bool ignoreEmpty = false; const int maxFailedFiles = 25; bool wasStopped = false; - const CStatusMessageList msgs = CAircraftModelUtilities::validateModelFiles(m_models, valid, invalid, ignoreEmpty, maxFailedFiles, wasStopped, ""); + const CStatusMessageList msgs = CAircraftModelUtilities::validateModelFiles(m_simulator, m_models, valid, invalid, ignoreEmpty, maxFailedFiles, wasStopped, ""); ui->comp_StatusMessage->clear(); ui->comp_StatusMessage->setNoSorting(); // we use the pre-sorted list ui->comp_StatusMessage->appendStatusMessagesToList(msgs); diff --git a/src/blackgui/views/aircraftmodelvalidationdialog.h b/src/blackgui/views/aircraftmodelvalidationdialog.h index 123d46e87..b9788e748 100644 --- a/src/blackgui/views/aircraftmodelvalidationdialog.h +++ b/src/blackgui/views/aircraftmodelvalidationdialog.h @@ -33,10 +33,12 @@ namespace BlackGui explicit CAircraftModelValidationDialog(QWidget *parent = nullptr); //! Destructor - virtual ~CAircraftModelValidationDialog(); + virtual ~CAircraftModelValidationDialog() override; //! Models - void setModels(const BlackMisc::Simulation::CAircraftModelList &models) { m_models = models; } + void setModels( + const BlackMisc::Simulation::CAircraftModelList &models, + const BlackMisc::Simulation::CSimulatorInfo &simulator); //! Trigger a validation void triggerValidation(int delayMs = 2500); @@ -47,6 +49,7 @@ namespace BlackGui QScopedPointer ui; BlackMisc::Simulation::CAircraftModelList m_models; + BlackMisc::Simulation::CSimulatorInfo m_simulator { BlackMisc::Simulation::CSimulatorInfo::None }; }; } // ns } // ns diff --git a/src/blackgui/views/aircraftmodelview.cpp b/src/blackgui/views/aircraftmodelview.cpp index 97d2b54db..00164349d 100644 --- a/src/blackgui/views/aircraftmodelview.cpp +++ b/src/blackgui/views/aircraftmodelview.cpp @@ -322,7 +322,7 @@ namespace BlackGui QDialog *parentDialog = CGuiUtility::findParentDialog(this); if (!(parentDialog && (qobject_cast(parentDialog)))) { - menuActions.addAction(CIcons::disk16(), "Model validation", CMenuAction::pathModel(), { this, &CAircraftModelView::displayModelValidationDialog }); + menuActions.addAction(CIcons::disk16(), "Model validation (selected)", CMenuAction::pathModel(), { this, &CAircraftModelView::displayModelValidationDialog }); } } if (CAircraftModelList::hasInvalidModelFile()) @@ -389,22 +389,22 @@ namespace BlackGui CStatusMessage CAircraftModelView::modifyLoadedJsonData(CAircraftModelList &models) const { - if (m_loadingRequiresSimulator.isNoSimulator()) { return {}; } + if (m_correspondingSimulator.isNoSimulator()) { return {}; } if (models.isEmpty()) { return CStatusMessage(this, CStatusMessage::SeverityDebug, u"Empty models", true); } // multiple sims with same count - const int removed = models.removeIfNotMatchingSimulator(m_loadingRequiresSimulator); + const int removed = models.removeIfNotMatchingSimulator(m_correspondingSimulator); if (removed < 1) { return {}; } - return CStatusMessage(this, CStatusMessage::SeverityWarning, u"Reduced by %1 model(s) to only use %2 models", true) << removed << m_loadingRequiresSimulator.toQString(true); + return CStatusMessage(this, CStatusMessage::SeverityWarning, u"Reduced by %1 model(s) to only use %2 models", true) << removed << m_correspondingSimulator.toQString(true); } CStatusMessage CAircraftModelView::validateLoadedJsonData(const CAircraftModelList &models) const { if (models.isEmpty()) { return COrderableViewWithDbObjects::validateLoadedJsonData(models); } - if (m_loadingRequiresSimulator.isNoSimulator()) { return COrderableViewWithDbObjects::validateLoadedJsonData(models); } - if (models.containsNotMatchingSimulator(m_loadingRequiresSimulator)) + if (m_correspondingSimulator.isNoSimulator()) { return COrderableViewWithDbObjects::validateLoadedJsonData(models); } + if (models.containsNotMatchingSimulator(m_correspondingSimulator)) { - return CStatusMessage(this, CStatusMessage::SeverityError, u"Found entry not matching %1 in model data", true) << m_loadingRequiresSimulator.toQString(); + return CStatusMessage(this, CStatusMessage::SeverityError, u"Found entry not matching %1 in model data", true) << m_correspondingSimulator.toQString(); } return COrderableViewWithDbObjects::validateLoadedJsonData(models); } @@ -473,7 +473,7 @@ namespace BlackGui void CAircraftModelView::displayModelValidationDialog() { if (!m_fileValidationDialog) { m_fileValidationDialog = new CAircraftModelValidationDialog(this); } - m_fileValidationDialog->setModels(this->selectedObjects()); + m_fileValidationDialog->setModels(this->selectedObjects(), m_correspondingSimulator); m_fileValidationDialog->triggerValidation(1000); m_fileValidationDialog->exec(); } diff --git a/src/blackgui/views/aircraftmodelview.h b/src/blackgui/views/aircraftmodelview.h index 572fe26a5..479aa0544 100644 --- a/src/blackgui/views/aircraftmodelview.h +++ b/src/blackgui/views/aircraftmodelview.h @@ -112,8 +112,9 @@ namespace BlackGui //! \copydoc BlackGui::Models::CAircraftModelListModel::highlightModels bool highlightModels() const; - //! Loading data will be restricted to simulator - void setSimulatorForLoading(const BlackMisc::Simulation::CSimulatorInfo &simulator) { m_loadingRequiresSimulator = simulator; } + //! Corresponding simulator + //! \remark used for validation or loading data will be restricted to simulator + void setCorrespondingSimulator(const BlackMisc::Simulation::CSimulatorInfo &simulator) { m_correspondingSimulator = simulator; } //! Enable the validation context menu void setValidationContextMenu(const bool enabled) { m_withValidationContextMenu = enabled; } @@ -171,9 +172,9 @@ namespace BlackGui bool m_stashingClearsSelection = true; //!< stashing unselects bool m_withValidationContextMenu = true; //!< validation didalog context menu - CAircraftModelStatisticsDialog *m_statisticsDialog = nullptr; + CAircraftModelStatisticsDialog *m_statisticsDialog = nullptr; CAircraftModelValidationDialog *m_fileValidationDialog = nullptr; - BlackMisc::Simulation::CSimulatorInfo m_loadingRequiresSimulator; //!< simulator required when loading + BlackMisc::Simulation::CSimulatorInfo m_correspondingSimulator; //!< validation, simulator required when loading }; } // ns } // ns diff --git a/src/blackmisc/simulation/aircraftmodel.cpp b/src/blackmisc/simulation/aircraftmodel.cpp index 5eb9f76e6..15183fd7d 100644 --- a/src/blackmisc/simulation/aircraftmodel.cpp +++ b/src/blackmisc/simulation/aircraftmodel.cpp @@ -766,6 +766,19 @@ namespace BlackMisc return this->getFileDirectory().absolutePath(); } + bool CAircraftModel::isInPath(const QString &path, Qt::CaseSensitivity cs) const + { + const QString p(this->getFileDirectoryPath()); + if (path.isEmpty() || p.isEmpty()) { return false; } + if (path.startsWith('/')) + { + if (path.endsWith('/')) { return p.contains(path.mid(1, path.length() - 2), cs); } + return p.contains(path.mid(1)); + } + if (path.endsWith('/')) { return p.contains(path.left(path.length() - 1), cs); } + return (p.contains(path, cs)); + } + bool CAircraftModel::hasExistingIconFile() const { if (m_iconFile.isEmpty()) { return false; } diff --git a/src/blackmisc/simulation/aircraftmodel.h b/src/blackmisc/simulation/aircraftmodel.h index 7c2fa16a8..8bf62c22a 100644 --- a/src/blackmisc/simulation/aircraftmodel.h +++ b/src/blackmisc/simulation/aircraftmodel.h @@ -457,6 +457,9 @@ namespace BlackMisc //! Directory path if any QString getFileDirectoryPath() const; + //! Is the file in the give path + bool isInPath(const QString &path, Qt::CaseSensitivity cs) const; + //! File name void setFileName(const QString &fileName) { m_fileName = fileName; } diff --git a/src/blackmisc/simulation/aircraftmodellist.cpp b/src/blackmisc/simulation/aircraftmodellist.cpp index de09e881d..5e5273256 100644 --- a/src/blackmisc/simulation/aircraftmodellist.cpp +++ b/src/blackmisc/simulation/aircraftmodellist.cpp @@ -1325,7 +1325,7 @@ namespace BlackMisc { CAircraftModelList invalidModels; CAircraftModelList validModels; - return validateForPublishing(validModels, invalidModels); + return this->validateForPublishing(validModels, invalidModels); } CStatusMessageList CAircraftModelList::validateForPublishing(CAircraftModelList &validModels, CAircraftModelList &invalidModels) const @@ -1351,7 +1351,7 @@ namespace BlackMisc CStatusMessage singleMsg(CStatusMessageList({msgModel, msgDb}).toSingleMessage()); if (!singleMsg.isWarningOrAbove()) { - validModels.push_back(model); + CAircraftModelList::addAsValidOrInvalidModel(model, true, validModels, invalidModels); continue; } if (model.hasModelString()) @@ -1359,7 +1359,7 @@ namespace BlackMisc singleMsg.prependMessage(model.getModelString() % u": "); } msgs.push_back(singleMsg); - invalidModels.push_back(model); + CAircraftModelList::addAsValidOrInvalidModel(model, false, validModels, invalidModels); } return msgs; } @@ -1375,21 +1375,18 @@ namespace BlackMisc { const CStatusMessage msg = CStatusMessage(this).validationError(u"No DB distributors for validation"); msgs.push_back(msg); - invalidModels.push_back(*this); + CAircraftModelList::addAsValidOrInvalidModels(*this, false, validModels, invalidModels); return msgs; } for (const CAircraftModel &model : *this) { - if (model.hasDbDistributor() || model.matchesAnyDbDistributor(distributorsFromDb)) - { - validModels.push_back(model); - } - else + const bool valid = (model.hasDbDistributor() || model.matchesAnyDbDistributor(distributorsFromDb)); + CAircraftModelList::addAsValidOrInvalidModel(model, valid, validModels, invalidModels); + if (!valid) { const CStatusMessage msg = CStatusMessage(this).validationError(u"No valid distributor for '%1', was '%2'") << model.getModelString() << model.getDistributor().getDbKey(); msgs.push_back(msg); - invalidModels.push_back(model); } } return msgs; @@ -1397,8 +1394,6 @@ namespace BlackMisc CStatusMessageList CAircraftModelList::validateFiles(CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, bool &stopped, const QString &rootDirectory, bool alreadySortedByFn) const { - invalidModels.clear(); - validModels.clear(); stopped = false; CStatusMessageList msgs; @@ -1466,15 +1461,7 @@ namespace BlackMisc } while (false); - if (ok) - { - validModels.push_back(model); - } - else - { - invalidModels.push_back(model); - } - + CAircraftModelList::addAsValidOrInvalidModel(model, ok, validModels, invalidModels); if (stopAtFailedFiles > 0 && failedFilesCount >= stopAtFailedFiles) { stopped = true; @@ -1717,5 +1704,26 @@ namespace BlackMisc return fi.exists(); } + void CAircraftModelList::addAsValidOrInvalidModel(const CAircraftModel &model, bool valid, CAircraftModelList &validModels, CAircraftModelList &invalidModels) + { + if (valid) + { + validModels.push_back(model); + invalidModels.removeModelWithString(model.getModelString(), Qt::CaseInsensitive); + } + else + { + invalidModels.push_back(model); + validModels.removeModelWithString(model.getModelString(), Qt::CaseInsensitive); + } + } + + void CAircraftModelList::addAsValidOrInvalidModels(const CAircraftModelList &models, bool valid, CAircraftModelList &validModels, CAircraftModelList &invalidModels) + { + for (const CAircraftModel &model : models) + { + CAircraftModelList::addAsValidOrInvalidModel(model, valid, validModels, invalidModels); + } + } } // namespace } // namespace diff --git a/src/blackmisc/simulation/aircraftmodellist.h b/src/blackmisc/simulation/aircraftmodellist.h index aba41f4db..13b1245a2 100644 --- a/src/blackmisc/simulation/aircraftmodellist.h +++ b/src/blackmisc/simulation/aircraftmodellist.h @@ -512,6 +512,11 @@ namespace BlackMisc static bool hasInvalidModelFile(); //! @} + //! Add as valid or invalid model (mutual exclusive) @{ + static void addAsValidOrInvalidModel(const CAircraftModel &model, bool valid, CAircraftModelList &validModels, CAircraftModelList &invalidModels); + static void addAsValidOrInvalidModels(const CAircraftModelList &models, bool valid, CAircraftModelList &validModels, CAircraftModelList &invalidModels); + //! @} + //! Newer version static CAircraftModelList fromDatabaseJsonCaching(const QJsonArray &array, const Aviation::CAircraftIcaoCodeList &aircraftIcaos = {}, diff --git a/src/blackmisc/simulation/aircraftmodelutils.cpp b/src/blackmisc/simulation/aircraftmodelutils.cpp index a95ce687a..82a086dc7 100644 --- a/src/blackmisc/simulation/aircraftmodelutils.cpp +++ b/src/blackmisc/simulation/aircraftmodelutils.cpp @@ -140,7 +140,7 @@ namespace BlackMisc return ok ? dir.absoluteFilePath(fn) : ""; } - CStatusMessageList CAircraftModelUtilities::validateModelFiles(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmpty, int stopAtFailedFiles, bool &stopped, const QString &simulatorDir) + CStatusMessageList CAircraftModelUtilities::validateModelFiles(const CSimulatorInfo &simulator, const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmpty, int stopAtFailedFiles, bool &stopped, const QString &simulatorDir) { // some generic tests CStatusMessageList msgs; @@ -164,14 +164,23 @@ namespace BlackMisc // specific checks for FSX/XPlane/FG CStatusMessageList specificTests; - if (models.isLikelyFsFamilyModelList()) + if (simulator.isMicrosoftOrPrepare3DSimulator() || models.isLikelyFsFamilyModelList()) { const CStatusMessageList specificTests1 = FsCommon::CFsCommonUtil::validateConfigFiles(models, validModels, invalidModels, ignoreEmpty, stopAtFailedFiles, stopped); - const CStatusMessageList specificTests2 = FsCommon::CFsCommonUtil::validateP3DSimObjectsPath(models, validModels, invalidModels, ignoreEmpty, stopAtFailedFiles, stopped); specificTests.push_back(specificTests1); - specificTests.push_back(specificTests2); + + if (simulator.isP3D()) + { + const CStatusMessageList specificTests2 = FsCommon::CFsCommonUtil::validateP3DSimObjectsPath(models, validModels, invalidModels, ignoreEmpty, stopAtFailedFiles, stopped, simulatorDir); + specificTests.push_back(specificTests2); + } + else if (simulator.isFSX()) + { + const CStatusMessageList specificTests2 = FsCommon::CFsCommonUtil::validateFSXSimObjectsPath(models, validModels, invalidModels, ignoreEmpty, stopAtFailedFiles, stopped); + specificTests.push_back(specificTests2); + } } - else if (models.isLikelyXPlaneModelList()) + else if (simulator.isXPlane() || models.isLikelyXPlaneModelList()) { specificTests = models.validateFiles(validModels, invalidModels, ignoreEmpty, stopAtFailedFiles, stopped, simulatorDir); } diff --git a/src/blackmisc/simulation/aircraftmodelutils.h b/src/blackmisc/simulation/aircraftmodelutils.h index da6ad1864..a86183f2f 100644 --- a/src/blackmisc/simulation/aircraftmodelutils.h +++ b/src/blackmisc/simulation/aircraftmodelutils.h @@ -36,7 +36,7 @@ namespace BlackMisc static QString createIcaoAirlineAircraftHtmlMatrixFile(const BlackMisc::Simulation::CAircraftModelList &models, const QString &tempDir); //! Validate aircraft.cfg entries - static CStatusMessageList validateModelFiles(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmpty, int stopAtFailedFiles, bool &stopped, const QString &simulatorDir); + static CStatusMessageList validateModelFiles(const CSimulatorInfo &simulator, const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmpty, int stopAtFailedFiles, bool &stopped, const QString &simulatorDir); }; } //namespace } // namespace diff --git a/src/blackmisc/simulation/backgroundvalidation.cpp b/src/blackmisc/simulation/backgroundvalidation.cpp index cf54dd6d2..bdeb42a1d 100644 --- a/src/blackmisc/simulation/backgroundvalidation.cpp +++ b/src/blackmisc/simulation/backgroundvalidation.cpp @@ -130,19 +130,22 @@ namespace BlackMisc onlyErrorsAndWarnings = setup.onlyShowVerificationWarningsAndErrors(); const CAircraftModelList models = m_modelSets.getCachedModels(simulator); + const qint64 now = QDateTime::currentMSecsSinceEpoch(); + validated = true; + if (models.isEmpty()) { msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityWarning, QStringLiteral("No models in set for '%1'").arg(simulator.toQString(true)))); - break; } - msgs = CAircraftModelUtilities::validateModelFiles(models, valid, invalid, false, 25, wasStopped, m_simDirectory); + else + { + msgs = CAircraftModelUtilities::validateModelFiles(simulator, models, valid, invalid, false, 25, wasStopped, m_simDirectory); + } - const qint64 now = QDateTime::currentMSecsSinceEpoch(); const qint64 deltaTimeMs = now - started; msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityInfo, QStringLiteral("Validated in %1ms").arg(deltaTimeMs))); msgs.sortBySeverityHighestFirst(); msgs.freezeOrder(); - validated = true; QWriteLocker l(&m_lock); m_lastResultValid = valid;