diff --git a/src/blackgui/components/dbmappingcomponent.cpp b/src/blackgui/components/dbmappingcomponent.cpp index 703a712d9..2921dbef8 100644 --- a/src/blackgui/components/dbmappingcomponent.cpp +++ b/src/blackgui/components/dbmappingcomponent.cpp @@ -57,7 +57,7 @@ namespace BlackGui connect(ui->comp_StashAircraft, &CDbStashComponent::modelsSuccessfullyPublished, this, &CDbMappingComponent::ps_onModelsSuccessfullyPublished); ui->tvp_OwnAircraftModels->setDisplayAutomatically(true); - ui->tvp_OwnAircraftModels->setCustomMenu(new CMappingSimulatorModelMenu(this)); + ui->tvp_OwnAircraftModels->setCustomMenu(new CMappingOwnSimulatorModelMenu(this)); ui->tvp_OwnAircraftModels->setCustomMenu(new CModelStashTools(this)); ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(this->m_cachedOwnModels.get()); @@ -92,6 +92,7 @@ namespace BlackGui connect(&m_vPilotReader, &CVPilotRulesReader::readFinished, this, &CDbMappingComponent::ps_onLoadVPilotDataFinished); connect(this->ui->tvp_AircraftModelsForVPilot, &CAircraftModelView::requestStash, this, &CDbMappingComponent::stashSelectedModels); connect(this->ui->tvp_AircraftModelsForVPilot, &CAircraftModelView::toggledHighlightStashedModels, this, &CDbMappingComponent::ps_onStashedModelsChanged); + connect(this->ui->tvp_AircraftModelsForVPilot, &CAircraftModelView::requestUpdate, this, &CDbMappingComponent::ps_requestVPilotDataUpdate); this->ui->tvp_AircraftModelsForVPilot->setCustomMenu(new CMappingVPilotMenu(this, true)); this->ui->tvp_AircraftModelsForVPilot->setCustomMenu(new CModelStashTools(this)); @@ -259,13 +260,14 @@ namespace BlackGui return ui->comp_StashAircraft->getStashedModelStrings(); } - CAircraftModel CDbMappingComponent::getOwnModelForModelString(const QString &modelString) + CAircraftModel CDbMappingComponent::getOwnModelForModelString(const QString &modelString) const { return m_cachedOwnModels.get().findFirstByModelString(modelString); } CDbMappingComponent::TabIndex CDbMappingComponent::currentTabIndex() const { + if (!ui->tw_ModelsToBeMapped) { return CDbMappingComponent::NoValidTab; } int t = ui->tw_ModelsToBeMapped->currentIndex(); return static_cast(t); } @@ -312,7 +314,7 @@ namespace BlackGui void CDbMappingComponent::ps_displayAutoStashingDialog() { - this->m_autostashDialog->setVisible(true); + this->m_autostashDialog->exec(); } void CDbMappingComponent::ps_removeDbModelsFromView() @@ -325,6 +327,11 @@ namespace BlackGui } } + void CDbMappingComponent::ps_toggleAutoFiltering() + { + this->m_autoFilterInDbViews = !this->m_autoFilterInDbViews; + } + void CDbMappingComponent::resizeForSelect() { int h = this->height(); @@ -406,6 +413,11 @@ namespace BlackGui } } + void CDbMappingComponent::ps_requestVPilotDataUpdate() + { + this->ps_onVPilotCacheChanged(); + } + void CDbMappingComponent::ps_onStashedModelsChanged() { bool hlvp = this->ui->tvp_AircraftModelsForVPilot->derivedModel()->highlightModelStrings(); @@ -514,9 +526,12 @@ namespace BlackGui else { this->ui->editor_Distributor->clear(); } // request filtering - emit filterByLivery(model.getLivery()); - emit filterByAircraftIcao(model.getAircraftIcaoCode()); - emit filterByDistributor(model.getDistributor()); + if (this->m_autoFilterInDbViews) + { + emit filterByLivery(model.getLivery()); + emit filterByAircraftIcao(model.getAircraftIcaoCode()); + emit filterByDistributor(model.getDistributor()); + } } void CDbMappingComponent::ps_loadInstalledModels(const CSimulatorInfo &simInfo) @@ -569,9 +584,9 @@ namespace BlackGui return model; } - CStatusMessage CDbMappingComponent::stashModel(const CAircraftModel &model) + CStatusMessage CDbMappingComponent::stashModel(const CAircraftModel &model, bool replace) { - return this->ui->comp_StashAircraft->stashModel(model); + return this->ui->comp_StashAircraft->stashModel(model, replace); } CStatusMessageList CDbMappingComponent::stashModels(const CAircraftModelList &models) @@ -579,7 +594,17 @@ namespace BlackGui return this->ui->comp_StashAircraft->stashModels(models); } - void CDbMappingComponent::CMappingSimulatorModelMenu::customMenu(QMenu &menu) const + CAircraftModel CDbMappingComponent::consolidateModel(const CAircraftModel &model) const + { + return this->ui->comp_StashAircraft->consolidateModel(model); + } + + void CDbMappingComponent::replaceStashedModelsUnvalidated(const CAircraftModelList &models) const + { + this->ui->comp_StashAircraft->replaceModelsUnvalidated(models); + } + + void CDbMappingComponent::CMappingOwnSimulatorModelMenu::customMenu(QMenu &menu) const { CSimulatorInfo sims = CSimulatorInfo::getLocallyInstalledSimulators(); bool noSims = sims.isNoSimulator() || sims.isUnspecified(); @@ -656,6 +681,16 @@ namespace BlackGui // we have keys and data where we could delete them from const QString msgAutoStash("Auto stashing"); menu.addAction(CIcons::appDbStash16(), msgAutoStash, mapComp, SLOT(ps_displayAutoStashingDialog())); + + if (mapComp->m_autostashDialog && mapComp->m_autostashDialog->isCompleted()) + { + menu.addAction(CIcons::appDbStash16(), "Last auto stash run", mapComp->m_autostashDialog.data(), SLOT(showLastResults())); + } + + // auto filter in DB views + QAction *a = menu.addAction(CIcons::filter16(), "Auto filtering (DB views)", mapComp, SLOT(ps_toggleAutoFiltering())); + a->setCheckable(true); + a->setChecked(mapComp->m_autoFilterInDbViews); } } this->nestedCustomMenu(menu); diff --git a/src/blackgui/components/dbmappingcomponent.h b/src/blackgui/components/dbmappingcomponent.h index dc79e576d..5233bacee 100644 --- a/src/blackgui/components/dbmappingcomponent.h +++ b/src/blackgui/components/dbmappingcomponent.h @@ -85,11 +85,17 @@ namespace BlackGui QStringList getStashedModelStrings() const; //! Own (installed) model for given model string - BlackMisc::Simulation::CAircraftModel getOwnModelForModelString(const QString &modelString); + BlackMisc::Simulation::CAircraftModel getOwnModelForModelString(const QString &modelString) const; //! Current tab index TabIndex currentTabIndex() const; + //! Current model view + const BlackGui::Views::CAircraftModelView *currentModelView() const; + + //! Current model view + BlackGui::Views::CAircraftModelView *currentModelView(); + //! Is stashed view bool isStashedTab() const; @@ -98,11 +104,29 @@ namespace BlackGui BlackMisc::Simulation::CAircraftModel getEditorAircraftModel() const; public slots: - //! Stash model - BlackMisc::CStatusMessage stashModel(const BlackMisc::Simulation::CAircraftModel &model); + //! \copydoc CDbStashComponent::stashModel + BlackMisc::CStatusMessage stashModel(const BlackMisc::Simulation::CAircraftModel &model, bool replace = false); + + //! \copydoc CDbStashComponent::stashModels + BlackMisc::CStatusMessageList stashModels(const BlackMisc::Simulation::CAircraftModelList &models); + + //! \copydoc CDbStashComponent::consolidateModel + BlackMisc::Simulation::CAircraftModel consolidateModel(const BlackMisc::Simulation::CAircraftModel &model) const; + + //! \copydoc CDbStashComponent::replaceModelsUnvalidated + void replaceStashedModelsUnvalidated(const BlackMisc::Simulation::CAircraftModelList &models) const; + + //! Validate, empty list means OK + BlackMisc::CStatusMessageList validateCurrentModel(bool withNestedForms) const; + + //! Resize so that selection is easy (larger table view) + void resizeForSelect(); + + //! Resize so that mapping is easier + void resizeForMapping(); //! Stash models - BlackMisc::CStatusMessageList stashModels(const BlackMisc::Simulation::CAircraftModelList &models); + void stashSelectedModels(); signals: //! Request to filter by livery @@ -117,19 +141,6 @@ namespace BlackGui //! Request latest (incrementall) data from backend void requestUpdatedData(BlackMisc::Network::CEntityFlags::Entity entities); - public slots: - //! Validate, empty list means OK - BlackMisc::CStatusMessageList validateCurrentModel(bool withNestedForms) const; - - //! Resize so that selection is easy (larger table view) - void resizeForSelect(); - - //! Resize so that mapping is easier - void resizeForMapping(); - - //! Stash models - void stashSelectedModels(); - private slots: //! Load the vPilot rules void ps_loadVPilotData(); @@ -140,6 +151,9 @@ namespace BlackGui //! vPilot cached models changed void ps_onVPilotCacheChanged(); + //! Request update of vPilot data + void ps_requestVPilotDataUpdate(); + //! Stashed models changed void ps_onStashedModelsChanged(); @@ -182,6 +196,9 @@ namespace BlackGui //! Remove DB models from current view void ps_removeDbModelsFromView(); + //! Toggle auto filtering + void ps_toggleAutoFiltering(); + private: QScopedPointer ui; QScopedArrayPointer m_autostashDialog { new CDbAutoStashingComponent(this) }; @@ -190,8 +207,9 @@ namespace BlackGui std::unique_ptr m_modelLoader; //!< read own aircraft models BlackMisc::CData m_cachedOwnModels { this }; //!< cache for own installed models BlackMisc::CData m_user {this, &CDbMappingComponent::ps_userChanged}; - bool m_vPilot1stInit = true; - bool m_withVPilot = false; + bool m_vPilot1stInit = true; + bool m_withVPilot = false; + bool m_autoFilterInDbViews = false; //!< automatically filter the DB view by the current model //! Init vPilot if rights and suitable void initVPilotLoading(); @@ -202,12 +220,6 @@ namespace BlackGui //! Model for given index from sender/current view BlackMisc::Simulation::CAircraftModel getModelFromView(const QModelIndex &index) const; - //! Current model view - const BlackGui::Views::CAircraftModelView *currentModelView() const; - - //! Current model view - BlackGui::Views::CAircraftModelView *currentModelView(); - //! Current tab text QString currentTabText() const; @@ -215,11 +227,11 @@ namespace BlackGui //! The menu for loading and handling own models for mapping tasks //! \note This is specific for that very component - class CMappingSimulatorModelMenu : public BlackGui::IMenuDelegate + class CMappingOwnSimulatorModelMenu : public BlackGui::IMenuDelegate { public: //! Constructor - CMappingSimulatorModelMenu(CDbMappingComponent *mappingComponent, bool separator = true) : + CMappingOwnSimulatorModelMenu(CDbMappingComponent *mappingComponent, bool separator = true) : BlackGui::IMenuDelegate(mappingComponent, separator) {} diff --git a/src/blackgui/components/dbstashcomponent.cpp b/src/blackgui/components/dbstashcomponent.cpp index b6ba729c2..18dc7714b 100644 --- a/src/blackgui/components/dbstashcomponent.cpp +++ b/src/blackgui/components/dbstashcomponent.cpp @@ -76,37 +76,25 @@ namespace BlackGui if (!allowReplace && this->ui->tvp_StashAircraftModels->container().containsModelStringOrId(model)) { const QString msg("Model \"%1\" already stashed"); - return CStatusMessage(validationCats(), CStatusMessage::SeverityError, msg.arg(model.getModelString())); + return CStatusMessage(validationCategories(), CStatusMessage::SeverityError, msg.arg(model.getModelString())); } return CStatusMessage(); } CStatusMessage CDbStashComponent::stashModel(const CAircraftModel &model, bool replace) { - CAircraftModel pushModel(model); - // merge with own models if any - if (pushModel.getModelType() != CAircraftModel::TypeOwnSimulatorModel) - { - pushModel = this->consolidateWithOwnModels(pushModel); - } - - // merge with DB data if any - if (!pushModel.hasValidDbKey()) - { - pushModel = this->consolidateWithDbData(pushModel); - } - - CStatusMessage m(validateStashModel(pushModel, replace)); + CAircraftModel stashModel(this->consolidateModel(model)); + CStatusMessage m(validateStashModel(stashModel, replace)); if (!m.isWarningOrAbove()) { if (replace) { - this->ui->tvp_StashAircraftModels->replaceOrAdd(&CAircraftModel::getModelString, pushModel.getModelString(), pushModel); + this->ui->tvp_StashAircraftModels->replaceOrAdd(&CAircraftModel::getModelString, stashModel.getModelString(), stashModel); } else { - this->ui->tvp_StashAircraftModels->insert(pushModel); + this->ui->tvp_StashAircraftModels->insert(stashModel); } } return m; @@ -124,6 +112,11 @@ namespace BlackGui return msgs; } + void CDbStashComponent::replaceModelsUnvalidated(const CAircraftModelList &models) + { + this->ui->tvp_StashAircraftModels->updateContainerMaybeAsync(models); + } + int CDbStashComponent::unstashModels(QList keys) { if (keys.isEmpty()) { return 0; } @@ -228,7 +221,17 @@ namespace BlackGui if (!this->validateAndDisplay()) { return; } CAircraftModelList models(getSelectedOrAllModels()); if (models.isEmpty()) { return; } - CStatusMessageList msgs = this->asyncPublishModels(models); + + CStatusMessageList msgs; + if (models.size() > MaxModelPublished) + { + CAircraftModelList::iterator i = models.begin(); + std::advance(i, MaxModelPublished); + models.erase(i, models.end()); + msgs.push_back(CStatusMessage(validationCategories(), CStatusMessage::SeverityWarning, QString("More than %1 values, values skipped").arg(MaxModelPublished))); + } + + msgs.push_back(this->asyncPublishModels(models)); if (msgs.hasWarningOrErrorMessages()) { this->showMessages(msgs); @@ -276,7 +279,7 @@ namespace BlackGui { return CStatusMessageList( { - CStatusMessage(validationCats(), CStatusMessage::SeverityInfo, QString("No errors in %1 model(s)").arg(models.size())) + CStatusMessage(validationCategories(), CStatusMessage::SeverityInfo, QString("No errors in %1 model(s)").arg(models.size())) }); } else @@ -301,7 +304,7 @@ namespace BlackGui if (displayInfo) { QString no = QString::number(this->getStashedModelsCount()); - CStatusMessage msg(validationCats(), CStatusMessage::SeverityInfo, "Validation passed for " + no + " models"); + CStatusMessage msg(validationCategories(), CStatusMessage::SeverityInfo, "Validation passed for " + no + " models"); this->showMessage(msg); } return true; // no error @@ -320,7 +323,7 @@ namespace BlackGui this->ui->pb_Validate->setEnabled(e); } - const CLogCategoryList &CDbStashComponent::validationCats() const + const CLogCategoryList &CDbStashComponent::validationCategories() const { static const CLogCategoryList cats(CLogCategoryList(this).join({ CLogCategory::validation()})); return cats; @@ -333,19 +336,58 @@ namespace BlackGui return models; } - CAircraftModel CDbStashComponent::consolidateWithDbData(const CAircraftModel &model) + CAircraftModel CDbStashComponent::consolidateWithDbData(const CAircraftModel &model) const { if (!model.hasModelString()) { return model; } CAircraftModel dbModel(this->getModelForModelString(model.getModelString())); - if (!dbModel.hasValidDbKey()) { return model; } + // we try to best update by DB data here + if (!dbModel.hasValidDbKey()) + { + // we have no(!) DB model, so we update ecach of it subobjects + CAircraftModel consolidatedModel(model); // copy over + if (!consolidatedModel.getLivery().hasValidDbKey() && consolidatedModel.hasAirlineDesignator()) + { + // we try to find a DB livery for the airline + // maybe slow because all liveries always copied over + CLivery dbLivery(this->getLiveries().findStdLiveryByAirlineIcaoDesignator(model.getAirlineIcaoCode())); + if (dbLivery.hasValidDbKey()) + { + consolidatedModel.setLivery(dbLivery); + } + } + if (!consolidatedModel.getAircraftIcaoCode().hasValidDbKey() && consolidatedModel.hasAircraftDesignator()) + { + // try to find DB aircraft ICAO here + CAircraftIcaoCode dbIcao(this->getAircraftIcaoCodeForDesignator(consolidatedModel.getAircraftIcaoCode().getDesignator())); + if (dbIcao.hasValidDbKey()) + { + consolidatedModel.setAircraftIcaoCode(dbIcao); + } + } + + // key alone here can be misleading, as the key can be valid but no DB key + // mostly happens when key is an alias + QString keyOrAlias(consolidatedModel.getDistributor().getDbKey()); + CDistributor dbDistributor(this->getDistributors().findByKeyOrAlias(keyOrAlias)); + + // if no distributor is found, it is now empty because it was invalid + // otherwise replaced with the current DB data + consolidatedModel.setDistributor(dbDistributor); + + // copy over + dbModel = consolidatedModel; + } + + bool someDbData = dbModel.hasValidDbKey() || dbModel.getLivery().hasValidDbKey() || dbModel.getAircraftIcaoCode().hasValidDbKey(); + if (!someDbData) { return model; } // use DB model as base, update everything else dbModel.updateMissingParts(model); return dbModel; } - CAircraftModel CDbStashComponent::consolidateWithOwnModels(const CAircraftModel &model) + CAircraftModel CDbStashComponent::consolidateWithOwnModels(const CAircraftModel &model) const { if (!model.hasModelString()) { return model; } if (model.getModelType() == CAircraftModel::TypeOwnSimulatorModel) { return model; } @@ -355,6 +397,25 @@ namespace BlackGui return ownModel; } + CAircraftModel CDbStashComponent::consolidateModel(const CAircraftModel &model) const + { + CAircraftModel stashModel(model); + + // merge with own models if any + if (stashModel.getModelType() != CAircraftModel::TypeOwnSimulatorModel) + { + stashModel = this->consolidateWithOwnModels(stashModel); + } + + // merge with DB data if any + if (!stashModel.hasValidDbKey()) + { + stashModel = this->consolidateWithDbData(stashModel); + } + + return stashModel; + } + void CDbStashComponent::ps_copyOverPartsToSelected() { QObject *sender = QObject::sender(); diff --git a/src/blackgui/components/dbstashcomponent.h b/src/blackgui/components/dbstashcomponent.h index 49634368d..877558813 100644 --- a/src/blackgui/components/dbstashcomponent.h +++ b/src/blackgui/components/dbstashcomponent.h @@ -40,6 +40,9 @@ namespace BlackGui Q_OBJECT public: + //! Number of models which can be published at once + static const int MaxModelPublished = 1000; + //! Constructor explicit CDbStashComponent(QWidget *parent = nullptr); @@ -91,13 +94,19 @@ namespace BlackGui //! Apply object to select objects void applyToSelected(const BlackMisc::Simulation::CDistributor &distributor, bool acceptWarnings = true); + //! Consolidate with other available data + BlackMisc::Simulation::CAircraftModel consolidateModel(const BlackMisc::Simulation::CAircraftModel &model) const; + public slots: - //! Stash given model + //! Stash given model (includes validation and consolidation with DB data) BlackMisc::CStatusMessage stashModel(const BlackMisc::Simulation::CAircraftModel &model, bool replace = false); - //! Stash given models + //! Stash given models (includes validation and consolidation with DB data) BlackMisc::CStatusMessageList stashModels(const BlackMisc::Simulation::CAircraftModelList &models); + //! Replace models, no validation + void replaceModelsUnvalidated(const BlackMisc::Simulation::CAircraftModelList &models); + signals: //! Unstash void unstashed(BlackMisc::Simulation::CAircraftModel &model); @@ -151,16 +160,16 @@ namespace BlackGui void enableButtonRow(); //! Validation categories - const BlackMisc::CLogCategoryList &validationCats() const; + const BlackMisc::CLogCategoryList &validationCategories() const; //! Get the selected only models or all models depending on checkbox BlackMisc::Simulation::CAircraftModelList getSelectedOrAllModels() const; //! Consolidate with any DB data (if available). - BlackMisc::Simulation::CAircraftModel consolidateWithDbData(const BlackMisc::Simulation::CAircraftModel &model); + BlackMisc::Simulation::CAircraftModel consolidateWithDbData(const BlackMisc::Simulation::CAircraftModel &model) const; //! Consolidate with own models (if available). - BlackMisc::Simulation::CAircraftModel consolidateWithOwnModels(const BlackMisc::Simulation::CAircraftModel &model); + BlackMisc::Simulation::CAircraftModel consolidateWithOwnModels(const BlackMisc::Simulation::CAircraftModel &model) const; }; } // ns } // ns diff --git a/src/blackgui/editors/modelmappingform.cpp b/src/blackgui/editors/modelmappingform.cpp index 54a9180f6..a70af94a4 100644 --- a/src/blackgui/editors/modelmappingform.cpp +++ b/src/blackgui/editors/modelmappingform.cpp @@ -45,10 +45,10 @@ namespace BlackGui return model; } - CStatusMessageList CModelMappingForm::validate(bool withNestedForms) const + CStatusMessageList CModelMappingForm::validate(bool withNestedObjects) const { CAircraftModel model(getValue()); - CStatusMessageList msgs(model.validate(withNestedForms)); + CStatusMessageList msgs(model.validate(withNestedObjects)); this->ui->val_Indicator->setState(msgs); return msgs; } diff --git a/src/blackgui/editors/modelmappingform.h b/src/blackgui/editors/modelmappingform.h index 48eec4c0b..cc485f947 100644 --- a/src/blackgui/editors/modelmappingform.h +++ b/src/blackgui/editors/modelmappingform.h @@ -40,7 +40,7 @@ namespace BlackGui BlackMisc::Simulation::CAircraftModel getValue() const; //! Validate - BlackMisc::CStatusMessageList validate(bool withNestedForms) const; + BlackMisc::CStatusMessageList validate(bool withNestedObjects) const; //! \copydoc CForm::setReadOnly virtual void setReadOnly(bool readOnly) override; @@ -53,9 +53,6 @@ namespace BlackGui void setValue(BlackMisc::Simulation::CAircraftModel &model); signals: - //! Request validation - void requestValidation(); - //! Request stashing for model void requestStash();