Files
pilotclient/src/blackgui/components/dbownmodelscomponent.cpp

756 lines
38 KiB
C++

/* Copyright (C) 2016
* 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. 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 "blackgui/components/dbownmodelscomponent.h"
#include "blackgui/components/simulatorselector.h"
#include "blackgui/guiapplication.h"
#include "blackgui/menus/aircraftmodelmenus.h"
#include "blackgui/menus/menuaction.h"
#include "blackgui/models/aircraftmodellistmodel.h"
#include "blackgui/views/aircraftmodelview.h"
#include "blackcore/webdataservices.h"
#include "blackcore/db/databaseutils.h"
#include "blackmisc/icons.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/statusmessage.h"
#include "blackconfig/buildconfig.h"
#include "ui_dbownmodelscomponent.h"
#include <QAction>
#include <QIcon>
#include <QDir>
#include <QtGlobal>
#include <QPointer>
#include <QFileDialog>
#include <QMessageBox>
using namespace BlackConfig;
using namespace BlackMisc;
using namespace BlackMisc::Simulation;
using namespace BlackCore::Db;
using namespace BlackGui::Menus;
using namespace BlackGui::Views;
using namespace BlackGui::Models;
namespace BlackGui
{
namespace Components
{
CDbOwnModelsComponent::CDbOwnModelsComponent(QWidget *parent) :
COverlayMessagesFrame(parent),
ui(new Ui::CDbOwnModelsComponent)
{
ui->setupUi(this);
ui->comp_SimulatorSelector->setMode(CSimulatorSelector::RadioButtons);
ui->tvp_OwnAircraftModels->setAircraftModelMode(CAircraftModelListModel::OwnAircraftModelMappingTool);
ui->tvp_OwnAircraftModels->addFilterDialog();
ui->tvp_OwnAircraftModels->setDisplayAutomatically(true);
ui->tvp_OwnAircraftModels->setCustomMenu(new CLoadModelsMenu(this));
const CSimulatorInfo sim = ui->comp_SimulatorSelector->getValue();
ui->tvp_OwnAircraftModels->setCorrespondingSimulator(sim, m_simulatorSettings.getSimulatorDirectoryOrDefault(sim));
bool c = connect(ui->tvp_OwnAircraftModels, &CAircraftModelView::requestUpdate, this, &CDbOwnModelsComponent::requestOwnModelsUpdate);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
c = connect(ui->tvp_OwnAircraftModels, &CAircraftModelView::jsonLoadCompleted, this, &CDbOwnModelsComponent::onViewDiskLoadingFinished, Qt::QueuedConnection);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
c = connect(ui->comp_SimulatorSelector, &CSimulatorSelector::changed, this, &CDbOwnModelsComponent::onSimulatorSelectorChanged);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(), &CMultiAircraftModelLoaderProvider::loadingFinished, this, &CDbOwnModelsComponent::onModelLoaderLoadingFinished, Qt::QueuedConnection);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(), &CMultiAircraftModelLoaderProvider::diskLoadingStarted, this, &CDbOwnModelsComponent::onModelLoaderDiskLoadingStarted, Qt::QueuedConnection);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(), &CMultiAircraftModelLoaderProvider::loadingProgress, this, &CDbOwnModelsComponent::onModelLoadingProgress, Qt::QueuedConnection);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(), &CMultiAircraftModelLoaderProvider::cacheChanged, this, &CDbOwnModelsComponent::onCacheChanged, Qt::QueuedConnection);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
c = connect(ui->pb_ForceReload, &QPushButton::released, this, &CDbOwnModelsComponent::confirmedForcedReloadCurrentSimulator, Qt::QueuedConnection);
Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
// Last selection isPinned -> no sync needed
ui->comp_SimulatorSelector->setRememberSelectionAndSetToLastSelection();
const CSimulatorInfo simulator = ui->comp_SimulatorSelector->getValue();
if (simulator.isSingleSimulator())
{
m_simulator = simulator;
this->setUiSimulatorString(simulator);
const bool success = this->initModelLoader(simulator, IAircraftModelLoader::CacheOnly);
if (!success)
{
CLogMessage(this).error(u"Init of model loader failed in component");
}
}
// menu
ui->tvp_OwnAircraftModels->setCustomMenu(new CConsolidateWithDbDataMenu(ui->tvp_OwnAircraftModels, this));
}
CDbOwnModelsComponent::~CDbOwnModelsComponent()
{
// void
}
const CLogCategoryList &CDbOwnModelsComponent::getLogCategories()
{
static const CLogCategoryList l({ CLogCategory::modelGui(), CLogCategory::guiComponent() });
return l;
}
CAircraftModelView *CDbOwnModelsComponent::view() const
{
return ui->tvp_OwnAircraftModels;
}
CAircraftModelListModel *CDbOwnModelsComponent::model() const
{
return ui->tvp_OwnAircraftModels->derivedModel();
}
bool CDbOwnModelsComponent::requestModelsInBackground(const CSimulatorInfo &simulator, bool onlyIfNotEmpty)
{
this->setSimulator(simulator);
if (onlyIfNotEmpty && this->getOwnModelsCount() > 0) { return false; }
const IAircraftModelLoader::LoadMode mode = onlyIfNotEmpty ? IAircraftModelLoader::InBackgroundNoCache : IAircraftModelLoader::LoadInBackground;
this->requestSimulatorModels(simulator, mode);
return true;
}
CAircraftModel CDbOwnModelsComponent::getOwnModelForModelString(const QString &modelString) const
{
return this->getOwnModels().findFirstByModelStringOrDefault(modelString);
}
CAircraftModelList CDbOwnModelsComponent::getOwnModels() const
{
return this->getOwnCachedModels(this->getOwnModelsSimulator());
}
CAircraftModelList CDbOwnModelsComponent::getOwnCachedModels(const CSimulatorInfo &simulator) const
{
static const CAircraftModelList empty;
if (!m_modelLoader) { return empty; }
return m_modelLoader->getCachedModels(simulator);
}
CAircraftModelList CDbOwnModelsComponent::getOwnSelectedModels() const
{
return ui->tvp_OwnAircraftModels->selectedObjects();
}
const CSimulatorInfo CDbOwnModelsComponent::getOwnModelsSimulator() const
{
return ui->comp_SimulatorSelector->getValue();
}
bool CDbOwnModelsComponent::setSimulator(const CSimulatorInfo &simulator, bool forced)
{
Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
if (!forced && m_simulator == simulator) { return false; }
// changed simulator
m_simulator = simulator;
this->requestSimulatorModelsWithCacheInBackground(simulator);
ui->comp_SimulatorSelector->setValue(simulator);
this->setUiSimulatorString(simulator);
ui->tvp_OwnAircraftModels->setCorrespondingSimulator(simulator, m_simulatorSettings.getSimulatorDirectoryOrDefault(simulator));
return true;
}
void CDbOwnModelsComponent::setSimulatorSelectorMode(CSimulatorSelector::Mode mode)
{
ui->comp_SimulatorSelector->setMode(mode);
}
void CDbOwnModelsComponent::onSimulatorSelectorChanged()
{
const CSimulatorInfo simulator(ui->comp_SimulatorSelector->getValue());
this->setSimulator(simulator);
}
int CDbOwnModelsComponent::getOwnModelsCount() const
{
if (!m_modelLoader) { return 0; }
return m_modelLoader->getCachedModelsCount(this->getOwnModelsSimulator());
}
QString CDbOwnModelsComponent::getInfoString() const
{
if (!m_modelLoader) { return {}; }
return m_modelLoader->getInfoString();
}
QString CDbOwnModelsComponent::getInfoStringFsFamily() const
{
if (!m_modelLoader) { return {}; }
return m_modelLoader->getInfoStringFsFamily();
}
CStatusMessage CDbOwnModelsComponent::updateViewAndCache(const CAircraftModelList &models)
{
const CStatusMessage m = m_modelLoader->setCachedModels(models, this->getOwnModelsSimulator());
if (m.isSuccess())
{
ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(models);
}
return m;
}
void CDbOwnModelsComponent::gracefulShutdown()
{
// void
}
void CDbOwnModelsComponent::setModelsForSimulator(const CAircraftModelList &models, const CSimulatorInfo &simulator)
{
if (!m_modelLoader) { return; }
m_modelLoader->setCachedModels(models, simulator);
ui->tvp_OwnAircraftModels->replaceOrAddModelsWithString(models);
}
int CDbOwnModelsComponent::updateModelsForSimulator(const CAircraftModelList &models, const CSimulatorInfo &simulator)
{
if (!m_modelLoader) { return 0; }
const int c = m_modelLoader->updateModelsForSimulator(models, simulator);
const CAircraftModelList allModels(m_modelLoader->getCachedModels(simulator));
ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(allModels);
return c;
}
bool CDbOwnModelsComponent::initModelLoader(const CSimulatorInfo &simulator, IAircraftModelLoader::LoadMode load)
{
// called when simulator is changed / init
Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
// already loaded
if (!m_modelLoader || !m_modelLoader->supportsSimulator(simulator))
{
m_modelLoader = CMultiAircraftModelLoaderProvider::multiModelLoaderInstance().loaderInstance(simulator);
if (m_modelLoader) { m_modelLoader->startLoading(load); }
}
this->setSaveFileName(simulator);
return m_modelLoader && m_modelLoader->supportsSimulator(simulator);
}
void CDbOwnModelsComponent::setSaveFileName(const CSimulatorInfo &sim)
{
Q_ASSERT_X(sim.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
const QString n("simulator models " + sim.toQString(true));
ui->tvp_OwnAircraftModels->setSaveFileName(n);
}
QString CDbOwnModelsComponent::directorySelector(const CSimulatorInfo &simulatorInfo)
{
QString dir = m_directorySettings.get().getLastModelDirectoryOrDefault();
dir = QFileDialog::getExistingDirectory(this, QStringLiteral("Open directory (%1)").arg(simulatorInfo.toQString()), dir,
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
const QDir d(dir);
if (d.exists())
{
CDirectories dirs = m_directorySettings.get();
dirs.setLastModelDirectory(dir);
const CStatusMessage m = m_directorySettings.setAndSave(dirs);
CLogMessage::preformatted(m);
}
return dir;
}
void CDbOwnModelsComponent::setUiSimulatorString(const CSimulatorInfo &simulatorInfo)
{
const QString s = simulatorInfo.toQString(true);
ui->le_Simulator->setText(s);
ui->pb_ForceReload->setText(QStringLiteral("force reload '%1'").arg(s));
}
void CDbOwnModelsComponent::confirmedForcedReloadCurrentSimulator()
{
this->confirmedForcedReload(m_simulator);
}
void CDbOwnModelsComponent::confirmedForcedReload(const CSimulatorInfo &simulator)
{
QMessageBox msgBox(QMessageBox::Question, "Reload models from disk",
QStringLiteral("Completely reload '%1' models from disk?").arg(simulator.toQString(true)),
QMessageBox::Ok | QMessageBox::Cancel, this);
msgBox.setDefaultButton(QMessageBox::Cancel);
const QMessageBox::StandardButton reply = static_cast<QMessageBox::StandardButton>(msgBox.exec());
if (reply != QMessageBox::Ok) { return; }
this->requestSimulatorModels(simulator, IAircraftModelLoader::InBackgroundNoCache);
}
void CDbOwnModelsComponent::CLoadModelsMenu::customMenu(CMenuActions &menuActions)
{
if (!sGui || sGui->isShuttingDown()) { return; }
// for the moment I use all sims, I could restrict to CSimulatorInfo::getLocallyInstalledSimulators();
const CSimulatorInfo sims = CSimulatorInfo::allSimulators();
const bool noSims = sims.isNoSimulator() || sims.isUnspecified();
if (!noSims)
{
QPointer<CDbOwnModelsComponent> ownModelsComp(qobject_cast<CDbOwnModelsComponent *>(this->parent()));
Q_ASSERT_X(ownModelsComp, Q_FUNC_INFO, "Cannot access parent");
if (m_loadActions.isEmpty()) { m_loadActions = QList<QAction *>({nullptr, nullptr, nullptr, nullptr, nullptr}); }
menuActions.addMenuSimulator();
if (sims.isFSX())
{
if (!m_loadActions[0])
{
m_loadActions[0] = new QAction(CIcons::appModels16(), "FSX models", this);
connect(m_loadActions[0], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->setSimulator(CSimulatorInfo::fsx(), true);
});
}
menuActions.addAction(m_loadActions[0], CMenuAction::pathSimulator());
}
if (sims.isP3D())
{
if (!m_loadActions[1])
{
m_loadActions[1] = new QAction(CIcons::appModels16(), "P3D models", this);
connect(m_loadActions[1], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->setSimulator(CSimulatorInfo::p3d(), true);
});
}
menuActions.addAction(m_loadActions[1], CMenuAction::pathSimulator());
}
if (sims.isFS9())
{
if (!m_loadActions[2])
{
m_loadActions[2] = new QAction(CIcons::appModels16(), "FS9 models", this);
connect(m_loadActions[2], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->setSimulator(CSimulatorInfo::fs9(), true);
});
}
menuActions.addAction(m_loadActions[2], CMenuAction::pathSimulator());
}
if (sims.isXPlane())
{
if (!m_loadActions[3])
{
m_loadActions[3] = new QAction(CIcons::appModels16(), "XPlane models", this);
connect(m_loadActions[3], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->setSimulator(CSimulatorInfo::xplane(), true);
});
}
menuActions.addAction(m_loadActions[3], CMenuAction::pathSimulator());
}
if (sims.isFG())
{
if (!m_loadActions[4])
{
m_loadActions[4] = new QAction(CIcons::appModels16(), "FG models", this);
connect(m_loadActions[4], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->setSimulator(CSimulatorInfo::fg(), true);
});
}
menuActions.addAction(m_loadActions[4], CMenuAction::pathSimulator());
}
// with models loaded I allow a refresh reload
// I need those models because I want to merge with DB data in the loader
if (sGui && sGui->getWebDataServices() && sGui->getWebDataServices()->getModelsCount() > 0)
{
if (m_reloadActions.isEmpty()) { m_reloadActions = QList<QAction *>({nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}); }
menuActions.addMenu(CIcons::refresh16(), "Force model reload", CMenuAction::pathSimulatorModelsReload());
if (sims.isFSX())
{
if (!m_reloadActions[0])
{
m_reloadActions[0] = new QAction(CIcons::appModels16(), "FSX models", this);
connect(m_reloadActions[0], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->requestSimulatorModels(CSimulatorInfo::fsx(), IAircraftModelLoader::InBackgroundNoCache);
});
m_reloadActions[1] = new QAction(CIcons::appModels16(), "FSX models from directory", this);
connect(m_reloadActions[1], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
const CSimulatorInfo sim(CSimulatorInfo::FSX);
const QString dir = ownModelsComp->directorySelector(sim);
if (!dir.isEmpty())
{
ownModelsComp->requestSimulatorModels(sim, IAircraftModelLoader::InBackgroundNoCache, QStringList(dir));
}
});
}
menuActions.addAction(m_reloadActions[0], CMenuAction::pathSimulatorModelsReload());
menuActions.addAction(m_reloadActions[1], CMenuAction::pathSimulatorModelsReload());
}
if (sims.isP3D())
{
if (!m_reloadActions[2])
{
m_reloadActions[2] = new QAction(CIcons::appModels16(), "P3D models", this);
connect(m_reloadActions[2], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->requestSimulatorModels(CSimulatorInfo::p3d(), IAircraftModelLoader::InBackgroundNoCache);
});
m_reloadActions[3] = new QAction(CIcons::appModels16(), "P3D models from directoy", this);
connect(m_reloadActions[3], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
const CSimulatorInfo sim(CSimulatorInfo::P3D);
const QString dir = ownModelsComp->directorySelector(sim);
if (!dir.isEmpty())
{
ownModelsComp->requestSimulatorModels(sim, IAircraftModelLoader::InBackgroundNoCache, QStringList(dir));
}
});
}
menuActions.addAction(m_reloadActions[2], CMenuAction::pathSimulatorModelsReload());
menuActions.addAction(m_reloadActions[3], CMenuAction::pathSimulatorModelsReload());
}
if (sims.isFS9())
{
if (!m_reloadActions[4])
{
m_reloadActions[4] = new QAction(CIcons::appModels16(), "FS9 models", this);
connect(m_reloadActions[4], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->requestSimulatorModels(CSimulatorInfo::fs9(), IAircraftModelLoader::InBackgroundNoCache);
});
m_reloadActions[5] = new QAction(CIcons::appModels16(), "FS9 models from directoy", this);
connect(m_reloadActions[5], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
const CSimulatorInfo sim(CSimulatorInfo::FS9);
const QString dir = ownModelsComp->directorySelector(sim);
if (!dir.isEmpty())
{
ownModelsComp->requestSimulatorModels(sim, IAircraftModelLoader::InBackgroundNoCache, QStringList(dir));
}
});
}
menuActions.addAction(m_reloadActions[4], CMenuAction::pathSimulatorModelsReload());
menuActions.addAction(m_reloadActions[5], CMenuAction::pathSimulatorModelsReload());
}
if (sims.isXPlane())
{
if (!m_reloadActions[6])
{
m_reloadActions[6] = new QAction(CIcons::appModels16(), "XPlane models", this);
connect(m_reloadActions[6], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->requestSimulatorModels(CSimulatorInfo::xplane(), IAircraftModelLoader::InBackgroundNoCache);
});
m_reloadActions[7] = new QAction(CIcons::appModels16(), "XPlane models from directoy", this);
connect(m_reloadActions[7], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
const CSimulatorInfo sim(CSimulatorInfo::XPLANE);
const QString dir = ownModelsComp->directorySelector(sim);
if (!dir.isEmpty())
{
ownModelsComp->requestSimulatorModels(sim, IAircraftModelLoader::InBackgroundNoCache, QStringList(dir));
}
});
}
menuActions.addAction(m_reloadActions[6], CMenuAction::pathSimulatorModelsReload());
menuActions.addAction(m_reloadActions[7], CMenuAction::pathSimulatorModelsReload());
}
if (sims.isFG())
{
if (!m_reloadActions[8])
{
m_reloadActions[8] = new QAction(CIcons::appModels16(), "FG models", this);
connect(m_reloadActions[8], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->requestSimulatorModels(CSimulatorInfo::fg(), IAircraftModelLoader::InBackgroundNoCache);
});
m_reloadActions[9] = new QAction(CIcons::appModels16(), "FG models from directoy", this);
connect(m_reloadActions[9], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
const CSimulatorInfo sim(CSimulatorInfo::FG);
const QString dir = ownModelsComp->directorySelector(sim);
if (!dir.isEmpty())
{
ownModelsComp->requestSimulatorModels(sim, IAircraftModelLoader::InBackgroundNoCache, QStringList(dir));
}
});
}
menuActions.addAction(m_reloadActions[8], CMenuAction::pathSimulatorModelsReload());
menuActions.addAction(m_reloadActions[9], CMenuAction::pathSimulatorModelsReload());
}
}
else
{
// dummy action grayed out
CMenuAction a = menuActions.addAction(CIcons::refresh16(), "Force model reload impossible, no DB data", CMenuAction::pathSimulator());
a.setActionEnabled(false); // gray out
}
if (m_clearCacheActions.isEmpty()) { m_clearCacheActions = QList<QAction *>({nullptr, nullptr, nullptr, nullptr, nullptr}); }
menuActions.addMenu(CIcons::delete16(), "Clear model caches", CMenuAction::pathSimulatorModelsClearCache());
if (sims.isFSX())
{
if (!m_clearCacheActions[0])
{
m_clearCacheActions[0] = new QAction(CIcons::appModels16(), "Clear FSX cache", this);
connect(m_loadActions[0], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->clearSimulatorCache(CSimulatorInfo::fsx());
});
}
menuActions.addAction(m_clearCacheActions[0], CMenuAction::pathSimulatorModelsClearCache());
}
if (sims.isP3D())
{
if (!m_clearCacheActions[1])
{
m_clearCacheActions[1] = new QAction(CIcons::appModels16(), "Clear P3D cache", this);
connect(m_clearCacheActions[1], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->clearSimulatorCache(CSimulatorInfo::p3d());
});
}
menuActions.addAction(m_clearCacheActions[1], CMenuAction::pathSimulatorModelsClearCache());
}
if (sims.isFS9())
{
if (!m_clearCacheActions[2])
{
m_clearCacheActions[2] = new QAction(CIcons::appModels16(), "Clear FS9 cache", this);
connect(m_clearCacheActions[2], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->clearSimulatorCache(CSimulatorInfo::fs9());
});
}
menuActions.addAction(m_clearCacheActions[2], CMenuAction::pathSimulatorModelsClearCache());
}
if (sims.isXPlane())
{
if (!m_clearCacheActions[3])
{
m_clearCacheActions[3] = new QAction(CIcons::appModels16(), "Clear XPlane cache", this);
connect(m_clearCacheActions[3], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->clearSimulatorCache(CSimulatorInfo::xplane());
});
}
menuActions.addAction(m_clearCacheActions[3], CMenuAction::pathSimulatorModelsClearCache());
}
if (sims.isFG())
{
if (!m_clearCacheActions[4])
{
m_clearCacheActions[4] = new QAction(CIcons::appModels16(), "Clear FG cache", this);
connect(m_clearCacheActions[3], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked)
{
if (!ownModelsComp) { return; }
Q_UNUSED(checked);
ownModelsComp->clearSimulatorCache(CSimulatorInfo::fg());
});
}
menuActions.addAction(m_clearCacheActions[4], CMenuAction::pathSimulatorModelsClearCache());
}
}
this->nestedCustomMenu(menuActions);
}
void CDbOwnModelsComponent::requestOwnModelsUpdate()
{
if (!m_modelLoader) { return; }
ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(this->getOwnModels());
}
void CDbOwnModelsComponent::loadInstalledModels(const CSimulatorInfo &simulator, IAircraftModelLoader::LoadMode mode, const QStringList &modelDirectories)
{
if (!m_modelLoader) { return; }
// here m_modelLoader is still the "current" loader
if (m_modelLoader->isLoadingInProgress())
{
if (m_modelLoader->supportsSimulator(simulator))
{
const CStatusMessage msg = CLogMessage(this).warning(u"Loading for '%1' already in progress, will NOT load.") << simulator.toQString();
this->showOverlayMessage(msg);
return;
}
else
{
const CStatusMessage msg = CLogMessage(this).warning(u"Loading for another simulator '%1' already in progress. Loading might be slow.") << simulator.toQString();
this->showOverlayMessage(msg);
}
}
if (!this->initModelLoader(simulator))
{
const CStatusMessage msg = CLogMessage(this).error(u"Cannot init model loader for %1") << simulator.toQString();
this->showOverlayMessage(msg);
return;
}
// Do not check for empty models die here, as depending on mode we could still load
// will be checked in model loader
CLogMessage(this).info(u"Starting loading for '%1' in mode '%2'") << simulator.toQString() << IAircraftModelLoader::enumToString(mode);
ui->tvp_OwnAircraftModels->showLoadIndicator();
Q_ASSERT_X(sGui && sGui->getWebDataServices(), Q_FUNC_INFO, "missing web data services");
m_modelLoader->startLoading(mode, static_cast<int (*)(CAircraftModelList &, bool)>(&CDatabaseUtils::consolidateModelsWithDbData), modelDirectories);
}
void CDbOwnModelsComponent::onModelLoaderDiskLoadingStarted(const CSimulatorInfo &simulator, IAircraftModelLoader::LoadMode mode)
{
const CStatusMessage msg = CLogMessage(this).info(u"Started disk loading for '%1' in mode '%2'") << simulator.toQString(true) << IAircraftModelLoader::enumToString(mode);
this->showOverlayHTMLMessage(msg, 5000);
}
void CDbOwnModelsComponent::onModelLoadingProgress(const CSimulatorInfo &simulator, const QString &message, int progress)
{
const CStatusMessage loadingMsg = CStatusMessage(this).info(u"%1 loading: %2") << simulator.toQString(true) << message;
this->showOverlayHTMLMessage(loadingMsg, 5000);
ui->tvp_OwnAircraftModels->showLoadIndicatorWithTimeout(5000); // trigger new load indicator
Q_UNUSED(progress);
}
void CDbOwnModelsComponent::onModelLoaderLoadingFinished(const CStatusMessageList &statusMessages, const CSimulatorInfo &simulator, IAircraftModelLoader::LoadFinishedInfo info)
{
Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Expect single simulator");
bool hideIndicator = false; // hide in case loading failed
if (IAircraftModelLoader::isLoadedInfo(info) && m_modelLoader)
{
const CAircraftModelList models(m_modelLoader->getCachedModels(simulator));
const int modelsLoaded = models.size();
ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(models);
CStatusMessage m;
if (modelsLoaded < 1)
{
// loading ok, but no data
m = CLogMessage(this).warning(u"Loading completed for simulator '%1', but no models") << simulator;
hideIndicator = true;
}
else
{
m = CLogMessage(this).info(u"Loading completed for simulator '%1' with %2 models") << simulator << modelsLoaded;
}
// overlay
if (!m.isEmpty() && info == IAircraftModelLoader::ParsedData)
{
this->showOverlayHTMLMessage(m, 5000);
}
// signal
emit this->successfullyLoadedModels(simulator, modelsLoaded);
}
else if (info == IAircraftModelLoader::LoadingSkipped)
{
CLogMessage(this).error(u"Loading of models skipped, simulator '%1'") << simulator.toQString();
hideIndicator = true;
}
else
{
ui->tvp_OwnAircraftModels->clear();
hideIndicator = true;
CLogMessage(this).error(u"Loading of models failed, simulator '%1'") << simulator.toQString();
}
// with errors we make sure errors are on top
int timeoutMs = -1;
if (statusMessages.hasErrorMessages())
{
this->setOverlayMessagesSorting(CStatusMessage::IndexSeverityAsIcon, Qt::DescendingOrder);
}
else if (!statusMessages.hasWarningOrErrorMessages())
{
// no issues
timeoutMs = 5000;
}
this->showOverlayMessages(statusMessages, false, timeoutMs);
if (hideIndicator) { ui->tvp_OwnAircraftModels->hideLoadIndicatorForced(); }
// cache loads may occur in background, do not adjust UI settings
if (info == IAircraftModelLoader::CacheLoaded) { return; }
// parsed loads normally explicit displaying this simulator
this->setSimulator(simulator);
}
void CDbOwnModelsComponent::onViewDiskLoadingFinished(const CStatusMessage &status)
{
if (status.isFailure()) { return; }
QMessageBox msgBox(QMessageBox::Question, "Loaded models from disk", "Loaded models from disk file.\nSave to cache or just temporarily keep them?\n\nHint: Saving them will override the loaded models from the simulator.\nNormally you would not want that (cancel).", QMessageBox::Save | QMessageBox::Cancel, this);
msgBox.setDefaultButton(QMessageBox::Cancel);
const QMessageBox::StandardButton reply = static_cast<QMessageBox::StandardButton>(msgBox.exec());
if (reply != QMessageBox::Cancel) { return; }
const CAircraftModelList models = ui->tvp_OwnAircraftModels->container();
if (models.isEmpty()) { return; }
const CSimulatorInfo simulator = ui->comp_SimulatorSelector->getValue();
m_modelLoader->setModelsForSimulator(models, simulator);
}
void CDbOwnModelsComponent::onCacheChanged(const CSimulatorInfo &simulator)
{
const CAircraftModelList models(m_modelLoader->getCachedModels(simulator));
ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(models);
}
void CDbOwnModelsComponent::requestSimulatorModels(const CSimulatorInfo &simulator, IAircraftModelLoader::LoadMode mode, const QStringList &modelDirectories)
{
this->loadInstalledModels(simulator, mode, modelDirectories);
}
void CDbOwnModelsComponent::requestSimulatorModelsWithCacheInBackground(const CSimulatorInfo &simulator)
{
this->requestSimulatorModels(simulator, IAircraftModelLoader::InBackgroundWithCache);
}
void CDbOwnModelsComponent::clearSimulatorCache(const CSimulatorInfo &simulator)
{
if (!m_modelLoader) { return; }
m_modelLoader->clearCachedModels(simulator);
}
} // ns
} // ns