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,
83  connect(ui->pb_LoadExistingSet, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
85  connect(ui->pb_ShowStatistics, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
87  connect(ui->pb_FirstSet, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
89  connect(ui->pb_Clear, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
91  connect(ui->pb_CopyFromAnotherSwift, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
93  connect(ui->pb_SaveAsSetForSimulator, &QPushButton::clicked, this, &CDbOwnModelSetComponent::buttonClicked,
95 
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  views::CAircraftModelView *CDbOwnModelSetComponent::view() const { return ui->tvp_OwnModelSet; }
113 
115  {
116  using namespace std::chrono_literals;
117 
118  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
119  this->setSimulator(simulator);
120  if (models.isEmpty())
121  {
122  ui->tvp_OwnModelSet->clear();
123  return;
124  }
125 
126  CAircraftModelList cleanModelList(
127  models.matchesSimulator(simulator)); // remove those not matching the simulator
128  const int diff = models.size() - cleanModelList.size();
129  if (diff > 0)
130  {
131  const CStatusMessage m =
132  CStatusMessage(this).warning(u"Removed %1 models from set, because not matching %2")
133  << diff << simulator.toQString(true);
135  }
136  cleanModelList.resetOrder();
137  ui->tvp_OwnModelSet->updateContainerMaybeAsync(cleanModelList);
138  }
139 
141  {
142  using namespace std::chrono_literals;
143 
144  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
145  if (models.isEmpty()) { return 0; }
146  CAircraftModelList cleanModelList(
147  models.matchesSimulator(simulator)); // remove those not matching the simulator
148  const int diff = models.size() - cleanModelList.size();
149  if (diff > 0)
150  {
151  const CStatusMessage m =
152  CStatusMessage(this).warning(u"Removed %1 models from set, because not matching %2")
153  << diff << simulator.toQString(true);
155  }
156  if (cleanModelList.isEmpty()) { return 0; }
157  CAircraftModelList updatedModels(ui->tvp_OwnModelSet->container());
158  updatedModels.replaceOrAddModelsWithString(cleanModelList, Qt::CaseInsensitive);
159  updatedModels.resetOrder();
160  ui->tvp_OwnModelSet->updateContainerMaybeAsync(updatedModels);
161  return diff;
162  }
163 
165  {
166  return ui->tvp_OwnModelSet->container();
167  }
168 
169  int CDbOwnModelSetComponent::getModelSetCountFromView() const { return ui->tvp_OwnModelSet->container().size(); }
170 
172  {
173  return this->addToModelSet(CAircraftModelList({ model }), simulator);
174  }
175 
177  const CSimulatorInfo &simulator)
178  {
179  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
180  if (models.isEmpty()) { return { this, CStatusMessage::SeverityInfo, u"No data", true }; }
181  if (!this->getModelSetSimulator().isSingleSimulator())
182  {
183  // no sim yet, we set it
184  this->setSimulator(simulator);
185  }
186  if (simulator != this->getModelSetSimulator())
187  {
188  // only currently selected sim allowed
189  return { this, CStatusMessage::SeverityError,
190  u"Cannot add data for " % simulator.toQString(true) % u" to " %
191  this->getModelSetSimulator().toQString(true),
192  true };
193  }
194 
195  const bool allowExcludedModels = m_modelSettings.get().getAllowExcludedModels();
197  int d = updateModels.replaceOrAddModelsWithString(models, Qt::CaseInsensitive);
198  if (d > 0)
199  {
200  if (!allowExcludedModels) { updateModels.removeIfExcluded(); }
201  updateModels.resetOrder();
202  ui->tvp_OwnModelSet->updateContainerMaybeAsync(updateModels);
203  return { this, CStatusMessage::SeverityInfo,
204  u"Modified " % QString::number(d) % u" entries in model set " %
205  this->getModelSetSimulator().toQString(true),
206  true };
207  }
208  else { return { this, CStatusMessage::SeverityInfo, u"No data modified in model set", true }; }
209  }
210 
212  {
214  if (component)
215  {
217  &CDbOwnModelSetComponent::tabIndexChanged);
218  }
219  }
220 
221  void CDbOwnModelSetComponent::enableButtons(bool firstSet, bool newSet)
222  {
223  ui->pb_FirstSet->setEnabled(firstSet);
224  ui->pb_CreateNewSet->setEnabled(newSet);
225  }
226 
227  void CDbOwnModelSetComponent::tabIndexChanged(int index) { Q_UNUSED(index) }
228 
229  void CDbOwnModelSetComponent::buttonClicked()
230  {
231  using namespace std::chrono_literals;
232 
233  const QObject *sender = QObject::sender();
234  if (!sender) { return; }
235 
236  if (sender == ui->pb_CreateNewSet)
237  {
238  this->createNewSet();
239  return;
240  }
241 
242  if (sender == ui->pb_LoadExistingSet)
243  {
244  ui->tvp_OwnModelSet->showFileLoadDialog();
245  return;
246  }
247 
248  if (sender == ui->pb_SaveAsSetForSimulator)
249  {
250  const CAircraftModelList ownModelSet(ui->tvp_OwnModelSet->container());
251  if (!ownModelSet.isEmpty())
252  {
253  const CSimulatorInfo sim = this->getSelectedSimulator();
254  const CStatusMessage m = this->setCachedModels(ownModelSet, sim);
255  CLogMessage::preformatted(m);
256  if (m.isSuccess())
257  {
258  const QString msg = QStringLiteral("Saved model set for '%1'").arg(sim.toQString(true));
259 
260  // display either as overlay of componet or view
261  if (!this->showMappingComponentOverlayHtmlMessage(msg, 5s))
262  {
263  ui->tvp_OwnModelSet->showOverlayHTMLMessage(msg, 5s);
264  }
265  }
266  else
267  {
268  if (!this->showMappingComponentOverlayMessage(m)) { ui->tvp_OwnModelSet->showOverlayMessage(m); }
269  }
270  }
271  return;
272  }
273 
274  if (sender == ui->pb_ShowStatistics)
275  {
276  this->showModelStatistics();
277  return;
278  }
279 
280  if (sender == ui->pb_FirstSet)
281  {
282  this->firstSet();
283  return;
284  }
285 
286  if (sender == ui->pb_CopyFromAnotherSwift)
287  {
288  this->copyFromAnotherSwift();
289  return;
290  }
291 
292  if (sender == ui->pb_Clear)
293  {
294  ui->tvp_OwnModelSet->clear();
295  return;
296  }
297  }
298 
299  void CDbOwnModelSetComponent::onRowCountChanged(int count, bool withFilter)
300  {
301  Q_UNUSED(count)
302  Q_UNUSED(withFilter)
303 
304  const int realUnfilteredCount = ui->tvp_OwnModelSet->container().size();
305  const bool canSave = this->getModelSetSimulator().isSingleSimulator() && (realUnfilteredCount > 0);
306  ui->pb_SaveAsSetForSimulator->setEnabled(canSave);
307  if (canSave)
308  {
309  this->setSaveFileName(this->getModelSetSimulator());
310  ui->pb_SaveAsSetForSimulator->setText(
311  QStringLiteral("save '%1'").arg(this->getModelSetSimulator().toQString(true)));
312  }
313  else { ui->pb_SaveAsSetForSimulator->setText("save"); }
314  }
315 
316  void CDbOwnModelSetComponent::onJsonDataLoaded(const CSimulatorInfo &simulator)
317  {
318  if (simulator.isSingleSimulator()) { this->setSimulator(simulator); }
319  }
320 
321  void CDbOwnModelSetComponent::distributorPreferencesChanged()
322  {
323  const CDistributorListPreferences preferences = m_distributorPreferences.getThreadLocal();
324  const CSimulatorInfo simuulator = preferences.getLastUpdatedSimulator();
325  if (simuulator.isSingleSimulator()) { this->updateDistributorOrder(simuulator); }
326  }
327 
328  void CDbOwnModelSetComponent::reduceModels()
329  {
330  if (!m_reduceModelsDialog) { m_reduceModelsDialog.reset(new CDbReduceModelDuplicates(this)); }
331 
332  CAircraftModelList models = ui->tvp_OwnModelSet->containerOrFilteredContainer();
333  const CSimulatorInfo simulator = this->getModelSetSimulator();
334  m_reduceModelsDialog->setModels(models, simulator);
335  const auto ret = static_cast<QDialog::DialogCode>(m_reduceModelsDialog->exec());
336  if (ret != QDialog::Accepted) { return; }
337  const CAircraftModelList removeModels = m_reduceModelsDialog->getRemoveCandidates();
338  const CSimulatorInfo removeSimulator = m_reduceModelsDialog->getSimulator();
339  if (removeModels.isEmpty()) { return; }
340  const QStringList modelStrings = removeModels.getModelStringList(false);
341  models.removeModelsWithString(modelStrings, Qt::CaseInsensitive); // by strings also removes if id is missing
342  this->setModelSet(models, removeSimulator);
343  }
344 
345  void CDbOwnModelSetComponent::removeExcludedModels()
346  {
347  const CSimulatorInfo simulator = this->getModelSetSimulator();
348  CAircraftModelList models = ui->tvp_OwnModelSet->containerOrFilteredContainer();
349  const int r = models.removeIfExcluded();
350  if (r < 1) { return; }
351  this->setModelSet(models, simulator);
352  }
353 
354  void CDbOwnModelSetComponent::removeNonDBModels()
355  {
356  const CSimulatorInfo simulator = this->getModelSetSimulator();
357  CAircraftModelList models = ui->tvp_OwnModelSet->containerOrFilteredContainer();
358  const int r = models.removeObjectsWithoutDbKey();
359  if (r < 1) { return; }
360  this->setModelSet(models, simulator);
361  }
362 
363  void CDbOwnModelSetComponent::viewModelChanged()
364  {
365  const bool hasData = ui->tvp_OwnModelSet->rowCount() > 0;
366  ui->pb_SaveAsSetForSimulator->setEnabled(hasData);
367  }
368 
369  void CDbOwnModelSetComponent::setSaveFileName(const CSimulatorInfo &simulator)
370  {
371  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
372  const QString name("modelset" + simulator.toQString(true));
373  ui->tvp_OwnModelSet->setSaveFileName(name);
374  }
375 
376  void CDbOwnModelSetComponent::updateViewToCurrentModels()
377  {
378  const CAircraftModelList models(this->getModelSet());
379  ui->tvp_OwnModelSet->updateContainerMaybeAsync(models);
380  }
381 
382  void CDbOwnModelSetComponent::createNewSet()
383  {
384  // make sure both tabs display the same simulator
385  // since we use the component also in the launcher wizard, mc might not be existing
386  const CSimulatorInfo simulator(this->getModelSetSimulator());
387  if (!simulator.isSingleSimulator())
388  {
389  // Ref T630, avoid invalid simulator
390  CLogMessage(this).error(u"No single simulator!");
391  return;
392  }
393 
394  CDbMappingComponent *mc = this->getMappingComponent();
395  if (!mc)
396  {
397  CLogMessage(this).error(u"No mapping component available!");
398  return;
399  }
400 
401  mc->setOwnModelsSimulator(simulator);
402  if (!m_modelSetFormDialog)
403  {
404  m_modelSetFormDialog.reset(new CDbOwnModelSetFormDialog(this));
405  m_modelSetFormDialog->setMappingComponent(this->getMappingComponent());
406  }
407 
408  if (mc->getOwnModelsCount() > 0)
409  {
410  m_modelSetFormDialog->setModal(true);
411  m_modelSetFormDialog->reloadData();
412  const auto rc = static_cast<QDialog::DialogCode>(m_modelSetFormDialog->exec());
413  if (rc == QDialog::Accepted)
414  {
415  this->setModelSet(m_modelSetFormDialog->getModelSet(), m_modelSetFormDialog->getSimulatorInfo());
416  }
417  }
418  else
419  {
420  const CStatusMessage m = CStatusMessage(this).error(u"No model data for %1") << simulator.toQString(true);
421  mc->showOverlayMessage(m);
422  }
423  }
424 
425  void CDbOwnModelSetComponent::firstSet()
426  {
427  if (!m_firstModelSetDialog) { m_firstModelSetDialog.reset(new CFirstModelSetDialog(this)); }
428  m_firstModelSetDialog->show();
429  }
430 
431  void CDbOwnModelSetComponent::copyFromAnotherSwift()
432  {
433  if (!m_copyFromAnotherSwiftDialog)
434  {
435  m_copyFromAnotherSwiftDialog.reset(new CCopyModelsFromOtherSwiftVersionsDialog(this));
436  }
437  m_copyFromAnotherSwiftDialog->show();
438  }
439 
441  {
442  if (m_simulator == simulator) { return; } // avoid unnecessary signals
443  if (simulator.isNoSimulator()) { return; }
444  Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator");
445 
446  m_simulator = simulator;
447  ui->comp_SimulatorSelector->setValue(simulator);
448  ui->tvp_OwnModelSet->setCorrespondingSimulator(simulator,
449  m_simulatorSettings.getSimulatorDirectoryOrDefault(m_simulator));
450  ui->le_Simulator->setText(simulator.toQString(true));
451  this->synchronizeCache(simulator);
452  this->updateViewToCurrentModels();
453  }
454 
456  {
457  ui->comp_SimulatorSelector->setMode(mode);
458  }
459 
461  {
462  this->admitCache(simulator); // trigger loading
463 
465  QTimer::singleShot(1000, this, [=] {
466  if (!sApp || sApp->isShuttingDown()) { return; }
467  if (!myself) { return; }
468  this->setSimulator(simulator);
469  });
470  }
471 
472  void CDbOwnModelSetComponent::showModelStatistics()
473  {
474  const CAircraftModelList set(this->getModelSetFromView());
475  if (!m_modelStatisticsDialog) { m_modelStatisticsDialog.reset(new CAircraftModelStatisticsDialog(this)); }
476  m_modelStatisticsDialog->analyzeModels(set);
477  m_modelStatisticsDialog->show();
478  }
479 
480  void CDbOwnModelSetComponent::updateDistributorOrder(const CSimulatorInfo &simulator)
481  {
482  CAircraftModelList modelSet = this->getCachedModels(simulator);
483  if (modelSet.isEmpty()) { return; }
484  const CDistributorListPreferences preferences = m_distributorPreferences.getThreadLocal();
485  const CDistributorList distributors = preferences.getDistributors(simulator);
486  if (distributors.isEmpty()) { return; }
487  modelSet.updateDistributorOrder(distributors);
488  this->setCachedModels(modelSet, simulator);
489 
490  // display?
491  const CSimulatorInfo currentSimulator(this->getModelSetSimulator());
492  if (simulator == currentSimulator) { ui->tvp_OwnModelSet->updateContainerAsync(modelSet); }
493  }
494 
495  bool CDbOwnModelSetComponent::runsInDialog() { return CGuiUtility::findParentDialog(this, 5); }
496 
497  void CDbOwnModelSetComponent::CLoadModelSetMenu::customMenu(CMenuActions &menuActions)
498  {
499  // for the moment I use all sims, I could restrict to CSimulatorInfo::getLocallyInstalledSimulators();
500  const CSimulatorInfo sims = CSimulatorInfo::allSimulators();
501  const bool noSims = sims.isNoSimulator() || sims.isUnspecified();
502  if (!noSims)
503  {
504  auto *ownModelSetComp = qobject_cast<CDbOwnModelSetComponent *>(this->parent());
505  Q_ASSERT_X(ownModelSetComp, Q_FUNC_INFO, "Cannot access parent");
506  if (m_setActions.isEmpty())
507  {
508  if (sims.isFSX())
509  {
510  auto *a = new QAction(CIcons::appModels16(), "FSX models", this);
511  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
512  Q_UNUSED(checked)
513  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::FSX));
514  });
515  m_setActions.append(a);
516 
517  a = new QAction(CIcons::appModels16(), "New set FSX models", this);
518  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
519  Q_UNUSED(checked)
520  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::FSX));
521  });
522  m_setNewActions.append(a);
523  }
524  if (sims.isP3D())
525  {
526  auto *a = new QAction(CIcons::appModels16(), "P3D models", this);
527  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
528  Q_UNUSED(checked)
529  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::P3D));
530  });
531  m_setActions.append(a);
532 
533  a = new QAction(CIcons::appModels16(), "New set P3D models", this);
534  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
535  Q_UNUSED(checked)
536  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::P3D));
537  });
538  m_setNewActions.append(a);
539  }
540  if (sims.isFS9())
541  {
542  auto *a = new QAction(CIcons::appModels16(), "FS9 models", this);
543  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
544  Q_UNUSED(checked)
545  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::FS9));
546  });
547  m_setActions.append(a);
548 
549  a = new QAction(CIcons::appModels16(), "New set FS9 models", this);
550  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
551  Q_UNUSED(checked)
552  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::FS9));
553  });
554  m_setNewActions.append(a);
555  }
556  if (sims.isXPlane())
557  {
558  auto *a = new QAction(CIcons::appModels16(), "XPlane models", this);
559  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
560  Q_UNUSED(checked)
561  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::XPLANE));
562  });
563  m_setActions.append(a);
564 
565  a = new QAction(CIcons::appModels16(), "New set XPlane models", this);
566  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
567  Q_UNUSED(checked)
568  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::XPLANE));
569  });
570  m_setNewActions.append(a);
571  }
572  if (sims.isFG())
573  {
574  auto *a = new QAction(CIcons::appModels16(), "FG models", this);
575  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
576  Q_UNUSED(checked)
577  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::FG));
578  });
579  m_setActions.append(a);
580 
581  a = new QAction(CIcons::appModels16(), "New set FG models", this);
582  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
583  Q_UNUSED(checked)
584  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::FG));
585  });
586  m_setNewActions.append(a);
587  }
588  if (sims.isMSFS())
589  {
590  auto *a = new QAction(CIcons::appModels16(), "MSFS models", this);
591  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
592  Q_UNUSED(checked)
593  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::MSFS));
594  });
595  m_setActions.append(a);
596 
597  a = new QAction(CIcons::appModels16(), "New set MSFS models", this);
598  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
599  Q_UNUSED(checked)
600  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::MSFS));
601  });
602  m_setNewActions.append(a);
603  }
604  if (sims.isMSFS2024())
605  {
606  auto *a = new QAction(CIcons::appModels16(), "MSFS2024 models", this);
607  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
608  Q_UNUSED(checked)
609  ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::MSFS2024));
610  });
611  m_setActions.append(a);
612 
613  a = new QAction(CIcons::appModels16(), "New set MSFS2024 models", this);
614  connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) {
615  Q_UNUSED(checked)
616  ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::MSFS2024));
617  });
618  m_setNewActions.append(a);
619  }
620 
621  auto *a = new QAction(CIcons::appDistributors16(), "Apply distributor preferences", this);
622  connect(a, &QAction::triggered, ownModelSetComp,
623  &CDbOwnModelSetComponent::distributorPreferencesChanged, Qt::QueuedConnection);
624  m_setActions.append(a);
625 
626  a = new QAction(CIcons::delete16(), "Reduce models (remove duplicates)", this);
627  connect(a, &QAction::triggered, ownModelSetComp, &CDbOwnModelSetComponent::reduceModels,
629  m_setActions.append(a);
630 
631  a = new QAction(CIcons::delete16(), "Remove excluded models", this);
632  connect(a, &QAction::triggered, ownModelSetComp, &CDbOwnModelSetComponent::removeExcludedModels,
634  m_setActions.append(a);
635 
636  a = new QAction(CIcons::delete16(), "Remove non DB models", this);
637  connect(a, &QAction::triggered, ownModelSetComp, &CDbOwnModelSetComponent::removeNonDBModels,
639  m_setActions.append(a);
640  }
641  menuActions.addMenuModelSet();
642  menuActions.addActions(m_setActions, CMenuAction::pathModelSet());
643  menuActions.addActions(m_setNewActions, CMenuAction::pathModelSetNew());
644  }
645  this->nestedCustomMenu(menuActions);
646  }
647 } // 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:845
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.
swift::misc::simulation::CSimulatorInfo getSelectedSimulator() const
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.
void setMappingComponent(CDbMappingComponent *component)
Set the corresponding component.
void triggerSetSimulatorDeferred(const swift::misc::simulation::CSimulatorInfo &simulator)
Deferred init of simulator.
void setModelSet(const swift::misc::simulation::CAircraftModelList &models, const swift::misc::simulation::CSimulatorInfo &simulator)
Set the model set for a given simulator.
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:74
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:14
Models to be used with views, mainly QTableView.
Views, mainly QTableView.
Free functions in swift::misc.
void clicked(bool checked)
void triggered(bool checked)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QObject * sender() const const
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
CaseInsensitive
QueuedConnection