From 0a51c0a7b71688893a2a1a54ce8fbf146e94c472 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Thu, 24 Sep 2015 01:12:25 +0200 Subject: [PATCH] refs #452 mapping component where mappings can be performed --- .../components/dbmappingcomponent.cpp | 373 +++++++++++++++++ src/blackgui/components/dbmappingcomponent.h | 151 +++++++ src/blackgui/components/dbmappingcomponent.ui | 376 ++++++++++++++++++ 3 files changed, 900 insertions(+) create mode 100644 src/blackgui/components/dbmappingcomponent.cpp create mode 100644 src/blackgui/components/dbmappingcomponent.h create mode 100644 src/blackgui/components/dbmappingcomponent.ui diff --git a/src/blackgui/components/dbmappingcomponent.cpp b/src/blackgui/components/dbmappingcomponent.cpp new file mode 100644 index 000000000..dcebb4c61 --- /dev/null +++ b/src/blackgui/components/dbmappingcomponent.cpp @@ -0,0 +1,373 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "dbmappingcomponent.h" +#include "ui_dbmappingcomponent.h" +#include "blackmisc/simulation/fscommon/aircraftcfgparser.h" +#include "blackmisc/logmessage.h" +#include "blackmisc/project.h" +#include "blackgui/guiutility.h" + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Simulation; +using namespace BlackMisc::Simulation::FsCommon; +using namespace BlackGui; +using namespace BlackGui::Editors; +using namespace BlackGui::Views; +using namespace BlackGui::Models; + +namespace BlackGui +{ + namespace Components + { + CDbMappingComponent::CDbMappingComponent(QWidget *parent) : + COverlayMessagesFrame(parent), + ui(new Ui::CDbMappingComponent) + { + ui->setupUi(this); + this->ui->tvp_AircraftModelsForVPilot->setAircraftModelMode(CAircraftModelListModel::VPilotRuleModel); + connect(ui->editor_Model, &CModelMappingForm::requestSave, this, &CDbMappingComponent::save); + connect(ui->tvp_OwnAircraftModels, &CAircraftModelView::doubleClicked, this, &CDbMappingComponent::ps_onModelRowSelected); + connect(ui->tvp_OwnAircraftModels, &CAircraftModelView::rowCountChanged, this, &CDbMappingComponent::ps_onOwnModelsCountChanged); + + ui->tvp_OwnAircraftModels->setCustomMenu(new CMappingSimulatorModelMenu(this)); + ui->tvp_OwnAircraftModels->setDisplayAutomatically(true); + + ui->editor_AircraftIcao->setMappingMode(); + ui->editor_Distributor->setMappingMode(); + ui->editor_Livery->setMappingMode(); + + initVPilotLoading(); + } + + CDbMappingComponent::~CDbMappingComponent() + { + gracefulShutdown(); + } + + void CDbMappingComponent::initVPilotLoading() + { + if (CProject::isRunningOnWindowsNtPlatform() && CProject::isCompiledWithMsFlightSimulatorSupport()) + { + this->m_withVPilot = true; + this->ui->tab_VPilot->setEnabled(true); + this->ui->tvp_AircraftModelsForVPilot->setCustomMenu(new CMappingVPilotMenu(this)); + this->ui->tvp_AircraftModelsForVPilot->setDisplayAutomatically(true); + connect(ui->tvp_AircraftModelsForVPilot, &CAircraftModelView::doubleClicked, this, &CDbMappingComponent::ps_onModelRowSelected); + connect(ui->tvp_AircraftModelsForVPilot, &CAircraftModelView::rowCountChanged, this, &CDbMappingComponent::ps_onVPilotCountChanged); + connect(&m_vPilotReader, &CVPilotRulesReader::readFinished, this, &CDbMappingComponent::ps_onLoadVPilotDataFinished); + } + else + { + this->m_withVPilot = false; + this->ui->tab_VPilot->setEnabled(false); + } + } + + bool CDbMappingComponent::initModelLoader(const CSimulatorInfo &simInfo) + { + // already loaded + if (this->m_modelLoader && this->m_modelLoader->supportsSimulator(simInfo)) { return true; } + + // unload old + if (this->m_modelLoader) { this->m_modelLoader->cancelLoading(); } + + //! \todo appropriate model loader or loaders via factory? + this->m_modelLoader.reset(IAircraftModelLoader::createModelLoader(simInfo)); + if (!this->m_modelLoader || !this->m_modelLoader->supportsSimulator(simInfo)) + { + CLogMessage(this).error("Failed to init model loader %1") << simInfo.toQString(); + this->m_modelLoader.reset(); + return false; + } + else + { + bool c = connect(this->m_modelLoader.data(), &IAircraftModelLoader::loadingFinished, this, &CDbMappingComponent::ps_onInstalledModelLoadingFinished); + Q_ASSERT_X(c, Q_FUNC_INFO, "Failed connect for model loader"); + Q_UNUSED(c); + return true; + } + } + + void CDbMappingComponent::setProvider(BlackMisc::Network::IWebDataServicesProvider *provider) + { + CWebDataServicesAware::setProvider(provider); + this->ui->editor_Livery->setProvider(provider); + this->ui->editor_Distributor->setProvider(provider); + this->ui->editor_AircraftIcao->setProvider(provider); + } + + void CDbMappingComponent::gracefulShutdown() + { + this->disconnect(); + CWebDataServicesAware::gracefulShutdown(); + this->m_vPilotReader.gracefulShutdown(); + if (this->m_modelLoader) { this->m_modelLoader->gracefulShutdown(); } + } + + CStatusMessageList CDbMappingComponent::validate(bool withNestedForms) const + { + CStatusMessageList msgs(this->ui->editor_Model->validate(!withNestedForms)); + if (withNestedForms) + { + msgs.push_back(ui->editor_AircraftIcao->validate()); + msgs.push_back(ui->editor_Livery->validate(withNestedForms)); + msgs.push_back(ui->editor_Distributor->validate()); + } + return msgs; + } + + void CDbMappingComponent::save() + { + CStatusMessageList msgs(validate(true)); + if (msgs.hasErrorMessages()) + { + CLogMessage::preformatted(msgs); + this->showMessages(msgs); + return; + } + + CAircraftModel model(getAircraftModel()); + msgs = this->asyncWriteModel(model); + if (!msgs.isEmpty()) + { + CLogMessage(this).preformatted(msgs); + } + } + + void CDbMappingComponent::resizeForSelect() + { + int h = this->height(); + int h1 = h / 3 * 2; + int h2 = h / 3; + QList sizes({h1, h2}); + this->ui->sp_MappingComponent->setSizes(sizes); + } + + void CDbMappingComponent::resizeForMapping() + { + int h = this->height(); // total height + int h2 = ui->qw_EditorsScrollArea->minimumHeight(); + h2 *= 1.10; // desired height of inner widget + some space for scrollarea + int currentSize = ui->sp_MappingComponent->sizes().last(); // current size + if (h2 <= currentSize) { return; } + + int h1; + if (h * 0.90 > h2) + { + // enough space to display as whole + h1 = h - h2; + } + else + { + h1 = h / 3; + h2 = h / 3 * 2; + } + QList sizes({h1, h2}); + this->ui->sp_MappingComponent->setSizes(sizes); + } + + void CDbMappingComponent::ps_loadVPilotData() + { + if (this->m_vPilotReader.readASync(true)) + { + CLogMessage(this).info("Start loading vPilot rulesets"); + this->ui->tvp_AircraftModelsForVPilot->showLoadIndicator(); + } + else + { + CLogMessage(this).warning("Loading vPilot rulesets already in progress"); + } + } + + void CDbMappingComponent::ps_onLoadVPilotDataFinished(bool success) + { + if (!m_withVPilot) { return; } + if (success) + { + CLogMessage(this).info("Loading vPilot ruleset completed"); + if (this->ui->tvp_AircraftModelsForVPilot->displayAutomatically()) + { + this->ui->tvp_AircraftModelsForVPilot->updateContainerMaybeAsync( + this->m_vPilotReader.getAsModels() + ); + } + } + else + { + CLogMessage(this).error("Loading vPilot ruleset failed"); + } + this->ui->tvp_OwnAircraftModels->hideLoadIndicator(); + } + + void CDbMappingComponent::ps_onVPilotCountChanged(int count, bool withFilter) + { + if (!m_withVPilot) { return; } + Q_UNUSED(count); + Q_UNUSED(withFilter); + int i = this->ui->tw_ModelsToBeMapped->indexOf(this->ui->tab_VPilot); + QString o = this->ui->tw_ModelsToBeMapped->tabText(i); + QString f = this->ui->tvp_AircraftModelsForVPilot->derivedModel()->hasFilter() ? "F" : ""; + o = CGuiUtility::replaceTabCountValue(o, this->ui->tvp_AircraftModelsForVPilot->rowCount()) + f; + this->ui->tw_ModelsToBeMapped->setTabText(i, o); + } + + void CDbMappingComponent::ps_onOwnModelsCountChanged(int count, bool withFilter) + { + Q_UNUSED(count); + Q_UNUSED(withFilter); + int i = this->ui->tw_ModelsToBeMapped->indexOf(this->ui->tab_OwnModels); + QString o = this->ui->tw_ModelsToBeMapped->tabText(i); + if (this->m_modelLoader) + { + QString sims(this->m_modelLoader->supportedSimulatorsAsString()); + if (!sims.isEmpty()) { o = o.append(" ").append(sims); } + } + QString f = this->ui->tvp_OwnAircraftModels->derivedModel()->hasFilter() ? "F" : ""; + o = CGuiUtility::replaceTabCountValue(o, this->ui->tvp_AircraftModelsForVPilot->rowCount()) + f; + this->ui->tw_ModelsToBeMapped->setTabText(i, o); + } + + void CDbMappingComponent::ps_requestSimulatorModels() + { + QAction *a = qobject_cast(QObject::sender()); + if (!a) { return; } + int f = a->data().toInt(); + CSimulatorInfo sim(f); + this->ps_loadInstalledModels(sim); + } + + void CDbMappingComponent::ps_onModelRowSelected(const QModelIndex &index) + { + QObject *sender = QObject::sender(); + CAircraftModel model; + if (sender == this->ui->tvp_AircraftModelsForVPilot) + { + model = this->ui->tvp_AircraftModelsForVPilot->at(index); + } + else if (sender == this->ui->tvp_OwnAircraftModels) + { + model = this->ui->tvp_OwnAircraftModels->at(index); + } + else + { + return; + } + this->ui->editor_Model->setValue(model); + + const CLivery livery(this->smartLiverySelector(model.getLivery())); + const CAircraftIcaoCode aircraftIcao(this->smartAircraftIcaoSelector(model.getAircraftIcaoCode())); + const CDistributor distributor(this->smartDistributorSelector(model.getDistributor())); + + // if found, then set in editor + if (livery.hasValidDbKey()) { this->ui->editor_Livery->setValue(livery); } + else { this->ui->editor_Livery->clear(); } + if (aircraftIcao.hasValidDbKey()) { this->ui->editor_AircraftIcao->setValue(aircraftIcao); } + else { this->ui->editor_AircraftIcao->clear(); } + if (distributor.hasValidDbKey()) { this->ui->editor_Distributor->setValue(distributor); } + else { this->ui->editor_Distributor->clear(); } + + // request filtering + emit filterByLivery(model.getLivery()); + emit filterByAircraftIcao(model.getAircraftIcaoCode()); + emit filterByDistributor(model.getDistributor()); + } + + void CDbMappingComponent::ps_loadInstalledModels(const CSimulatorInfo &simInfo) + { + //! \todo, load correct loader + if (!this->initModelLoader(simInfo)) + { + CLogMessage(this).error("Cannot load model loader for %1") << simInfo.toQString(); + return; + } + + if (!this->m_modelLoader->isLoadingFinished()) + { + CLogMessage(this).info("Loading for %1 already in progress") << simInfo.toQString(); + return; + } + + CLogMessage(this).info("Starting loading for %1") << simInfo.toQString(); + this->m_modelLoader->startLoading(); + this->ui->tvp_OwnAircraftModels->showLoadIndicator(); + } + + void CDbMappingComponent::ps_onInstalledModelLoadingFinished(bool success) + { + if (success && this->m_modelLoader) + { + CLogMessage(this).info("Loading of models completed"); + if (this->ui->tvp_OwnAircraftModels->displayAutomatically()) + { + this->ui->tvp_OwnAircraftModels->updateContainer( + this->m_modelLoader->getAircraftModels() + ); + } + } + else + { + CLogMessage(this).error("Loading of models failed, simulator"); + this->ui->tvp_OwnAircraftModels->hideLoadIndicator(); + } + this->ui->tvp_OwnAircraftModels->hideLoadIndicator(); + } + + CAircraftModel CDbMappingComponent::getAircraftModel() const + { + CAircraftModel model(ui->editor_Model->getValue()); + model.setDistributor(ui->editor_Distributor->getValue()); + model.setAircraftIcaoCode(ui->editor_AircraftIcao->getValue()); + model.setLivery(ui->editor_Livery->getValue()); + return model; + } + + void CDbMappingComponent::CMappingSimulatorModelMenu::customMenu(QMenu &menu) const + { + CSimulatorInfo sims = CSimulatorInfo::getLocallyInstalledSimulators(); + QMenu *load = menu.addMenu(CIcons::appModels16(), "Load installed models"); + QAction *a = nullptr; + CDbMappingComponent *mapComp = qobject_cast(this->parent()); + Q_ASSERT_X(mapComp, Q_FUNC_INFO, "Cannot access parent"); + + if (sims.fs9()) + { + a = load->addAction(CIcons::appModels16(), "FS9 models", mapComp, SLOT(ps_requestSimulatorModels())); + a->setData(QVariant(static_cast(CSimulatorInfo::FS9))); + } + if (sims.fsx()) + { + a = load->addAction(CIcons::appModels16(), "FSX models", mapComp, SLOT(ps_requestSimulatorModels())); + a->setData(QVariant(static_cast(CSimulatorInfo::FSX))); + } + if (sims.p3d()) + { + a = load->addAction(CIcons::appModels16(), "P3D models", mapComp, SLOT(ps_requestSimulatorModels())); + a->setData(QVariant(static_cast(CSimulatorInfo::P3D))); + } + if (sims.xplane()) + { + a = load->addAction(CIcons::appModels16(), "XPlane models", mapComp, SLOT(ps_requestSimulatorModels())); + a->setData(QVariant(static_cast(CSimulatorInfo::XPLANE))); + } + menu.addSeparator(); + } + + void CDbMappingComponent::CMappingVPilotMenu::customMenu(QMenu &menu) const + { + CDbMappingComponent *mapComp = qobject_cast(this->parent()); + Q_ASSERT_X(mapComp, Q_FUNC_INFO, "Cannot access parent"); + + menu.addAction(CIcons::appMappings16(), "Load vPilot Rules", mapComp, SLOT(ps_loadVPilotData())); + menu.addSeparator(); + } + + } // ns +} // ns diff --git a/src/blackgui/components/dbmappingcomponent.h b/src/blackgui/components/dbmappingcomponent.h new file mode 100644 index 000000000..d0bd760b7 --- /dev/null +++ b/src/blackgui/components/dbmappingcomponent.h @@ -0,0 +1,151 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKGUI_COMPONENTS_DBMAPPINGCOMPONENT_H +#define BLACKGUI_COMPONENTS_DBMAPPINGCOMPONENT_H + +#include "blackgui/blackguiexport.h" +#include "blackgui/overlaymessagesframe.h" +#include "blackgui/menudelegate.h" +#include "blackgui/components/enablefordockwidgetinfoarea.h" +#include "blackmisc/simulation/aircraftmodelloader.h" +#include "blackmisc/simulation/fscommon/vpilotrulesreader.h" +#include "blackmisc/network/webdataservicesprovider.h" +#include "blackmisc/statusmessagelist.h" +#include +#include + +namespace Ui { class CDbMappingComponent; } + +namespace BlackGui +{ + namespace Components + { + /*! + * Mapping component + */ + class BLACKGUI_EXPORT CDbMappingComponent : + public BlackGui::COverlayMessagesFrame, + public CEnableForDockWidgetInfoArea, + public BlackMisc::Network::CWebDataServicesAware + { + Q_OBJECT + + public: + //! Constructor + explicit CDbMappingComponent(QWidget *parent = nullptr); + + //! Destructor + ~CDbMappingComponent(); + + //! \copydoc CWebDataReaderAware::setProvider + virtual void setProvider(BlackMisc::Network::IWebDataServicesProvider *provider) override; + + //! Graceful shutdown + void gracefulShutdown(); + + signals: + //! Request to filter by livery + void filterByLivery(const BlackMisc::Aviation::CLivery &livery); + + //! Request to filter by aircraft ICAO + void filterByAircraftIcao(const BlackMisc::Aviation::CAircraftIcaoCode &icao); + + //! Request to filter by distributor + void filterByDistributor(const BlackMisc::Simulation::CDistributor &distributor); + + public slots: + //! Validate, empty list means OK + BlackMisc::CStatusMessageList validate(bool withNestedForms) const; + + //! Save + void save(); + + //! Resize so that selection is easy (larger table view) + void resizeForSelect(); + + //! Resize so that mapping is easier + void resizeForMapping(); + + private slots: + //! Load the vPilot rules + void ps_loadVPilotData(); + + //! Data for vPilot have been loaded + void ps_onLoadVPilotDataFinished(bool success); + + //! Row count for vPilot data changed + void ps_onVPilotCountChanged(int count, bool withFilter); + + //! Row has been selected + void ps_onModelRowSelected(const QModelIndex &index); + + //! Load the models + void ps_loadInstalledModels(const BlackMisc::Simulation::CSimulatorInfo &simInfo); + + //! Model loading finished + void ps_onInstalledModelLoadingFinished(bool success); + + //! Own model count changed + void ps_onOwnModelsCountChanged(int count, bool withFilter); + + //! Request simulator models + void ps_requestSimulatorModels(); + + private: + QScopedPointer ui; + BlackMisc::Simulation::FsCommon::CVPilotRulesReader m_vPilotReader; + QScopedPointer m_modelLoader; + bool m_withVPilot = false; + + //! Consolidated aircraft model + BlackMisc::Simulation::CAircraftModel getAircraftModel() const; + + //! Init vPilot loading is suitable + void initVPilotLoading(); + + //! Init model loader + bool initModelLoader(const BlackMisc::Simulation::CSimulatorInfo &simInfo); + + // -------------------- component specifi menus -------------------------- + + //! The menu for loading and handling own models for mapping + //! \note This is specific for that very component + class CMappingSimulatorModelMenu : public BlackGui::IMenuDelegate + { + public: + //! Constructor + CMappingSimulatorModelMenu(CDbMappingComponent *mappingComponent) : + BlackGui::IMenuDelegate(mappingComponent) + {} + + //! \copydoc IMenuDelegate::customMenu + virtual void customMenu(QMenu &menu) const override; + }; + + //! The menu for loading and handling VPilot rules for mapping + //! \note This is specific for that very component + class CMappingVPilotMenu : public BlackGui::IMenuDelegate + { + public: + //! Constructor + CMappingVPilotMenu(CDbMappingComponent *mappingComponent) : + BlackGui::IMenuDelegate(mappingComponent) + {} + + //! \copydoc IMenuDelegate::customMenu + virtual void customMenu(QMenu &menu) const override; + }; + }; + + } // ns +} // ns +#endif // guard diff --git a/src/blackgui/components/dbmappingcomponent.ui b/src/blackgui/components/dbmappingcomponent.ui new file mode 100644 index 000000000..aac427e0d --- /dev/null +++ b/src/blackgui/components/dbmappingcomponent.ui @@ -0,0 +1,376 @@ + + + CDbMappingComponent + + + + 0 + 0 + 266 + 618 + + + + Frame + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + Own models + + + + 4 + + + 0 + + + 2 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + + + + + vPilot rules + + + + 4 + + + 0 + + + 2 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + + + + + + + + + 0 + 75 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + + 0 + 0 + 245 + 375 + + + + + 0 + 375 + + + + + 4 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Qt::Vertical + + + + 20 + 334 + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + + + + BlackGui::Views::CAircraftModelView + QTableView +
blackgui/views/aircraftmodelview.h
+
+ + BlackGui::Editors::CAircraftIcaoForm + QFrame +
blackgui/editors/aircrafticaoform.h
+ 1 +
+ + BlackGui::Editors::CLiveryForm + QFrame +
blackgui/editors/liveryform.h
+ 1 +
+ + BlackGui::Editors::CDistributorForm + QFrame +
blackgui/editors/distributorform.h
+ 1 +
+ + BlackGui::Editors::CModelMappingForm + QFrame +
blackgui/editors/modelmappingform.h
+ 1 +
+ + BlackGui::COverlayMessagesFrame + QFrame +
blackgui/overlaymessagesframe.h
+ 1 +
+
+ + +