swift
dbloaddatadialog.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2018 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QDialogButtonBox>
7 #include <QModelIndexList>
8 #include <QPointer>
9 #include <QStringBuilder>
10 
11 #include "ui_dbloaddatadialog.h"
12 
13 #include "core/db/databaseutils.h"
14 #include "core/webdataservices.h"
15 #include "gui/guiapplication.h"
16 #include "misc/logmessage.h"
18 
19 using namespace swift::misc;
20 using namespace swift::misc::network;
21 using namespace swift::misc::simulation;
22 using namespace swift::misc::simulation::data;
23 using namespace swift::core;
24 using namespace swift::core::db;
25 
26 namespace swift::gui::components
27 {
28  CDbLoadDataDialog::CDbLoadDataDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CDbLoadDataDialog)
29  {
30  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Need sGui");
31  ui->setupUi(this);
32  this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
33  QStringListModel *lvm = new QStringListModel(ui->lv_Entities);
34  ui->comp_SimulatorSelector->setMode(CSimulatorSelector::RadioButtons);
35  ui->lv_Entities->setModel(lvm);
36  ui->bb_loadDataDialog->button(QDialogButtonBox::Apply)->setText("Load");
37  ui->wi_WorkStatus->setVisible(false);
38  ui->wi_Consolidate->setVisible(false);
39  ui->comp_SimulatorSelector->setRememberSelection(true);
40  connect(sGui->getWebDataServices(), &CWebDataServices::dataRead, this, &CDbLoadDataDialog::onDataRead,
41  Qt::QueuedConnection);
42  connect(sGui->getWebDataServices(), &CWebDataServices::entityDownloadProgress, this,
43  &CDbLoadDataDialog::onEntityDownloadProgress, Qt::QueuedConnection);
44  connect(ui->bb_loadDataDialog, &QDialogButtonBox::clicked, this, &CDbLoadDataDialog::onButtonClicked);
45  connect(ui->pb_Consolidate, &QPushButton::clicked, this, &CDbLoadDataDialog::consolidate);
46  connect(this, &CDbLoadDataDialog::rejected, this, &CDbLoadDataDialog::onRejected);
47  }
48 
50 
51  bool CDbLoadDataDialog::newerOrEmptyEntitiesDetected(CEntityFlags::Entity loadEntities)
52  {
53  this->show();
55  if (m_consolidating) { return false; }
56  if (m_pendingEntities != CEntityFlags::NoEntity) { return false; } // already loading
57  if (loadEntities == CEntityFlags::NoEntity) { return false; }
58  m_autoConsolidate = false;
59  const QStringList entitiesStringList = CEntityFlags::entitiesToStringList(loadEntities);
60  this->entitiesModel()->setStringList(entitiesStringList);
61  ui->lv_Entities->selectAll();
62  return true;
63  }
64 
65  QStringListModel *CDbLoadDataDialog::entitiesModel() const
66  {
67  return qobject_cast<QStringListModel *>(ui->lv_Entities->model());
68  }
69 
70  QStringList CDbLoadDataDialog::selectedEntities() const
71  {
72  QStringList entities;
73  const QModelIndexList indexes = ui->lv_Entities->selectionModel()->selectedIndexes();
74  for (const QModelIndex &index : indexes) { entities.append(index.data(Qt::DisplayRole).toString()); }
75  return entities;
76  }
77 
78  void CDbLoadDataDialog::onButtonClicked(QAbstractButton *button)
79  {
80  if (!button) { return; }
81  if (button == ui->bb_loadDataDialog->button(QDialogButtonBox::Apply))
82  {
83  const QStringList entityList = this->selectedEntities();
84  if (entityList.isEmpty()) { return; }
85  const CEntityFlags::Entity loadEntities = CEntityFlags::multipleEntitiesByNames(entityList);
86  m_pendingEntities = sGui->getWebDataServices()->triggerLoadingDirectlyFromSharedFiles(loadEntities, false);
87  const int pending = CEntityFlags::numberOfEntities(m_pendingEntities);
88  m_pendingEntitiesCount = sGui->getWebDataServices()->getDbInfoObjectsCount(loadEntities);
89  ui->pb_Loading->setMaximum(m_pendingEntitiesCount > 0 ? m_pendingEntitiesCount : pending);
90  ui->pb_Loading->setValue(0);
91  ui->wi_WorkStatus->setVisible(pending > 0);
92  ui->wi_Consolidate->setVisible(false);
93  ui->le_Info->setText("Loading started ...");
94  }
95  }
96 
97  void CDbLoadDataDialog::onDataRead(CEntityFlags::Entity entity, CEntityFlags::ReadState state, int number,
98  const QUrl &url)
99  {
100  if (m_pendingEntities == CEntityFlags::NoEntity) { return; } // not triggered from here
101  if (!m_pendingEntities.testFlag(CEntityFlags::entityToEntityFlag(entity))) { return; }
102 
103  const QString e = CEntityFlags::entitiesToString(entity);
104  const QString s = CEntityFlags::stateToString(state);
105 
106  ui->le_Info->setText(e % u" " % s);
107  if (!CEntityFlags::isFinishedReadStateOrFailure(state)) { return; }
108  if (state == CEntityFlags::ReadFailed)
109  {
110  CLogMessage(this).warning(u"Read failed for %1 from '%2'") << e << url.toString();
111  }
112 
113  m_pendingEntities &= ~entity;
114  const int pending = CEntityFlags::numberOfEntities(m_pendingEntities);
115  const int max = ui->pb_Loading->maximum();
116  if (m_pendingEntitiesCount < 0) { ui->pb_Loading->setValue(max - pending); }
117  else
118  {
119  m_pendingEntitiesCount -= number;
120  ui->pb_Loading->setValue(max - m_pendingEntitiesCount);
121  }
122  if (pending < 1)
123  {
124  m_pendingEntitiesCount = -1;
125  const bool defaultConsolidate = !ui->cb_AllModels->isChecked() && ui->cb_ModelSet->isChecked();
126 
127  QPointer<CDbLoadDataDialog> myself(this);
128  QTimer::singleShot(2000, this, [=] {
129  if (!myself) { return; }
130  ui->wi_Consolidate->setVisible(true);
131  ui->wi_WorkStatus->setVisible(false);
132  if (defaultConsolidate)
133  {
134  m_autoConsolidate = true;
135  QPointer<CDbLoadDataDialog> self(
136  this); // 2nd "self"/"myself" for cppcheck identicalConditionAfterEarlyExit
137  QTimer::singleShot(1000, this, [=] {
138  if (!self) { return; }
139  self->consolidate();
140  });
141  }
142  });
143  }
144  }
145 
146  void CDbLoadDataDialog::onEntityDownloadProgress(CEntityFlags::Entity entity, int logId, int progress,
147  qint64 current, qint64 max, const QUrl &url)
148  {
149  Q_UNUSED(entity)
150  Q_UNUSED(logId)
151  Q_UNUSED(progress)
152  Q_UNUSED(current)
153  Q_UNUSED(max)
154  Q_UNUSED(url)
155  }
156 
157  void CDbLoadDataDialog::onRejected()
158  {
159  m_pendingEntities = CEntityFlags::NoEntity;
160  m_pendingEntitiesCount = -1;
161  m_autoConsolidate = false;
162  ui->pb_Loading->setVisible(false);
163  }
164 
165  void CDbLoadDataDialog::consolidate()
166  {
167  const bool set = ui->cb_ModelSet->isChecked();
168  const bool all = ui->cb_AllModels->isChecked();
169  if (m_consolidating) { return; }
170  if (!set && !all) { return; }
171  ui->wi_WorkStatus->setVisible(true);
172  ui->pb_Loading->setValue(0);
173  ui->pb_Loading->setMaximum(0); // 0/0 causing busy indicator
174  const CSimulatorInfo simulator = ui->comp_SimulatorSelector->getValue();
175 
176  do {
177  if (set)
178  {
179  ui->le_Info->setText("Model set");
180  CAircraftModelList models = m_sets.getCachedModels(simulator);
181  const int c = CDatabaseUtils::consolidateModelsWithDbDataAllowsGuiRefresh(models, true, true);
182  if (c > 0) { m_sets.setCachedModels(models, simulator); }
183  }
184 
185  if (!this->isVisible()) { break; } // dialog closed?
186  if (all)
187  {
188  ui->le_Info->setText("All models");
189  CAircraftModelList models = m_models.getCachedModels(simulator);
190  const int c = CDatabaseUtils::consolidateModelsWithDbDataAllowsGuiRefresh(models, true, true);
191  if (c > 0) { m_models.setCachedModels(models, simulator); }
192  }
193  }
194  while (false);
195 
196  m_consolidating = false;
197 
198  QPointer<CDbLoadDataDialog> myself(this);
199  QTimer::singleShot(2000, this, [=] {
200  if (!myself) { return; }
201  ui->pb_Loading->setMaximum(100);
202  ui->wi_WorkStatus->setVisible(false);
203  if (m_autoConsolidate)
204  {
205  m_autoConsolidate = false;
206  this->accept();
207  }
208  });
209  }
210 } // namespace swift::gui::components
CWebDataServices * getWebDataServices() const
Get the web data services.
swift::misc::network::CEntityFlags::Entity triggerLoadingDirectlyFromSharedFiles(swift::misc::network::CEntityFlags::Entity whatToRead, bool checkCacheTsUpfront)
Trigger reload from shared files, loads the data and bypasses caches.
int getDbInfoObjectsCount(swift::misc::network::CEntityFlags::Entity entities, bool stopIfNotFound=true) const
Count for 1-n entities from DB entity objects.
static void modalWindowToFront()
Bring any modal dialog to front.
bool newerOrEmptyEntitiesDetected(swift::misc::network::CEntityFlags::Entity loadEntities)
Newer or empty entities detected.
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.
Value object encapsulating a list of aircraft models.
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
CAircraftModelList getCachedModels(const CSimulatorInfo &simulator) const
Models for simulator.
CStatusMessage setCachedModels(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Set cached models.
CStatusMessage setCachedModels(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Set cached models.
CAircraftModelList getCachedModels(const CSimulatorInfo &simulator) const
Models for simulator.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Classes interacting with the swift database (aka "datastore").
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:13
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