swift
dbownmodelsetcomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2016 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QAction>
7 #include <QDesktopServices>
8 #include <QDialog>
9 #include <QFlags>
10 #include <QIcon>
11 #include <QLineEdit>
12 #include <QPointer>
13 #include <QPushButton>
14 #include <QString>
15 #include <QStringBuilder>
16 #include <QWidget>
17 #include <Qt>
18 #include <QtGlobal>
19 
20 #include "ui_dbownmodelsetcomponent.h"
21 
27 #include "gui/guiapplication.h"
28 #include "gui/guiutility.h"
29 #include "gui/menus/aircraftmodelmenus.h"
30 #include "gui/menus/menuaction.h"
34 #include "gui/views/viewbase.h"
35 #include "misc/icons.h"
36 #include "misc/logmessage.h"
38 #include "misc/orderable.h"
43 
44 using namespace swift::misc;
45 using namespace swift::misc::simulation;
46 using namespace swift::gui::models;
47 using namespace swift::gui::menus;
48 using namespace swift::gui::views;
49 
50 namespace swift::gui::components
51 {
52  CDbOwnModelSetComponent::CDbOwnModelSetComponent(QWidget *parent)
53  : QFrame(parent), CDbMappingComponentAware(parent), ui(new Ui::CDbOwnModelSetComponent)
54  {
55  ui->setupUi(this);
56  ui->tvp_OwnModelSet->setAircraftModelMode(CAircraftModelListModel::OwnModelSet);
57  ui->tvp_OwnModelSet->menuAddItems(CAircraftModelView::MenuStashing);
58  ui->tvp_OwnModelSet->menuRemoveItems(CAircraftModelView::MenuDisplayAutomaticallyAndRefresh |
59  CAircraftModelView::MenuBackend);
60  ui->tvp_OwnModelSet->menuAddItems(CAircraftModelView::MenuRemoveSelectedRows | CAircraftModelView::MenuClear |
61  CAircraftModelView::MenuMaterializeFilter);
62  ui->tvp_OwnModelSet->addFilterDialog();
63  ui->tvp_OwnModelSet->setCustomMenu(new CLoadModelSetMenu(this));
64  ui->tvp_OwnModelSet->setCustomMenu(new CConsolidateWithDbDataMenu(ui->tvp_OwnModelSet, this));
65  ui->tvp_OwnModelSet->setCustomMenu(new CConsolidateWithSimulatorModels(ui->tvp_OwnModelSet, this));
66  ui->tvp_OwnModelSet->menuAddItems(CAircraftModelView::MenuLoadAndSave | CAircraftModelView::MenuRefresh |
67  CAircraftModelView::MenuOrderable);
68  ui->tvp_OwnModelSet->setSorting(CAircraftModel::IndexOrderString);
69  ui->tvp_OwnModelSet->initAsOrderable();
70 
71  const CSimulatorInfo sim = ui->comp_SimulatorSelector->getValue();
72  ui->tvp_OwnModelSet->setCorrespondingSimulator(sim, m_simulatorSettings.getSimulatorDirectoryOrDefault(sim));
73  ui->comp_SimulatorSelector->setMode(CSimulatorSelector::RadioButtons);
74  ui->comp_SimulatorSelector->setRememberSelectionAndSetToLastSelection();
75  const CSimulatorInfo simulator = ui->comp_SimulatorSelector->getValue();
76  ui->le_Simulator->setText(simulator.toQString(true));
77 
79  ui->pb_SaveAsSetForSimulator->setStyleSheet("padding-left: 3px; padding-right: 3px;");
80 
81  connect(ui->pb_CreateNewSet, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
82  Qt::QueuedConnection);
83  connect(ui->pb_LoadExistingSet, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
84  Qt::QueuedConnection);
85  connect(ui->pb_ShowStatistics, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
86  Qt::QueuedConnection);
87  connect(ui->pb_FirstSet, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
88  Qt::QueuedConnection);
89  connect(ui->pb_Clear, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
90  Qt::QueuedConnection);
91  connect(ui->pb_CopyFromAnotherSwift, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
92  Qt::QueuedConnection);
93  connect(ui->pb_SaveAsSetForSimulator, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
94  Qt::QueuedConnection);
95 
96  connect(ui->comp_SimulatorSelector, &CSimulatorSelector::changed, this, &CDbOwnModelSetComponent::setSimulator,
97  Qt::QueuedConnection);
98  connect(ui->tvp_OwnModelSet, &CAircraftModelView::modelDataChanged, this,
99  &CDbOwnModelSetComponent::onRowCountChanged, Qt::QueuedConnection);
100  connect(ui->tvp_OwnModelSet, &CAircraftModelView::modelChanged, this,
101  &CDbOwnModelSetComponent::viewModelChanged, Qt::QueuedConnection);
102  connect(ui->tvp_OwnModelSet, &CAircraftModelView::requestUpdate, this,
103  &CDbOwnModelSetComponent::updateViewToCurrentModels, Qt::QueuedConnection);
104  connect(ui->tvp_OwnModelSet, &CAircraftModelView::jsonModelsForSimulatorLoaded, this,
105  &CDbOwnModelSetComponent::onJsonDataLoaded, Qt::QueuedConnection);
106 
107  this->triggerSetSimulatorDeferred(simulator);
108  }
109 
111  {
112  // void
113  }
114 
115  views::CAircraftModelView *CDbOwnModelSetComponent::view() const { return ui->tvp_OwnModelSet; }
116 
118  {
119  using namespace std::chrono_literals;
120 
121  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
122  this->setSimulator(simulator);
123  if (models.isEmpty())
124  {
125  ui->tvp_OwnModelSet->clear();
126  return;
127  }
128 
129  CAircraftModelList cleanModelList(
130  models.matchesSimulator(simulator)); // remove those not matching the simulator
131  const int diff = models.size() - cleanModelList.size();
132  if (diff > 0)
133  {
134  const CStatusMessage m =
135  CStatusMessage(this).warning(u"Removed %1 models from set, because not matching %2")
136  << diff << simulator.toQString(true);
138  }
139  cleanModelList.resetOrder();
140  ui->tvp_OwnModelSet->updateContainerMaybeAsync(cleanModelList);
141  }
142 
144  {
145  using namespace std::chrono_literals;
146 
147  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
148  if (models.isEmpty()) { return 0; }
149  CAircraftModelList cleanModelList(
150  models.matchesSimulator(simulator)); // remove those not matching the simulator
151  const int diff = models.size() - cleanModelList.size();
152  if (diff > 0)
153  {
154  const CStatusMessage m =
155  CStatusMessage(this).warning(u"Removed %1 models from set, because not matching %2")
156  << diff << simulator.toQString(true);
158  }
159  if (cleanModelList.isEmpty()) { return 0; }
160  CAircraftModelList updatedModels(ui->tvp_OwnModelSet->container());
161  updatedModels.replaceOrAddModelsWithString(cleanModelList, Qt::CaseInsensitive);
162  updatedModels.resetOrder();
163  ui->tvp_OwnModelSet->updateContainerMaybeAsync(updatedModels);
164  return diff;
165  }
166 
168  {
169  return ui->tvp_OwnModelSet->container();
170  }
171 
172  int CDbOwnModelSetComponent::getModelSetCountFromView() const { return ui->tvp_OwnModelSet->container().size(); }
173 
175  {
176  return this->addToModelSet(CAircraftModelList({ model }), simulator);
177  }
178 
180  const CSimulatorInfo &simulator)
181  {
182  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
183  if (models.isEmpty()) { return CStatusMessage(this, CStatusMessage::SeverityInfo, u"No data", true); }
184  if (!this->getModelSetSimulator().isSingleSimulator())
185  {
186  // no sim yet, we set it
187  this->setSimulator(simulator);
188  }
189  if (simulator != this->getModelSetSimulator())
190  {
191  // only currently selected sim allowed
192  return CStatusMessage(this, CStatusMessage::SeverityError,
193  u"Cannot add data for " % simulator.toQString(true) % u" to " %
194  this->getModelSetSimulator().toQString(true),
195  true);
196  }
197 
198  const bool allowExcludedModels = m_modelSettings.get().getAllowExcludedModels();
200  int d = updateModels.replaceOrAddModelsWithString(models, Qt::CaseInsensitive);
201  if (d > 0)
202  {
203  if (!allowExcludedModels) { updateModels.removeIfExcluded(); }
204  updateModels.resetOrder();
205  ui->tvp_OwnModelSet->updateContainerMaybeAsync(updateModels);
206  return CStatusMessage(this, CStatusMessage::SeverityInfo,
207  u"Modified " % QString::number(d) % u" entries in model set " %
208  this->getModelSetSimulator().toQString(true),
209  true);
210  }
211  else { return CStatusMessage(this, CStatusMessage::SeverityInfo, u"No data modified in model set", true); }
212  }
213 
215  {
217  if (component)
218  {
220  &CDbOwnModelSetComponent::tabIndexChanged);
221  }
222  }
223 
224  void CDbOwnModelSetComponent::enableButtons(bool firstSet, bool newSet)
225  {
226  ui->pb_FirstSet->setEnabled(firstSet);
227  ui->pb_CreateNewSet->setEnabled(newSet);
228  }
229 
230  void CDbOwnModelSetComponent::tabIndexChanged(int index) { Q_UNUSED(index) }
231 
232  void CDbOwnModelSetComponent::buttonClicked()
233  {
234  using namespace std::chrono_literals;
235 
236  const QObject *sender = QObject::sender();
237  if (!sender) { return; }
238 
239  if (sender == ui->pb_CreateNewSet)
240  {
241  this->createNewSet();
242  return;
243  }
244 
245  if (sender == ui->pb_LoadExistingSet)
246  {
247  ui->tvp_OwnModelSet->showFileLoadDialog();
248  return;
249  }
250 
251  if (sender == ui->pb_SaveAsSetForSimulator)
252  {
253  const CAircraftModelList ownModelSet(ui->tvp_OwnModelSet->container());
254  if (!ownModelSet.isEmpty())
255  {
256  const CSimulatorInfo sim = this->getSelectedSimulator();
257  const CStatusMessage m = this->setCachedModels(ownModelSet, sim);
258  CLogMessage::preformatted(m);
259  if (m.isSuccess())
260  {
261  const QString msg = QStringLiteral("Saved model set for '%1'").arg(sim.toQString(true));
262 
263  // display either as overlay of componet or view
264  if (!this->showMappingComponentOverlayHtmlMessage(msg, 5s))
265  {
266  ui->tvp_OwnModelSet->showOverlayHTMLMessage(msg, 5s);
267  }
268  }
269  else
270  {
271  if (!this->showMappingComponentOverlayMessage(m)) { ui->tvp_OwnModelSet->showOverlayMessage(m); }
272  }
273  }
274  return;
275  }
276 
277  if (sender == ui->pb_ShowStatistics)
278  {
279  this->showModelStatistics();
280  return;
281  }
282 
283  if (sender == ui->pb_FirstSet)
284  {
285  this->firstSet();
286  return;
287  }
288 
289  if (sender == ui->pb_CopyFromAnotherSwift)
290  {
291  this->copyFromAnotherSwift();
292  return;
293  }
294 
295  if (sender == ui->pb_Clear)
296  {
297  ui->tvp_OwnModelSet->clear();
298  return;
299  }
300  }
301 
302  void CDbOwnModelSetComponent::onRowCountChanged(int count, bool withFilter)
303  {
304  Q_UNUSED(count)
305  Q_UNUSED(withFilter)
306 
307  const int realUnfilteredCount = ui->tvp_OwnModelSet->container().size();
308  const bool canSave = this->getModelSetSimulator().isSingleSimulator() && (realUnfilteredCount > 0);
309  ui->pb_SaveAsSetForSimulator->setEnabled(canSave);
310  if (canSave)
311  {
312  this->setSaveFileName(this->getModelSetSimulator());
313  ui->pb_SaveAsSetForSimulator->setText(
314  QStringLiteral("save '%1'").arg(this->getModelSetSimulator().toQString(true)));
315  }
316  else { ui->pb_SaveAsSetForSimulator->setText("save"); }
317  }
318 
319  void CDbOwnModelSetComponent::onJsonDataLoaded(const CSimulatorInfo &simulator)
320  {
321  if (simulator.isSingleSimulator()) { this->setSimulator(simulator); }
322  }
323 
324  void CDbOwnModelSetComponent::distributorPreferencesChanged()
325  {
326  const CDistributorListPreferences preferences = m_distributorPreferences.getThreadLocal();
327  const CSimulatorInfo simuulator = preferences.getLastUpdatedSimulator();
328  if (simuulator.isSingleSimulator()) { this->updateDistributorOrder(simuulator); }
329  }
330 
331  void CDbOwnModelSetComponent::reduceModels()
332  {
333  if (!m_reduceModelsDialog) { m_reduceModelsDialog.reset(new CDbReduceModelDuplicates(this)); }
334 
335  CAircraftModelList models = ui->tvp_OwnModelSet->containerOrFilteredContainer();
336  const CSimulatorInfo simulator = this->getModelSetSimulator();
337  m_reduceModelsDialog->setModels(models, simulator);
338  const QDialog::DialogCode ret = static_cast<QDialog::DialogCode>(m_reduceModelsDialog->exec());
339  if (ret != QDialog::Accepted) { return; }
340  const CAircraftModelList removeModels = m_reduceModelsDialog->getRemoveCandidates();
341  const CSimulatorInfo removeSimulator = m_reduceModelsDialog->getSimulator();
342  if (removeModels.isEmpty()) { return; }
343  const QStringList modelStrings = removeModels.getModelStringList(false);
344  models.removeModelsWithString(modelStrings, Qt::CaseInsensitive); // by strings also removes if id is missing
345  this->setModelSet(models, removeSimulator);
346  }
347 
348  void CDbOwnModelSetComponent::removeExcludedModels()
349  {
350  const CSimulatorInfo simulator = this->getModelSetSimulator();
351  CAircraftModelList models = ui->tvp_OwnModelSet->containerOrFilteredContainer();
352  const int r = models.removeIfExcluded();
353  if (r < 1) { return; }
354  this->setModelSet(models, simulator);
355  }
356 
357  void CDbOwnModelSetComponent::removeNonDBModels()
358  {
359  const CSimulatorInfo simulator = this->getModelSetSimulator();
360  CAircraftModelList models = ui->tvp_OwnModelSet->containerOrFilteredContainer();
361  const int r = models.removeObjectsWithoutDbKey();
362  if (r < 1) { return; }
363  this->setModelSet(models, simulator);
364  }
365 
366  void CDbOwnModelSetComponent::viewModelChanged()
367  {
368  const bool hasData = ui->tvp_OwnModelSet->rowCount() > 0;
369  ui->pb_SaveAsSetForSimulator->setEnabled(hasData);
370  }
371 
372  void CDbOwnModelSetComponent::setSaveFileName(const CSimulatorInfo &simulator)
373  {
374  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
375  const QString name("modelset" + simulator.toQString(true));
376  ui->tvp_OwnModelSet->setSaveFileName(name);
377  }
378 
379  void CDbOwnModelSetComponent::updateViewToCurrentModels()
380  {
381  const CAircraftModelList models(this->getModelSet());
382  ui->tvp_OwnModelSet->updateContainerMaybeAsync(models);
383  }
384 
385  void CDbOwnModelSetComponent::createNewSet()
386  {
387  // make sure both tabs display the same simulator
388  // since we use the component also in the launcher wizard, mc might not be existing
389  const CSimulatorInfo simulator(this->getModelSetSimulator());
390  if (!simulator.isSingleSimulator())
391  {
392  // Ref T630, avoid invalid simulator
393  CLogMessage(this).error(u"No single simulator!");
394  return;
395  }
396 
397  CDbMappingComponent *mc = this->getMappingComponent();
398  if (!mc)
399  {
400  CLogMessage(this).error(u"No mapping component available!");
401  return;
402  }
403 
404  mc->setOwnModelsSimulator(simulator);
405  if (!m_modelSetFormDialog)
406  {
407  m_modelSetFormDialog.reset(new CDbOwnModelSetFormDialog(this));
408  m_modelSetFormDialog->setMappingComponent(this->getMappingComponent());
409  }
410 
411  if (mc->getOwnModelsCount() > 0)
412  {
413  m_modelSetFormDialog->setModal(true);
414  m_modelSetFormDialog->reloadData();
415  const QDialog::DialogCode rc = static_cast<QDialog::DialogCode>(m_modelSetFormDialog->exec());
416  if (rc == QDialog::Accepted)
417  {
418  this->setModelSet(m_modelSetFormDialog->getModelSet(), m_modelSetFormDialog->getSimulatorInfo());
419  }
420  }
421  else
422  {
423  const CStatusMessage m = CStatusMessage(this).error(u"No model data for %1") << simulator.toQString(true);
424  mc->showOverlayMessage(m);
425  }
426  }
427 
428  void CDbOwnModelSetComponent::firstSet()
429  {
430  if (!m_firstModelSetDialog) { m_firstModelSetDialog.reset(new CFirstModelSetDialog(this)); }
431  m_firstModelSetDialog->show();
432  }
433 
434  void CDbOwnModelSetComponent::copyFromAnotherSwift()
435  {
436  if (!m_copyFromAnotherSwiftDialog)
437  {
438  m_copyFromAnotherSwiftDialog.reset(new CCopyModelsFromOtherSwiftVersionsDialog(this));
439  }
440  m_copyFromAnotherSwiftDialog->show();
441  }
442 
444  {
445  if (m_simulator == simulator) { return; } // avoid unnecessary signals
446  if (simulator.isNoSimulator()) { return; }
447  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
448 
449  m_simulator = simulator;
450  ui->comp_SimulatorSelector->setValue(simulator);
451  ui->tvp_OwnModelSet->setCorrespondingSimulator(simulator,
452  m_simulatorSettings.getSimulatorDirectoryOrDefault(m_simulator));
453  ui->le_Simulator->setText(simulator.toQString(true));
454  this->synchronizeCache(simulator);
455  this->updateViewToCurrentModels();
456  }
457 
459  {
460  ui->comp_SimulatorSelector->setMode(mode);
461  }
462 
464  {
465  this->admitCache(simulator); // trigger loading
466 
467  QPointer<CDbOwnModelSetComponent> myself(this);
468  QTimer::singleShot(1000, this, [=] {
469  if (!sApp || sApp->isShuttingDown()) { return; }
470  if (!myself) { return; }
471  this->setSimulator(simulator);
472  });
473  }
474 
475  void CDbOwnModelSetComponent::showModelStatistics()
476  {
477  const CAircraftModelList set(this->getModelSetFromView());
478  if (!m_modelStatisticsDialog) { m_modelStatisticsDialog.reset(new CAircraftModelStatisticsDialog(this)); }
479  m_modelStatisticsDialog->analyzeModels(set);
480  m_modelStatisticsDialog->show();
481  }
482 
483  void CDbOwnModelSetComponent::updateDistributorOrder(const CSimulatorInfo &simulator)
484  {
485  CAircraftModelList modelSet = this->getCachedModels(simulator);
486  if (modelSet.isEmpty()) { return; }
487  const CDistributorListPreferences preferences = m_distributorPreferences.getThreadLocal();
488  const CDistributorList distributors = preferences.getDistributors(simulator);
489  if (distributors.isEmpty()) { return; }
490  modelSet.updateDistributorOrder(distributors);
491  this->setCachedModels(modelSet, simulator);
492 
493  // display?
494  const CSimulatorInfo currentSimulator(this->getModelSetSimulator());
495  if (simulator == currentSimulator) { ui->tvp_OwnModelSet->updateContainerAsync(modelSet); }
496  }
497 
498  bool CDbOwnModelSetComponent::runsInDialog() { return CGuiUtility::findParentDialog(this, 5); }
499 
500  void CDbOwnModelSetComponent::CLoadModelSetMenu::customMenu(CMenuActions &menuActions)
501  {
502  // for the moment I use all sims, I could restrict to CSimulatorInfo::getLocallyInstalledSimulators();
503  const CSimulatorInfo sims = CSimulatorInfo::allSimulators();
504  const bool noSims = sims.isNoSimulator() || sims.isUnspecified();
505  if (!noSims)
506  {
507  CDbOwnModelSetComponent *ownModelSetComp = qobject_cast<CDbOwnModelSetComponent *>(this->parent());
508  Q_ASSERT_X(ownModelSetComp, Q_FUNC_INFO, "Cannot access parent");
509  if (m_setActions.isEmpty())
510  {
511  if (sims.isFSX())
512  {
513  QAction *a = new QAction(CIcons::appModels16(), "FSX models", this);
514  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
515  Q_UNUSED(checked)
516  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::FSX));
517  });
518  m_setActions.append(a);
519 
520  a = new QAction(CIcons::appModels16(), "New set FSX models", this);
521  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
522  Q_UNUSED(checked)
523  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::FSX));
524  });
525  m_setNewActions.append(a);
526  }
527  if (sims.isP3D())
528  {
529  QAction *a = new QAction(CIcons::appModels16(), "P3D models", this);
530  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
531  Q_UNUSED(checked)
532  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::P3D));
533  });
534  m_setActions.append(a);
535 
536  a = new QAction(CIcons::appModels16(), "New set P3D models", this);
537  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
538  Q_UNUSED(checked)
539  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::P3D));
540  });
541  m_setNewActions.append(a);
542  }
543  if (sims.isFS9())
544  {
545  QAction *a = new QAction(CIcons::appModels16(), "FS9 models", this);
546  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
547  Q_UNUSED(checked)
548  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::FS9));
549  });
550  m_setActions.append(a);
551 
552  a = new QAction(CIcons::appModels16(), "New set FS9 models", this);
553  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
554  Q_UNUSED(checked)
555  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::FS9));
556  });
557  m_setNewActions.append(a);
558  }
559  if (sims.isXPlane())
560  {
561  QAction *a = new QAction(CIcons::appModels16(), "XPlane models", this);
562  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
563  Q_UNUSED(checked)
564  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::XPLANE));
565  });
566  m_setActions.append(a);
567 
568  a = new QAction(CIcons::appModels16(), "New set XPlane models", this);
569  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
570  Q_UNUSED(checked)
571  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::XPLANE));
572  });
573  m_setNewActions.append(a);
574  }
575  if (sims.isFG())
576  {
577  QAction *a = new QAction(CIcons::appModels16(), "FG models", this);
578  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
579  Q_UNUSED(checked)
580  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::FG));
581  });
582  m_setActions.append(a);
583 
584  a = new QAction(CIcons::appModels16(), "New set FG models", this);
585  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
586  Q_UNUSED(checked)
587  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::FG));
588  });
589  m_setNewActions.append(a);
590  }
591  if (sims.isMSFS())
592  {
593  QAction *a = new QAction(CIcons::appModels16(), "MSFS models", this);
594  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
595  Q_UNUSED(checked)
596  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::MSFS));
597  });
598  m_setActions.append(a);
599 
600  a = new QAction(CIcons::appModels16(), "New set MSFS models", this);
601  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
602  Q_UNUSED(checked)
603  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::MSFS));
604  });
605  m_setNewActions.append(a);
606  }
607  if (sims.isMSFS2024())
608  {
609  QAction *a = new QAction(CIcons::appModels16(), "MSFS2024 models", this);
610  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
611  Q_UNUSED(checked)
612  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::MSFS2024));
613  });
614  m_setActions.append(a);
615 
616  a = new QAction(CIcons::appModels16(), "New set MSFS2024 models", this);
617  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
618  Q_UNUSED(checked)
619  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::MSFS2024));
620  });
621  m_setNewActions.append(a);
622  }
623 
624  QAction *a = new QAction(CIcons::appDistributors16(), "Apply distributor preferences", this);
625  connect(a, &QAction::triggered, ownModelSetComp,
626  &CDbOwnModelSetComponent::distributorPreferencesChanged, Qt::QueuedConnection);
627  m_setActions.append(a);
628 
629  a = new QAction(CIcons::delete16(), "Reduce models (remove duplicates)", this);
630  connect(a, &QAction::triggered, ownModelSetComp, &CDbOwnModelSetComponent::reduceModels,
631  Qt::QueuedConnection);
632  m_setActions.append(a);
633 
634  a = new QAction(CIcons::delete16(), "Remove excluded models", this);
635  connect(a, &QAction::triggered, ownModelSetComp, &CDbOwnModelSetComponent::removeExcludedModels,
636  Qt::QueuedConnection);
637  m_setActions.append(a);
638 
639  a = new QAction(CIcons::delete16(), "Remove non DB models", this);
640  connect(a, &QAction::triggered, ownModelSetComp, &CDbOwnModelSetComponent::removeNonDBModels,
641  Qt::QueuedConnection);
642  m_setActions.append(a);
643  }
644  menuActions.addMenuModelSet();
645  menuActions.addActions(m_setActions, CMenuAction::pathModelSet());
646  menuActions.addActions(m_setNewActions, CMenuAction::pathModelSetNew());
647  }
648  this->nestedCustomMenu(menuActions);
649  }
650 } // namespace swift::gui::components
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
bool isShuttingDown() const
Is application shutting down?
static QDialog * findParentDialog(QWidget *widget)
Find parent dialog if there is any, otherwise null.
Definition: guiutility.cpp:868
Allows subcomponents to gain access to model component.
bool showMappingComponentOverlayMessage(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Overlay messages.
bool showMappingComponentOverlayHtmlMessage(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Overlay messages.
CDbMappingComponent * getMappingComponent() const
Get the mapping component.
virtual void setMappingComponent(CDbMappingComponent *component)
Set the corresponding component.
void tabIndexChanged(int index)
Tab index has been changed.
const swift::misc::simulation::CAircraftModelList & getModelSetFromView() const
Current model set for simulator CDbOwnModelSetComponent::getModelSetSimulator.
swift::misc::simulation::CAircraftModelList getModelSet() const
Cached models for current simulator.
int getModelSetCountFromView() const
Current sount of model set for simulator CDbOwnModelSetComponent::getModelSetSimulator.
int replaceOrAddModelSet(const swift::misc::simulation::CAircraftModelList &models, const swift::misc::simulation::CSimulatorInfo &simulator)
Replace or add models provided for a given simulator.
void setSimulator(const swift::misc::simulation::CSimulatorInfo &simulator)
Simulator.
swift::misc::CStatusMessage addToModelSet(const swift::misc::simulation::CAircraftModelList &models, const swift::misc::simulation::CSimulatorInfo &simulator)
Add to model set.
views::CAircraftModelView * view() const
Corresponding view.
void setSimulatorSelectorMode(CSimulatorSelector::Mode mode)
How to display.
swift::misc::simulation::CSimulatorInfo getModelSetSimulator() const
Model set is for simulator.
virtual void setMappingComponent(CDbMappingComponent *component)
Set the corresponding component.
void triggerSetSimulatorDeferred(const swift::misc::simulation::CSimulatorInfo &simulator)
Deferred init of simulator.
CDbOwnModelSetComponent(QWidget *parent=nullptr)
Constructor.
void setModelSet(const swift::misc::simulation::CAircraftModelList &models, const swift::misc::simulation::CSimulatorInfo &simulator)
Set the model set for a given simulator.
virtual swift::misc::simulation::CSimulatorInfo getSelectedSimulator() const
Simulator.
virtual int updateModels(const swift::misc::simulation::CAircraftModelList &models)
Update models.
void enableButtons(bool firstSet, bool newSet)
Enable buttons.
void changed(const swift::misc::simulation::CSimulatorInfo &simulator)
Value has been changed.
Merge/update with simulator models (e.g. remove no longer existing models)
Bunch of CMenuAction objects.
Definition: menuaction.h:384
CMenuActions addActions(const CMenuActions &actions)
Add menu actions, returns last valid QAction.
Definition: menuaction.cpp:217
CMenuAction addMenuModelSet()
Model set menu.
Definition: menuaction.cpp:461
const T & getThreadLocal() const
Read the current value.
Definition: valuecache.h:400
T get() const
Get a copy of the current value.
Definition: valuecache.h:408
Class for emitting a log message.
Definition: logmessage.h:27
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Streamable status message, e.g.
bool isSuccess() const
Operation considered successful.
void resetOrder(int offset=0)
Set order member to current order.
Definition: orderablelist.h:34
int removeObjectsWithoutDbKey()
Remove objects without key.
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:76
Aircraft model (used by another pilot, my models on disk)
Definition: aircraftmodel.h:71
Value object encapsulating a list of aircraft models.
QStringList getModelStringList(bool sort=true) const
Model strings.
int replaceOrAddModelsWithString(const CAircraftModelList &addOrReplaceList, Qt::CaseSensitivity sensitivity)
Replace or add based on model string.
int removeIfExcluded()
Remove if excluded CAircraftModel::Exclude.
int removeModelsWithString(const CAircraftModelList &models, Qt::CaseSensitivity sensitivity)
Remove those models with given model strings.
CAircraftModelList matchesSimulator(const CSimulatorInfo &simulator) const
Find for given simulator.
int updateDistributorOrder(const CDistributorList &distributors)
From given CDistributorList update the model`s distributor order.
Value object encapsulating a list of distributors.
const CSimulatorInfo & getLastUpdatedSimulator() const
Last updated simulator.
const CDistributorList & getDistributors(const CSimulatorInfo &simulator) const
Get distributors.
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
bool isSingleSimulator() const
Single simulator selected.
bool isNoSimulator() const
No simulator?
bool isUnspecified() const
Unspecified simulator.
void admitCache(const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
Definition: modelcaches.h:678
CAircraftModelList getCachedModels(const CSimulatorInfo &simulator) const
Look like IMultiSimulatorModelCaches interface.
Definition: modelcaches.h:644
CStatusMessage setCachedModels(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
Definition: modelcaches.h:657
void synchronizeCache(const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
Definition: modelcaches.h:674
QString getSimulatorDirectoryOrDefault(const CSimulatorInfo &simulator) const
Simulator directory or default model path per simulator.
High level reusable GUI components.
Definition: aboutdialog.cpp:13
Models to be used with views, mainly QTableView.
Views, mainly QTableView.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
Definition: threadutils.h:30