10 #include <QMessageBox>
14 #include "ui_dbownmodelscomponent.h"
21 #include "gui/menus/aircraftmodelmenus.h"
22 #include "gui/menus/menuaction.h"
32 using namespace swift::config;
34 using namespace swift::misc::simulation;
36 using namespace swift::gui::menus;
42 CDbOwnModelsComponent::CDbOwnModelsComponent(QWidget *parent)
47 ui->tvp_OwnAircraftModels->setAircraftModelMode(CAircraftModelListModel::OwnAircraftModelMappingTool);
48 ui->tvp_OwnAircraftModels->addFilterDialog();
49 ui->tvp_OwnAircraftModels->setDisplayAutomatically(
true);
50 ui->tvp_OwnAircraftModels->setCustomMenu(
new CLoadModelsMenu(
this));
53 ui->tvp_OwnAircraftModels->setCorrespondingSimulator(sim,
56 bool c = connect(ui->tvp_OwnAircraftModels, &CAircraftModelView::requestUpdate,
this,
57 &CDbOwnModelsComponent::requestOwnModelsUpdate);
58 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
59 c = connect(ui->tvp_OwnAircraftModels, &CAircraftModelView::jsonLoadCompleted,
this,
60 &CDbOwnModelsComponent::onViewDiskLoadingFinished, Qt::QueuedConnection);
61 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
63 &CDbOwnModelsComponent::onSimulatorSelectorChanged);
64 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
65 c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(),
66 &CMultiAircraftModelLoaderProvider::loadingFinished,
this,
67 &CDbOwnModelsComponent::onModelLoaderLoadingFinished, Qt::QueuedConnection);
68 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
69 c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(),
70 &CMultiAircraftModelLoaderProvider::diskLoadingStarted,
this,
71 &CDbOwnModelsComponent::onModelLoaderDiskLoadingStarted, Qt::QueuedConnection);
72 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
73 c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(),
74 &CMultiAircraftModelLoaderProvider::loadingProgress,
this,
75 &CDbOwnModelsComponent::onModelLoadingProgress, Qt::QueuedConnection);
76 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
77 c = connect(&CMultiAircraftModelLoaderProvider::multiModelLoaderInstance(),
78 &CMultiAircraftModelLoaderProvider::cacheChanged,
this, &CDbOwnModelsComponent::onCacheChanged,
79 Qt::QueuedConnection);
80 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
81 c = connect(ui->pb_ForceReload, &QPushButton::released,
this,
82 &CDbOwnModelsComponent::confirmedForcedReloadCurrentSimulator, Qt::QueuedConnection);
83 Q_ASSERT_X(c, Q_FUNC_INFO,
"Connect failed");
86 ui->comp_SimulatorSelector->setRememberSelectionAndSetToLastSelection();
87 const CSimulatorInfo simulator = ui->comp_SimulatorSelector->getValue();
90 m_simulator = simulator;
91 this->setUiSimulatorString(simulator);
92 const bool success = this->initModelLoader(simulator, IAircraftModelLoader::CacheOnly);
93 if (!success) {
CLogMessage(
this).
error(u
"Init of model loader failed in component"); }
107 static const QStringList l({ CLogCategories::modelGui(), CLogCategories::guiComponent() });
119 const IAircraftModelLoader::LoadMode mode =
120 onlyIfNotEmpty ? IAircraftModelLoader::InBackgroundNoCache : IAircraftModelLoader::LoadInBackground;
121 this->requestSimulatorModels(simulator, mode);
138 if (!m_modelLoader) {
return empty; }
144 return ui->tvp_OwnAircraftModels->selectedObjects();
149 return ui->comp_SimulatorSelector->getValue();
156 const bool simUnchanged = (m_simulator == simulator);
159 if (!forced && simUnchanged) {
return false; }
162 m_simulator = simulator;
163 this->requestSimulatorModelsWithCacheInBackground(simulator);
164 ui->comp_SimulatorSelector->setValue(simulator);
165 this->setUiSimulatorString(simulator);
166 ui->tvp_OwnAircraftModels->setCorrespondingSimulator(
173 ui->comp_SimulatorSelector->setMode(mode);
176 void CDbOwnModelsComponent::onSimulatorSelectorChanged()
178 const CSimulatorInfo simulator(ui->comp_SimulatorSelector->getValue());
184 if (!m_modelLoader) {
return 0; }
190 if (!m_modelLoader) {
return {}; }
196 if (!m_modelLoader) {
return {}; }
203 if (m.
isSuccess()) { ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(models); }
216 if (!m_modelLoader) {
return; }
218 ui->tvp_OwnAircraftModels->replaceOrAddModelsWithString(models);
224 if (!m_modelLoader) {
return 0; }
227 ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(allModels);
231 bool CDbOwnModelsComponent::initModelLoader(
const CSimulatorInfo &simulator, IAircraftModelLoader::LoadMode load)
239 m_modelLoader = CMultiAircraftModelLoaderProvider::multiModelLoaderInstance().loaderInstance(simulator);
240 if (m_modelLoader) { m_modelLoader->
startLoading(load); }
242 this->setSaveFileName(simulator);
246 void CDbOwnModelsComponent::setSaveFileName(
const CSimulatorInfo &sim)
249 const QString n(
"simulator models " + sim.
toQString(
true));
250 ui->tvp_OwnAircraftModels->setSaveFileName(n);
253 QString CDbOwnModelsComponent::directorySelector(
const CSimulatorInfo &simulatorInfo)
255 QString dir = m_directorySettings.
get().getLastModelDirectoryOrDefault();
256 dir = QFileDialog::getExistingDirectory(
this,
257 QStringLiteral(
"Open directory (%1)").arg(simulatorInfo.
toQString()),
258 dir, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
265 CLogMessage::preformatted(m);
270 void CDbOwnModelsComponent::setUiSimulatorString(
const CSimulatorInfo &simulatorInfo)
272 const QString s = simulatorInfo.
toQString(
true);
273 ui->le_Simulator->setText(s);
274 ui->pb_ForceReload->setText(QStringLiteral(
"force reload '%1'").arg(s));
277 void CDbOwnModelsComponent::confirmedForcedReloadCurrentSimulator() { this->confirmedForcedReload(m_simulator); }
279 void CDbOwnModelsComponent::confirmedForcedReload(
const CSimulatorInfo &simulator)
281 QMessageBox msgBox(QMessageBox::Question,
"Reload models from disk",
282 QStringLiteral(
"Completely reload '%1' models from disk?").arg(simulator.
toQString(
true)),
283 QMessageBox::Ok | QMessageBox::Cancel,
this);
284 msgBox.setDefaultButton(QMessageBox::Cancel);
285 const QMessageBox::StandardButton reply =
static_cast<QMessageBox::StandardButton
>(msgBox.exec());
286 if (reply != QMessageBox::Ok) {
return; }
288 this->requestSimulatorModels(simulator, IAircraftModelLoader::InBackgroundNoCache);
291 void CDbOwnModelsComponent::runScriptCSL2XSB()
293 static const QString script = QDir(CSwiftDirectories::shareDirectory()).filePath(
"CSL2XSB/CSL2XSB.exe");
296 CLogMessage(
this).
info(u
"Running CSL2XSB on model directory %1") << modelDir;
297 CProcessCtrl::startDetached(script, { QDir::cleanPath(modelDir) },
true);
301 void CDbOwnModelsComponent::CLoadModelsMenu::customMenu(
CMenuActions &menuActions)
310 QPointer<CDbOwnModelsComponent> ownModelsComp(qobject_cast<CDbOwnModelsComponent *>(this->parent()));
311 Q_ASSERT_X(ownModelsComp, Q_FUNC_INFO,
"Cannot access parent");
315 if (sims.
isXPlane() && CBuildConfig::isRunningOnWindowsNtPlatform() && CBuildConfig::buildWordSize() == 64)
317 if (!m_csl2xsbAction)
319 m_csl2xsbAction =
new QAction(CIcons::appTerminal16(),
"XPlane: run CSL2XSB on all models",
this);
320 connect(m_csl2xsbAction, &QAction::triggered, ownModelsComp, [ownModelsComp](
bool checked) {
321 if (!ownModelsComp) {
return; }
323 ownModelsComp->runScriptCSL2XSB();
326 menuActions.
addAction(m_csl2xsbAction, CMenuAction::pathSimulator());
329 this->nestedCustomMenu(menuActions);
332 void CDbOwnModelsComponent::requestOwnModelsUpdate()
334 if (!m_modelLoader) {
return; }
335 ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(this->
getOwnModels());
338 void CDbOwnModelsComponent::loadInstalledModels(
const CSimulatorInfo &simulator,
339 IAircraftModelLoader::LoadMode mode,
340 const QStringList &modelDirectories)
342 if (!m_modelLoader) {
return; }
359 u
"Loading for another simulator '%1' already in progress. Loading might be slow.")
365 if (!this->initModelLoader(simulator))
376 << simulator.
toQString() << IAircraftModelLoader::enumToString(mode);
377 ui->tvp_OwnAircraftModels->showLoadIndicator();
380 mode,
static_cast<int (*)(
CAircraftModelList &,
bool)
>(&CDatabaseUtils::consolidateModelsWithDbData),
384 void CDbOwnModelsComponent::onModelLoaderDiskLoadingStarted(
const CSimulatorInfo &simulator,
385 IAircraftModelLoader::LoadMode mode)
387 using namespace std::chrono_literals;
389 << simulator.
toQString(
true) << IAircraftModelLoader::enumToString(mode);
393 void CDbOwnModelsComponent::onModelLoadingProgress(
const CSimulatorInfo &simulator,
const QString &message,
396 using namespace std::chrono_literals;
401 ui->tvp_OwnAircraftModels->showLoadIndicatorWithTimeout(5s);
405 void CDbOwnModelsComponent::onModelLoaderLoadingFinished(
const CStatusMessageList &statusMessages,
409 using namespace std::chrono_literals;
410 Q_ASSERT_X(simulator.
isSingleSimulator(), Q_FUNC_INFO,
"Expect single simulator");
412 bool hideIndicator =
false;
415 if (IAircraftModelLoader::isLoadedInfo(info) && m_modelLoader)
418 const int modelsLoaded = models.size();
419 ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(models);
421 if (modelsLoaded < 1)
424 summaryMsg =
CLogMessage(
this).
warning(u
"Loading completed for simulator '%1', but no models")
426 hideIndicator =
true;
430 summaryMsg =
CLogMessage(
this).
info(u
"Loading completed for simulator '%1' with %2 models")
431 << simulator << modelsLoaded;
435 if (!summaryMsg.
isEmpty() && info == IAircraftModelLoader::ParsedData)
443 else if (info == IAircraftModelLoader::LoadingSkipped)
446 hideIndicator =
true;
450 ui->tvp_OwnAircraftModels->clear();
451 hideIndicator =
true;
465 if (statusMessages.
size() < 50)
472 QPointer<CDbOwnModelsComponent> myself(
this);
473 const QString confirmMessage =
474 QStringLiteral(
"Do you want to see the %1 detailled messages?").arg(statusMessages.
size());
476 if (!myself) {
return; }
477 myself->showOverlayMessagesOrHTMLMessage(statusMessages);
482 if (hideIndicator) { ui->tvp_OwnAircraftModels->hideLoadIndicatorForced(); }
485 if (info == IAircraftModelLoader::CacheLoaded) {
return; }
491 void CDbOwnModelsComponent::onViewDiskLoadingFinished(
const CStatusMessage &status)
495 QMessageBox::Question,
"Loaded models from disk",
496 "Loaded models from disk file.\nSave to cache or just temporarily keep them?\n\nHint: Saving them will "
497 "override the loaded models from the simulator.\nNormally you would not want that (cancel).",
498 QMessageBox::Save | QMessageBox::Cancel,
this);
499 msgBox.setDefaultButton(QMessageBox::Cancel);
500 const QMessageBox::StandardButton reply =
static_cast<QMessageBox::StandardButton
>(msgBox.exec());
501 if (reply != QMessageBox::Cancel) {
return; }
503 if (models.
isEmpty()) {
return; }
504 const CSimulatorInfo simulator = ui->comp_SimulatorSelector->getValue();
508 void CDbOwnModelsComponent::onCacheChanged(
const CSimulatorInfo &simulator)
511 ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(models);
514 void CDbOwnModelsComponent::requestSimulatorModels(
const CSimulatorInfo &simulator,
515 IAircraftModelLoader::LoadMode mode,
516 const QStringList &modelDirectories)
518 this->loadInstalledModels(simulator, mode, modelDirectories);
521 void CDbOwnModelsComponent::requestSimulatorModelsWithCacheInBackground(
const CSimulatorInfo &simulator)
523 this->requestSimulatorModels(simulator, IAircraftModelLoader::InBackgroundWithCache);
526 void CDbOwnModelsComponent::clearSimulatorCache(
const CSimulatorInfo &simulator)
528 if (!m_modelLoader) {
return; }
bool isShuttingDown() const
Is application shutting down?
CWebDataServices * getWebDataServices() const
Get the web data services.
bool showOverlayHTMLMessage(const QString &htmlMessage, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
HTML message.
bool showOverlayMessage(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Show single message.
void showOverlayMessagesWithConfirmation(const swift::misc::CStatusMessageList &messages, bool appendOldMessages, const QString &confirmationMessage, std::function< void()> okLambda, QMessageBox::StandardButton defaultButton=QMessageBox::Cancel, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Show multiple messages with confirmation bar.
void setOverlayMessagesSorting(const swift::misc::CPropertyIndex &property, Qt::SortOrder order)
Set sorting of overlay messages.
void showOverlayMessagesOrHTMLMessage(const swift::misc::CStatusMessageList &messages, bool appendOldMessages=false, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Show multiple messages or a single message (HTML)
Using this class provides a QFrame with the overlay functionality already integrated.
Handling of own models on disk (the models installed for the simulator)
virtual int updateModelsForSimulator(const swift::misc::simulation::CAircraftModelList &models, const swift::misc::simulation::CSimulatorInfo &simulator)
Set models.
virtual ~CDbOwnModelsComponent()
Destructor.
swift::misc::simulation::CAircraftModelList getOwnModels() const
Own models.
swift::misc::CStatusMessage updateViewAndCache(const swift::misc::simulation::CAircraftModelList &models)
Update view and cache.
models::CAircraftModelListModel * model() const
Access to aircraft model.
swift::misc::simulation::CAircraftModelList getOwnSelectedModels() const
Own models selected in view.
static const QStringList & getLogCategories()
Log categories.
void clearView()
Clear the view.
int getOwnModelsCount() const
Number of own models.
bool requestModelsInBackground(const swift::misc::simulation::CSimulatorInfo &simulator, bool onlyIfNotEmpty)
Forced read for given simulator.
virtual void setModelsForSimulator(const swift::misc::simulation::CAircraftModelList &models, const swift::misc::simulation::CSimulatorInfo &simulator)
Set models.
swift::misc::simulation::CAircraftModelList getOwnCachedModels(const swift::misc::simulation::CSimulatorInfo &simulator) const
Own cached models from loader.
bool setSimulator(const swift::misc::simulation::CSimulatorInfo &simulator, bool forced=false)
Change current simulator for own models.
swift::misc::simulation::CAircraftModel getOwnModelForModelString(const QString &modelString) const
Own (installed) model for given model string.
void ownModelsSimulatorChanged(const swift::misc::simulation::CSimulatorInfo &simulator)
Own models simulator has changed.
void successfullyLoadedModels(const swift::misc::simulation::CSimulatorInfo &simulator, int count)
Models have been successfully loaded.
void gracefulShutdown()
Graceful shutdown.
swift::misc::simulation::CSimulatorInfo getOwnModelsSimulator() const
Own models for simulator.
swift::gui::views::CAircraftModelView * view() const
Models view.
void setSimulatorSelectorMode(CSimulatorSelector::Mode mode)
How to display.
QString getInfoStringFsFamily() const
Info string without XPlane (FSX,P3D, FS9)
QString getInfoString() const
Info string about models in cache.
void changed(const swift::misc::simulation::CSimulatorInfo &simulator)
Value has been changed.
Aircraft model list model.
CStatusMessage setAndSave(const T &value, qint64 timestamp=0)
Write and save in the same step. Must be called from the thread in which the owner lives.
T get() const
Get a copy of the current value.
Directories (swift data directories)
void setLastModelDirectory(const QString &dir)
Last view JSON model directory.
Class for emitting a log message.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
bool isEmpty() const
Message empty.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
size_type size() const
Returns number of elements in the sequence.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
bool isSuccess() const
Operation considered successful.
bool isFailure() const
Operation considered unsuccessful.
Status messages, e.g. from Core -> GUI.
bool hasWarningOrErrorMessages() const
Warning or error messages.
bool hasErrorMessages() const
Error messages.
QString toQString(bool i18n=false) const
Cast as QString.
Aircraft model (used by another pilot, my models on disk)
Value object encapsulating a list of aircraft models.
CAircraftModel findFirstByModelStringOrDefault(const QString &modelString, Qt::CaseSensitivity sensitivity=Qt::CaseInsensitive) const
Find first by model string.
Simple hardcoded info about the corresponding simulator.
bool isSingleSimulator() const
Single simulator selected.
bool isNoSimulator() const
No simulator?
bool isUnspecified() const
Unspecified simulator.
bool isXPlane() const
XPlane.
void startLoading(LoadMode mode=InBackgroundWithCache, const ModelConsolidationCallback &modelConsolidation={}, const QStringList &modelDirectories={})
Start the loading process from disk. Optional DB models can be passed and used for data consolidation...
bool supportsSimulator(const CSimulatorInfo &simulator) const
Supported simulator.
bool isLoadingInProgress() const
Loading in progress.
LoadFinishedInfo
Load mode.
QString getInfoStringFsFamily() const
Look like IMultiSimulatorModelCaches interface.
CStatusMessage setCachedModels(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
void setModelsForSimulator(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Set models.
CStatusMessage clearCachedModels(const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
QString getInfoString() const
Look like IMultiSimulatorModelCaches interface.
int updateModelsForSimulator(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Set models.
CAircraftModelList getCachedModels(const CSimulatorInfo &simulator) const
Look like IMultiSimulatorModelCaches interface.
int getCachedModelsCount(const CSimulatorInfo &simulator) const
Look like IMultiSimulatorModelCaches interface.
QStringList getModelDirectoriesOrDefault(const CSimulatorInfo &simulator) const
Model directory or default model path per simulator.
QString getSimulatorDirectoryOrDefault(const CSimulatorInfo &simulator) const
Simulator directory or default model path per simulator.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Classes interacting with the swift database (aka "datastore").
High level reusable GUI components.
Models to be used with views, mainly QTableView.
Views, mainly QTableView.
Free functions in swift::misc.