swift
interpolationsetupcomponent.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 <QPointer>
7 
8 #include "ui_interpolationsetupcomponent.h"
9 
11 #include "gui/guiapplication.h"
14 #include "misc/statusmessage.h"
15 
16 using namespace swift::gui::views;
17 using namespace swift::misc;
18 using namespace swift::misc::aviation;
19 using namespace swift::misc::simulation;
20 using namespace swift::core::context;
21 
22 namespace swift::gui::components
23 {
24  CInterpolationSetupComponent::CInterpolationSetupComponent(QWidget *parent)
26  {
27  ui->setupUi(this);
28  ui->cb_IgnoreGlobal->setChecked(true);
29  ui->tvp_InterpolationSetup->menuAddItems(CInterpolationSetupView::MenuRemoveSelectedRows);
30 
31  connect(ui->pb_Save, &QPushButton::clicked, this, &CInterpolationSetupComponent::saveSetup);
32  connect(ui->pb_DeleteOrReset, &QPushButton::clicked, this, &CInterpolationSetupComponent::removeOrResetSetup);
33  connect(ui->pb_Reload, &QPushButton::clicked, this, &CInterpolationSetupComponent::reloadSetup,
34  Qt::QueuedConnection);
35  connect(ui->tvp_InterpolationSetup, &CInterpolationSetupView::doubleClicked, this,
36  &CInterpolationSetupComponent::onRowDoubleClicked);
37  connect(ui->tvp_InterpolationSetup, &CInterpolationSetupView::modelChanged, this,
38  &CInterpolationSetupComponent::onModelChanged, Qt::QueuedConnection);
39  connect(ui->tvp_InterpolationSetup, &CInterpolationSetupView::modelDataChanged, this,
40  &CInterpolationSetupComponent::onModelChanged, Qt::QueuedConnection);
41  connect(ui->tvp_InterpolationSetup, &CInterpolationSetupView::objectsDeleted, this,
42  &CInterpolationSetupComponent::onObjectsDeleted, Qt::QueuedConnection);
43  connect(ui->rb_Callsign, &QRadioButton::released, this, &CInterpolationSetupComponent::onModeChanged);
44  connect(ui->rb_Global, &QRadioButton::released, this, &CInterpolationSetupComponent::onModeChanged);
45  if (sGui && sGui->getIContextSimulator())
46  {
47  connect(sGui->getIContextSimulator(), &IContextSimulator::interpolationAndRenderingSetupChanged, this,
48  &CInterpolationSetupComponent::onSetupChanged, Qt::QueuedConnection);
49  }
50 
51  ui->rb_Global->setChecked(true);
52 
53  QPointer<CInterpolationSetupComponent> myself(this);
54  QTimer::singleShot(1000, this, [=] {
55  if (!sGui || sGui->isShuttingDown()) { return; }
56  if (!myself) { return; }
57  this->onModeChanged();
58  });
59 
60  QTimer::singleShot(30 * 1000, this, [=] {
61  if (!sGui || sGui->isShuttingDown()) { return; }
62  if (!myself) { return; }
63  this->onSetupChanged();
64  });
65  }
66 
68 
70  {
71  return ui->rb_Callsign->isChecked() ? CInterpolationSetupComponent::SetupPerCallsign :
72  CInterpolationSetupComponent::SetupGlobal;
73  }
74 
75  void CInterpolationSetupComponent::onRowDoubleClicked(const QModelIndex &index)
76  {
77  if (!index.isValid()) { return; }
78  const CInterpolationAndRenderingSetupPerCallsign setup = ui->tvp_InterpolationSetup->at(index);
79  ui->form_InterpolationSetup->setValue(setup);
80  ui->comp_CallsignCompleter->setCallsign(setup.getCallsign());
81  ui->comp_CallsignCompleter->setReadOnly(false);
82  ui->rb_Callsign->setChecked(true);
83  }
84 
85  void CInterpolationSetupComponent::onModeChanged()
86  {
87  if (!sGui || sGui->isShuttingDown()) { return; }
88  bool enableCallsign = false;
89  if (this->getSetupMode() == CInterpolationSetupComponent::SetupGlobal) { this->setUiValuesFromGlobal(); }
90  else { enableCallsign = true; }
91  this->displaySetupsPerCallsign();
92  ui->comp_CallsignCompleter->setReadOnly(!enableCallsign);
93  ui->pb_DeleteOrReset->setText(enableCallsign ? "delete" : "reset");
94  }
95 
96  void CInterpolationSetupComponent::onModelChanged()
97  {
98  // void
99  }
100 
101  void CInterpolationSetupComponent::onReloadSetup()
102  {
103  this->reloadSetup();
104  this->displaySetupsPerCallsign();
105  }
106 
107  void CInterpolationSetupComponent::reloadSetup()
108  {
109  const bool global = (this->getSetupMode() == CInterpolationSetupComponent::SetupGlobal);
110  const bool overlay = QObject::sender() == ui->pb_Reload;
111  if (!this->checkPrerequisites(!global, overlay)) { return; }
112  if (global)
113  {
116  ui->form_InterpolationSetup->setValue(gs);
117  }
118  else
119  {
120  const CCallsign cs = ui->comp_CallsignCompleter->getCallsign(false);
121  if (!cs.isValid()) { return; }
124  ui->form_InterpolationSetup->setValue(setup);
125  }
126  }
127 
128  void CInterpolationSetupComponent::saveSetup()
129  {
130  const bool global = (this->getSetupMode() == CInterpolationSetupComponent::SetupGlobal);
131  if (!this->checkPrerequisites(!global, true)) { return; }
132  CInterpolationAndRenderingSetupPerCallsign setup = ui->form_InterpolationSetup->getValue();
135  if (global)
136  {
137  gs.setBaseValues(setup);
138  gs.setLogInterpolation(false); // that would globally log all values
140  CLogMessage(this).info(u"Set global setup: '%1'") << gs.toQString(true);
141 
142  const QPointer<CInterpolationSetupComponent> myself(this);
143  QTimer::singleShot(250, this, [=] {
144  if (!myself) { return; }
145  this->reloadSetup();
146  });
147  }
148  else
149  {
150  const CCallsign cs = ui->comp_CallsignCompleter->getCallsign(false);
151  if (!cs.isValid()) { return; }
152  setup.setCallsign(cs);
153  const bool ignoreGlobal = ui->cb_IgnoreGlobal->isChecked();
154  if (ignoreGlobal && setup.isEqualToGlobal(gs))
155  {
156  static const CStatusMessage m = CStatusMessage(this).validationWarning(u"Same as global setup");
157  this->showOverlayMessage(m);
158  return;
159  }
160 
161  CInterpolationSetupList setups = ui->tvp_InterpolationSetup->container();
162  const int replaced = setups.replaceOrAddObjectByCallsign(setup);
163  if (replaced < 1) { return; }
164  const bool set = this->setSetupsToContext(setups);
165  if (!set) { return; }
166 
167  const QPointer<CInterpolationSetupComponent> myself(this);
168  QTimer::singleShot(250, this, [=] {
169  if (!myself) { return; }
170  this->displaySetupsPerCallsign();
171  });
172  }
173  }
174 
175  void CInterpolationSetupComponent::removeOrResetSetup()
176  {
177  const bool global = (this->getSetupMode() == CInterpolationSetupComponent::SetupGlobal);
178  if (!this->checkPrerequisites(!global, true)) {}
179  if (global)
180  {
181  // reset
184  this->reloadSetup();
185  }
186  else
187  {
188  // delete/remove
189  const CCallsign cs = ui->comp_CallsignCompleter->getCallsign(false);
190  CInterpolationSetupList setups = ui->tvp_InterpolationSetup->container();
191  const int removed = setups.removeByCallsign(cs);
192  if (removed < 1) { return; } // nothing done
193  const bool set = this->setSetupsToContext(setups);
194  if (!set) { return; }
195 
196  const QPointer<CInterpolationSetupComponent> myself(this);
197  QTimer::singleShot(100, this, [=] {
198  if (!myself) { return; }
199  this->displaySetupsPerCallsign();
200  });
201  }
202  }
203 
204  void CInterpolationSetupComponent::setUiValuesFromGlobal()
205  {
206  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Missing sGui");
209  ui->form_InterpolationSetup->setValue(setup);
210  }
211 
212  void CInterpolationSetupComponent::displaySetupsPerCallsign()
213  {
214  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Missing sGui");
215  const CInterpolationSetupList setups =
217  ui->tvp_InterpolationSetup->updateContainerMaybeAsync(setups);
218  }
219 
220  bool CInterpolationSetupComponent::checkPrerequisites(bool checkSim, bool showOverlay)
221  {
223  {
224  if (showOverlay)
225  {
226  const CStatusMessage m = CStatusMessage(this).validationError(u"No context");
227  this->showOverlayMessage(m);
228  }
229  return false;
230  }
231  if (checkSim && !sGui->getIContextSimulator()->isSimulatorAvailable())
232  {
233  if (showOverlay)
234  {
235  const CStatusMessage m = CStatusMessage(this).validationError(u"No simulator available");
236  this->showOverlayMessage(m);
237  }
238  return false;
239  }
240  return true;
241  }
242 
243  bool CInterpolationSetupComponent::setSetupsToContext(const CInterpolationSetupList &setups, bool force)
244  {
245  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextSimulator()) { return false; }
246  if (!force && setups == m_lastSetSetups) { return false; }
247  const bool ignoreGlobal = ui->cb_IgnoreGlobal->isChecked();
249  m_lastSetSetups = setups;
250  return true;
251  }
252 
253  void CInterpolationSetupComponent::onSetupChanged()
254  {
255  if (!sGui || sGui->isShuttingDown()) { return; }
256  this->displaySetupsPerCallsign();
257  }
258 
259  void CInterpolationSetupComponent::onObjectsDeleted(const CVariant &deletedObjects)
260  {
261  if (deletedObjects.canConvert<CInterpolationSetupList>())
262  {
263  const CInterpolationSetupList deletedSetups = deletedObjects.value<CInterpolationSetupList>();
264  if (deletedSetups.isEmpty()) { return; }
265 
266  // make sure the setups are really deleted
267  // it can be they are already in the container, but there is no guarantee
268  CInterpolationSetupList setups = ui->tvp_InterpolationSetup->container();
269  setups.removeByCallsigns(deletedSetups.getCallsigns());
270  const bool set = this->setSetupsToContext(setups, true);
271  Q_UNUSED(set)
272  }
273  }
274 } // namespace swift::gui::components
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
virtual bool setInterpolationAndRenderingSetupsPerCallsign(const swift::misc::simulation::CInterpolationSetupList &setups, bool ignoreSameAsGlobal)=0
Set all setups per callsign.
virtual void setInterpolationAndRenderingSetupGlobal(const swift::misc::simulation::CInterpolationAndRenderingSetupGlobal &setup)=0
Set the global setup.
bool isSimulatorAvailable() const
Simulator avialable (driver available)?
virtual swift::misc::simulation::CInterpolationSetupList getInterpolationAndRenderingSetupsPerCallsign() const =0
Get all setups per callsign.
virtual swift::misc::simulation::CInterpolationAndRenderingSetupPerCallsign getInterpolationAndRenderingSetupPerCallsignOrDefault(const swift::misc::aviation::CCallsign &callsign) const =0
Get the setup for callsign, if not existing the global setup.
virtual swift::misc::simulation::CInterpolationAndRenderingSetupGlobal getInterpolationAndRenderingSetupGlobal() const =0
The global setup.
bool showOverlayMessage(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Show single message.
Using this class provides a QFrame with the overlay functionality already integrated.
Class for emitting a log message.
Definition: logmessage.h:27
Derived & validationError(const char16_t(&format)[N])
Set the severity to error, providing a format string, and adding the validation category.
Derived & validationWarning(const char16_t(&format)[N])
Set the severity to warning, providing a format string, and adding the validation category.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Streamable status message, e.g.
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Definition: variant.h:66
T value() const
Return the value converted to the type T.
Definition: variant.h:169
bool canConvert(int typeId) const
True if this variant can be converted to the type with the given metatype ID.
Value object encapsulating information of a callsign.
Definition: callsign.h:30
bool isValid() const
Valid callsign?
Definition: callsign.cpp:359
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:76
void setBaseValues(const CInterpolationAndRenderingSetupBase &baseValues)
Set all base values.
Value object for interpolator and rendering per callsign.
bool isEqualToGlobal(const CInterpolationAndRenderingSetupGlobal &globalSetup) const
Equal to global setup?
void setCallsign(const aviation::CCallsign &callsign)
Set callsign.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
High level reusable GUI components.
Definition: aboutdialog.cpp:13
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