From fe677a5594c4f887c1610615afd989304d2f2e21 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Mon, 28 Mar 2016 00:56:22 +0200 Subject: [PATCH] refs #618, functions allowing to validate and modify loaded JSON data * models can be reduced to one simulator * a JSON model list can be loaded and the simulator derived from the distribution --- .../components/dbownmodelsetcomponent.cpp | 11 +++- .../components/dbownmodelsetcomponent.h | 3 + src/blackgui/views/aircraftmodelview.cpp | 56 +++++++++++++++++-- src/blackgui/views/aircraftmodelview.h | 28 ++++++---- src/blackgui/views/viewbase.cpp | 53 +++++++++++++----- src/blackgui/views/viewbase.h | 15 +++-- 6 files changed, 131 insertions(+), 35 deletions(-) diff --git a/src/blackgui/components/dbownmodelsetcomponent.cpp b/src/blackgui/components/dbownmodelsetcomponent.cpp index 977ab60b2..e2d091983 100644 --- a/src/blackgui/components/dbownmodelsetcomponent.cpp +++ b/src/blackgui/components/dbownmodelsetcomponent.cpp @@ -35,12 +35,14 @@ namespace BlackGui ui->tvp_OwnModelSet->menuAddItems(CAircraftModelView::MenuRemoveSelectedRows | CAircraftModelView::MenuClear); ui->tvp_OwnModelSet->addFilterDialog(); ui->tvp_OwnModelSet->setCustomMenu(new CLoadModelsMenu(this)); + ui->tvp_OwnModelSet->setJsonLoad(CAircraftModelView::AllowOnlySingleSimulator | CAircraftModelView::ReduceToOneSimulator); connect(ui->pb_CreateNewSet, &QPushButton::clicked, this, &CDbOwnModelSetComponent::ps_buttonClicked); connect(ui->pb_LoadExistingSet, &QPushButton::clicked, this, &CDbOwnModelSetComponent::ps_buttonClicked); connect(ui->pb_SaveAsSetForSimulator, &QPushButton::clicked, this, &CDbOwnModelSetComponent::ps_buttonClicked); connect(&this->m_modelSetLoader, &CModelSetLoader::simulatorChanged, this, &CDbOwnModelSetComponent::ps_onSimulatorChanged); connect(ui->tvp_OwnModelSet, &CAircraftModelView::rowCountChanged, this, &CDbOwnModelSetComponent::ps_onRowCountChanged); + connect(ui->tvp_OwnModelSet, &CAircraftModelView::jsonModelsForSimulatorLoaded, this, &CDbOwnModelSetComponent::ps_onJsonDataLoaded); this->ps_onRowCountChanged(ui->tvp_OwnModelSet->rowCount(), ui->tvp_OwnModelSet->hasFilter()); } @@ -163,7 +165,6 @@ namespace BlackGui } else if (sender == ui->pb_LoadExistingSet) { - this->ui->tvp_OwnModelSet->setLoadValidation(CAircraftModelView::AllowOnlySingeSimulator); this->ui->tvp_OwnModelSet->showFileLoadDialog(); } else if (sender == ui->pb_SaveAsSetForSimulator) @@ -210,6 +211,14 @@ namespace BlackGui } } + void CDbOwnModelSetComponent::ps_onJsonDataLoaded(const CSimulatorInfo &simulator) + { + if (simulator.isSingleSimulator()) + { + this->setSimulator(simulator); + } + } + void CDbOwnModelSetComponent::setSaveFileName(const CSimulatorInfo &sim) { Q_ASSERT_X(sim.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator"); diff --git a/src/blackgui/components/dbownmodelsetcomponent.h b/src/blackgui/components/dbownmodelsetcomponent.h index ba991a0ed..4a283532e 100644 --- a/src/blackgui/components/dbownmodelsetcomponent.h +++ b/src/blackgui/components/dbownmodelsetcomponent.h @@ -83,6 +83,9 @@ namespace BlackGui //! View has changed row count void ps_onRowCountChanged(int count, bool withFilter); + //! JSON data have been loaded from disk + void ps_onJsonDataLoaded(const BlackMisc::Simulation::CSimulatorInfo &simulator); + private: //! Default file name void setSaveFileName(const BlackMisc::Simulation::CSimulatorInfo &sim); diff --git a/src/blackgui/views/aircraftmodelview.cpp b/src/blackgui/views/aircraftmodelview.cpp index c06f06936..dcd852524 100644 --- a/src/blackgui/views/aircraftmodelview.cpp +++ b/src/blackgui/views/aircraftmodelview.cpp @@ -11,7 +11,8 @@ #include "blackmisc/aviation/aircrafticaocodelist.h" #include "blackmisc/aviation/airlineicaocodelist.h" #include "blackmisc/aviation/liverylist.h" -#include "blackmisc/simulation//distributorlist.h" +#include "blackmisc/simulation/distributorlist.h" +#include "blackmisc/simulation/simulatorinfolist.h" #include "blackgui/shortcut.h" #include "blackgui/guiapplication.h" #include "blackgui/guiutility.h" @@ -292,17 +293,64 @@ namespace BlackGui CViewWithDbObjects::customMenu(menu); } - CStatusMessage CAircraftModelView::validateLoadedData(const CAircraftModelList &models) const + CStatusMessage CAircraftModelView::modifyLoadedJsonData(CAircraftModelList &models) const + { + if (!this->m_jsonLoad.testFlag(ReduceToOneSimulator)) { return {}; } + if (models.isEmpty()) { return CStatusMessage(this, CStatusMessage::SeverityDebug, "Empty models", true); } + const CSimulatorInfo maxSims = models.simulatorsWithMaxEntries(); + if (maxSims.isNoSimulator()) + { + return CStatusMessage(this, CStatusMessage::SeverityError, "No simulator with maximum, cannot reduce"); + } + + if (maxSims.isSingleSimulator()) + { + int rm = models.removeIfNotMatchingSimulator(maxSims); + return rm < 1 ? + CStatusMessage(this, CStatusMessage::SeverityInfo, "Now only for " + maxSims.toQString(true), true) : + CStatusMessage(this, CStatusMessage::SeverityInfo, "Reduced by % 1 to only use %2", true) << rm << maxSims.toQString(true); + } + + // one simulator dominating + if (maxSims.isSingleSimulator()) + { + int rm = models.removeIfNotMatchingSimulator(maxSims); + return rm < 1 ? + CStatusMessage(this, CStatusMessage::SeverityInfo, "Now only for " + maxSims.toQString(true), true) : + CStatusMessage(this, CStatusMessage::SeverityInfo, "Reduced by % 1 to only use %2", true) << rm << maxSims.toQString(true); + } + + // multiple sims with same count + const CSimulatorInfo first = CSimulatorInfoList::splitIntoSingleSimulators(maxSims).front(); + int d = models.removeIfNotMatchingSimulator(first); + return d < 1 ? + CStatusMessage(this, CStatusMessage::SeverityInfo, "Now only for " + maxSims.toQString(true), true) : + CStatusMessage(this, CStatusMessage::SeverityInfo, "Reduced by % 1 to only use %2", true) << d << maxSims.toQString(true); + } + + CStatusMessage CAircraftModelView::validateLoadedJsonData(const CAircraftModelList &models) const { static const CStatusMessage ok(this, CStatusMessage::SeverityInfo, "model validation passed", true); if (models.isEmpty()) { return CStatusMessage(this, CStatusMessage::SeverityInfo, "no data", true); } - if (this->m_validation == AllowOnlySingeSimulator) + if (this->m_jsonLoad == AllowOnlySingleSimulator) { const CSimulatorInfo sim = models.simulatorsSupported(); if (sim.isSingleSimulator()) { return ok; } return CStatusMessage(this, CStatusMessage::SeverityError, "data need to be from one simulator"); } - return CViewWithDbObjects::validateLoadedData(models); + return CViewWithDbObjects::validateLoadedJsonData(models); + } + + void CAircraftModelView::jsonLoadedAndModelUpdated(const CAircraftModelList &models) + { + if (models.isEmpty()) + { + emit jsonModelsForSimulatorLoaded(CSimulatorInfo()); + } + else + { + emit jsonModelsForSimulatorLoaded(models.simulatorsWithMaxEntries()); + } } void CAircraftModelView::ps_toggleHighlightStashedModels() diff --git a/src/blackgui/views/aircraftmodelview.h b/src/blackgui/views/aircraftmodelview.h index 888a58ff7..cfe56f379 100644 --- a/src/blackgui/views/aircraftmodelview.h +++ b/src/blackgui/views/aircraftmodelview.h @@ -29,12 +29,13 @@ namespace BlackGui public: //! How to validate loaded JSON data - enum LoadValidationFlag + enum JsonLoadFlag { - NoValidation, - AllowOnlySingeSimulator + NotSet = 0, + AllowOnlySingleSimulator = 1 << 0, + ReduceToOneSimulator = 1 << 1 }; - Q_DECLARE_FLAGS(LoadValidation, LoadValidationFlag) + Q_DECLARE_FLAGS(JsonLoad, JsonLoadFlag) //! Constructor explicit CAircraftModelView(QWidget *parent = nullptr); @@ -88,7 +89,7 @@ namespace BlackGui bool highlightModelStrings() const; //! Load validation - void setLoadValidation(LoadValidation validation) { m_validation = validation; } + void setJsonLoad(JsonLoad jsonLoad) { m_jsonLoad = jsonLoad; } signals: //! Request to stash if applicable @@ -100,6 +101,9 @@ namespace BlackGui //! Request further handling of drops I cannot handle on my own void requestHandlingOfStashDrop(const BlackMisc::Aviation::CAirlineIcaoCode &airlineIcao); + //! Models for simulator loaded (JSON) + void jsonModelsForSimulatorLoaded(const BlackMisc::Simulation::CSimulatorInfo &simulator); + protected: //! \copydoc QTableView::dropEvent virtual void dropEvent(QDropEvent *event) override; @@ -107,7 +111,9 @@ namespace BlackGui //! \name View base class overrides //! @{ virtual void customMenu(QMenu &menu) const override; - virtual BlackMisc::CStatusMessage validateLoadedData(const BlackMisc::Simulation::CAircraftModelList &models) const override; + virtual BlackMisc::CStatusMessage modifyLoadedJsonData(BlackMisc::Simulation::CAircraftModelList &models) const override; + virtual BlackMisc::CStatusMessage validateLoadedJsonData(const BlackMisc::Simulation::CAircraftModelList &models) const override; + virtual void jsonLoadedAndModelUpdated(const BlackMisc::Simulation::CAircraftModelList &models) override; //! @} private slots: @@ -124,14 +130,14 @@ namespace BlackGui void ps_requestStash(); private: - bool m_stashingClearsSelection = true; //!< stashing unselects - LoadValidation m_validation = NoValidation; //!< Loaded JSON validation + bool m_stashingClearsSelection = true; //!< stashing unselects + JsonLoad m_jsonLoad = NotSet; //!< Loaded JSON validation }; } // ns } // ns -Q_DECLARE_METATYPE(BlackGui::Views::CAircraftModelView::LoadValidation) -Q_DECLARE_METATYPE(BlackGui::Views::CAircraftModelView::LoadValidationFlag) -Q_DECLARE_OPERATORS_FOR_FLAGS(BlackGui::Views::CAircraftModelView::LoadValidation) +Q_DECLARE_METATYPE(BlackGui::Views::CAircraftModelView::JsonLoad) +Q_DECLARE_METATYPE(BlackGui::Views::CAircraftModelView::JsonLoadFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(BlackGui::Views::CAircraftModelView::JsonLoad) #endif // guard diff --git a/src/blackgui/views/viewbase.cpp b/src/blackgui/views/viewbase.cpp index 512ce47b8..3565ee50d 100644 --- a/src/blackgui/views/viewbase.cpp +++ b/src/blackgui/views/viewbase.cpp @@ -956,7 +956,7 @@ namespace BlackGui } template - CStatusMessage CViewBase::modifyLoadedData(ContainerType &data) const + CStatusMessage CViewBase::modifyLoadedJsonData(ContainerType &data) const { Q_UNUSED(data); static const CStatusMessage e(this, CStatusMessage::SeverityInfo, "no modification", true); @@ -964,31 +964,54 @@ namespace BlackGui } template - CStatusMessage CViewBase::validateLoadedData(const ContainerType &data) const + CStatusMessage CViewBase::validateLoadedJsonData(const ContainerType &data) const { Q_UNUSED(data); static const CStatusMessage e(this, CStatusMessage::SeverityInfo, "no validation", true); return e; } + template + void CViewBase::jsonLoadedAndModelUpdated(const ContainerType &data) + { + Q_UNUSED(data); + } + template CStatusMessage CViewBase::ps_loadJson() { - const QString fileName = QFileDialog::getOpenFileName(nullptr, - tr("Load data file"), getDefaultFilename(true), - tr("swift (*.json *.txt)")); - if (fileName.isEmpty()) { return CStatusMessage(this, CStatusMessage::SeverityDebug, "Load canceled", true); } - QString json(CFileUtils::readFileToString(fileName)); - if (json.isEmpty()) + CStatusMessage m; + do { - return CStatusMessage(this, CStatusMessage::SeverityWarning, "Reading " + fileName + " yields no data", true); + const QString fileName = QFileDialog::getOpenFileName(nullptr, + tr("Load data file"), getDefaultFilename(true), + tr("swift (*.json *.txt)")); + if (fileName.isEmpty()) + { + m = CStatusMessage(this, CStatusMessage::SeverityDebug, "Load canceled", true); + break; + } + + QString json(CFileUtils::readFileToString(fileName)); + if (json.isEmpty()) + { + m = CStatusMessage(this, CStatusMessage::SeverityWarning, "Reading " + fileName + " yields no data", true); + break; + } + ContainerType container; + container.convertFromJson(json); + m = this->modifyLoadedJsonData(container); + if (m.isFailure()) { break; } // modification error + m = this->validateLoadedJsonData(container); + if (m.isFailure()) { break; } // validaton error + this->updateContainerMaybeAsync(container); + m = CStatusMessage(this, CStatusMessage::SeverityInfo, "Reading " + fileName + " completed", true); + this->jsonLoadedAndModelUpdated(container); } - ContainerType container; - container.convertFromJson(json); - const CStatusMessage s = this->validateLoadedData(container); - if (s.getSeverity() == CStatusMessage::SeverityError) { return s; } - this->updateContainerMaybeAsync(container); - return CStatusMessage(this, CStatusMessage::SeverityInfo, "Reading " + fileName + " completed", true); + while (false); + + emit this->jsonLoadCompleted(m); + return m; } template diff --git a/src/blackgui/views/viewbase.h b/src/blackgui/views/viewbase.h index c53a3cfc9..fa91ac15c 100644 --- a/src/blackgui/views/viewbase.h +++ b/src/blackgui/views/viewbase.h @@ -221,7 +221,7 @@ namespace BlackGui //! Number of elements changed void rowCountChanged(int count, bool withFilter); - //! Model bas been changed + //! Model bas been changed (means data in view have been changed) void modelChanged(); //! Single object was changed in model @@ -236,6 +236,9 @@ namespace BlackGui //! Object has been double clicked void objectSelected(const BlackMisc::CVariant &object); + //! JSON data load from disk completed, the BlackMisc::CStatusMessage represents the success + void jsonLoadCompleted(const BlackMisc::CStatusMessage &msg); + public slots: //! Resize to contents, strategy depends on container size virtual void resizeToContents(); @@ -401,7 +404,7 @@ namespace BlackGui //! Base class for views template class CViewBase : public CViewBaseNonTemplate { - // I cannot use Q_OBJECT here, because error: Template classes not supported by Q_OBJECT + // I cannot use Q_OBJECT here, because of error: Template classes not supported by Q_OBJECT // Cannot declare slots as SLOT because I have no Q_OBJECT macro public: @@ -528,10 +531,14 @@ namespace BlackGui virtual int performUpdateContainer(const BlackMisc::CVariant &variant, bool sort, bool resize) override; //! Modify JSON data loaded in BlackGui::Views::CViewBaseNonTemplate::ps_loadJson - virtual BlackMisc::CStatusMessage modifyLoadedData(ContainerType &data) const; + virtual BlackMisc::CStatusMessage modifyLoadedJsonData(ContainerType &data) const; //! Verify JSON data loaded in BlackGui::Views::CViewBaseNonTemplate::ps_loadJson - virtual BlackMisc::CStatusMessage validateLoadedData(const ContainerType &data) const; + virtual BlackMisc::CStatusMessage validateLoadedJsonData(const ContainerType &data) const; + + //! In BlackGui::Views::CViewBaseNonTemplate::ps_loadJson the view has been updated because of loaded JSON data + //! \remark I cannot use a signal with a template parameter, so this functions serves as callback + virtual void jsonLoadedAndModelUpdated(const ContainerType &data); // --------------------------------------------- SLOTS start here -----------------------------------------