swift
mappingcomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QCheckBox>
7 #include <QCompleter>
8 #include <QLabel>
9 #include <QLineEdit>
10 #include <QPixmap>
11 #include <QPointer>
12 #include <QPushButton>
13 #include <QStringListModel>
14 #include <QtGlobal>
15 
16 #include "mappingcomponent.h"
17 #include "ui_mappingcomponent.h"
18 
21 #include "gui/guiapplication.h"
22 #include "gui/guiutility.h"
28 #include "gui/views/viewbase.h"
29 #include "misc/aviation/callsign.h"
30 #include "misc/icons.h"
31 #include "misc/logmessage.h"
33 #include "misc/network/server.h"
34 #include "misc/pixmap.h"
38 #include "misc/statusmessage.h"
39 
40 using namespace swift::misc;
41 using namespace swift::misc::simulation;
42 using namespace swift::misc::network;
43 using namespace swift::misc::aviation;
44 using namespace swift::misc::physical_quantities;
45 using namespace swift::core;
46 using namespace swift::core::context;
47 using namespace swift::gui::views;
48 using namespace swift::gui::models;
49 using namespace swift::gui::filters;
50 using namespace swift::gui::settings;
51 
52 namespace swift::gui::components
53 {
54  const QStringList &CMappingComponent::getLogCategories()
55  {
56  static const QStringList cats({ CLogCategories::mapping(), CLogCategories::guiComponent() });
57  return cats;
58  }
59 
60  CMappingComponent::CMappingComponent(QWidget *parent)
61  : COverlayMessagesFrame(parent), CIdentifiable(this), ui(new Ui::CMappingComponent)
62  {
63  Q_ASSERT_X(sGui, Q_FUNC_INFO, "need sGui");
64  Q_ASSERT_X(sGui->getIContextSimulator(), Q_FUNC_INFO, "need simulator context");
65  Q_ASSERT_X(sGui->getIContextNetwork(), Q_FUNC_INFO, "need network context");
66 
67  ui->setupUi(this);
68  ui->tw_SpecializedViews->setCurrentIndex(0);
69 
70  ui->tvp_AircraftModels->setAircraftModelMode(CAircraftModelListModel::OwnAircraftModelClient);
71  ui->tvp_AircraftModels->setResizeMode(CAircraftModelView::ResizingOff);
72  ui->tvp_AircraftModels->addFilterDialog();
73  ui->tvp_AircraftModels->menuRemoveItems(CAircraftModelView::MenuBackend);
74  ui->tvp_AircraftModels->menuAddItems(CAircraftModelView::MenuDisableModelsTemp);
75 
76  ui->tvp_RenderedAircraft->setAircraftMode(CSimulatedAircraftListModel::RenderedMode);
77  ui->tvp_RenderedAircraft->setResizeMode(CAircraftModelView::ResizingOnce);
78  ui->tvp_RenderedAircraft->menuAddItems(CAircraftModelView::MenuDisableModelsTemp);
79 
80  connect(sGui->getIContextNetwork(), &IContextNetwork::connectionStatusChanged, this,
81  &CMappingComponent::onNetworkConnectionStatusChanged);
82 
83  connect(ui->tvp_AircraftModels, &CAircraftModelView::requestUpdate, this,
84  &CMappingComponent::onModelsUpdateRequested);
85  connect(ui->tvp_AircraftModels, &CAircraftModelView::modelDataChanged, this,
86  &CMappingComponent::onRowCountChanged);
87  connect(ui->tvp_AircraftModels, &CAircraftModelView::requestTempDisableModelsForMatching, this,
88  &CMappingComponent::onTempDisableModelsForMatchingRequested);
89 
90  connect(ui->tvp_RenderedAircraft, &CSimulatedAircraftView::modelDataChanged, this,
91  &CMappingComponent::onRowCountChanged);
92  connect(ui->tvp_RenderedAircraft, &CSimulatedAircraftView::clicked, this,
93  &CMappingComponent::onAircraftSelectedInView);
94  connect(ui->tvp_RenderedAircraft, &CSimulatedAircraftView::requestUpdate, this,
95  &CMappingComponent::tokenBucketUpdate);
96  connect(ui->tvp_RenderedAircraft, &CSimulatedAircraftView::requestTextMessageWidget, this,
98  connect(ui->tvp_RenderedAircraft, &CSimulatedAircraftView::requestTempDisableModelsForMatching, this,
99  &CMappingComponent::onTempDisableModelsForMatchingRequested);
100 
101  connect(ui->pb_SaveAircraft, &QPushButton::clicked, this, &CMappingComponent::onSaveAircraft);
102  connect(ui->pb_ResetAircraft, &QPushButton::clicked, this, &CMappingComponent::onResetAircraft);
103  connect(ui->pb_LoadModels, &QPushButton::clicked, this, &CMappingComponent::onModelsUpdateRequested);
104  connect(ui->pb_DoMatchingAgain, &QPushButton::clicked, this, &CMappingComponent::doMatchingsAgain);
105  connect(ui->pb_ValidateModelSet, &QPushButton::clicked, this, &CMappingComponent::requestValidationDialog);
106 
107  m_currentMappingsViewDelegate = new CCheckBoxDelegate(":/diagona/icons/diagona/icons/tick.png",
108  ":/diagona/icons/diagona/icons/cross.png", this);
109  ui->tvp_RenderedAircraft->setItemDelegateForColumn(0, m_currentMappingsViewDelegate);
110 
111  // overlay
112  this->setReducedInfo(true);
113  this->setForceSmall(true);
114 
115  // Aircraft previews
116  connect(ui->cb_AircraftIconDisplayed, &QCheckBox::stateChanged, this,
117  &CMappingComponent::onModelPreviewChanged);
118 
119  // model string completer
120  ui->completer_ModelStrings->setSourceVisible(CAircraftModelStringCompleter::OwnModels, false);
121  ui->completer_ModelStrings->selectSource(CAircraftModelStringCompleter::ModelSet);
122 
123  // Updates
124  connect(&m_updateTimer, &QTimer::timeout, this, &CMappingComponent::timerUpdate);
125  m_updateTimer.setObjectName(this->objectName() + "::updateTimer");
126  ui->tvp_AircraftModels->setDisplayAutomatically(false);
127  this->settingsChanged();
128 
129  // selector
130  ui->comp_SimulatorSelector->setRememberSelection(false); // pilot client UI
131  ui->comp_SimulatorSelector->setMode(CSimulatorSelector::ComboBox);
132  ui->comp_SimulatorSelector->setToConnectedSimulator();
133  connect(ui->comp_SimulatorSelector, &CSimulatorSelector::changed, this,
134  &CMappingComponent::onModelSetSimulatorChanged);
135 
136  // connect
137  connect(sGui->getIContextSimulator(), &IContextSimulator::modelSetChanged, this,
138  &CMappingComponent::onModelSetChanged, Qt::QueuedConnection);
139  connect(sGui->getIContextSimulator(), &IContextSimulator::modelMatchingCompleted, this,
140  &CMappingComponent::tokenBucketUpdateAircraft, Qt::QueuedConnection);
141  connect(sGui->getIContextSimulator(), &IContextSimulator::aircraftRenderingChanged, this,
142  &CMappingComponent::tokenBucketUpdateAircraft, Qt::QueuedConnection);
143  connect(sGui->getIContextSimulator(), &IContextSimulator::airspaceSnapshotHandled, this,
144  &CMappingComponent::tokenBucketUpdate, Qt::QueuedConnection);
145  connect(sGui->getIContextSimulator(), &IContextSimulator::addingRemoteModelFailed, this,
146  &CMappingComponent::onAddingRemoteAircraftFailed, Qt::QueuedConnection);
147  connect(sGui->getIContextSimulator(), &IContextSimulator::simulatorPluginChanged, this,
148  &CMappingComponent::onSimulatorPluginChanged, Qt::QueuedConnection);
149  connect(sGui->getIContextSimulator(), &IContextSimulator::simulatorStatusChanged, this,
150  &CMappingComponent::onSimulatorStatusChanged, Qt::QueuedConnection);
151  connect(sGui->getIContextNetwork(), &IContextNetwork::changedRemoteAircraftModel, this,
152  &CMappingComponent::onRemoteAircraftModelChanged, Qt::QueuedConnection);
153  connect(sGui->getIContextNetwork(), &IContextNetwork::changedRemoteAircraftEnabled, this,
154  &CMappingComponent::tokenBucketUpdateAircraft, Qt::QueuedConnection);
155  connect(sGui->getIContextNetwork(), &IContextNetwork::changedFastPositionUpdates, this,
156  &CMappingComponent::tokenBucketUpdateAircraft, Qt::QueuedConnection);
157  connect(sGui->getIContextNetwork(), &IContextNetwork::changedGndFlagCapability, this,
158  &CMappingComponent::tokenBucketUpdateAircraft, Qt::QueuedConnection);
159  connect(sGui->getIContextNetwork(), &IContextNetwork::removedAircraft, this,
160  &CMappingComponent::tokenBucketUpdate, Qt::QueuedConnection);
161  connect(sGui->getIContextNetwork(), &IContextNetwork::connectionStatusChanged, this,
162  &CMappingComponent::onConnectionStatusChanged, Qt::QueuedConnection);
163 
164  connect(ui->tw_SpecializedViews, &QTabWidget::currentChanged, this, &CMappingComponent::onTabWidgetChanged);
165 
166  // requires simulator context
167  connect(ui->tvp_RenderedAircraft, &CAircraftModelView::objectChanged, this,
168  &CMappingComponent::onChangedSimulatedAircraftInView, Qt::QueuedConnection);
169 
170  // with external core models might be already available
171  // nevertheless, wait some time to allow to init
172  QPointer<CMappingComponent> myself(this);
173  QTimer::singleShot(10000, this, [=] {
174  if (!myself || !sGui || sGui->isShuttingDown()) { return; }
175  const CSimulatorInfo simulator(myself->getConnectedOrSelectedSimulator());
176  myself->onModelSetSimulatorChanged(simulator);
177  myself->onModelSetChanged(simulator);
178  });
179  }
180 
182 
184  {
185  Q_ASSERT(ui->tvp_RenderedAircraft);
186  return ui->tvp_RenderedAircraft->rowCount();
187  }
188 
190  {
191  Q_ASSERT(ui->tvp_AircraftModels);
192  return ui->tvp_AircraftModels->rowCount();
193  }
194 
196  {
197  const int tabIndex = static_cast<int>(tab);
198  ui->tw_SpecializedViews->setCurrentIndex(tabIndex);
199  }
200 
201  CAircraftModelList CMappingComponent::findModelsStartingWith(const QString &modelName, Qt::CaseSensitivity cs)
202  {
203  Q_ASSERT(ui->tvp_AircraftModels);
204  return ui->tvp_AircraftModels->container().findModelsStartingWith(modelName, cs);
205  }
206 
207  void CMappingComponent::onModelSetChanged(const CSimulatorInfo &dummy)
208  {
209  // changed model set, which can be any model set
210  Q_UNUSED(dummy); // we do not use the passed simulator
211 
212  const CSimulatorInfo simulator(ui->comp_SimulatorSelector->getValue()); // UI value
213  const bool changed = ui->completer_ModelStrings->setSimulator(simulator);
214  if (!changed) { return; }
215 
216  if (ui->tvp_AircraftModels->displayAutomatically()) { this->onModelsUpdateRequested(); }
217  else
218  {
219  CLogMessage(this).info(u"Model set loaded ('%1'), you can update the model view")
220  << simulator.toQString(true);
221  }
222  }
223 
224  void CMappingComponent::onRowCountChanged(int count, bool withFilter)
225  {
226  Q_UNUSED(count);
227  Q_UNUSED(withFilter);
228  const int am = ui->tw_SpecializedViews->indexOf(ui->tb_AircraftModels);
229  const int cm = ui->tw_SpecializedViews->indexOf(ui->tb_CurrentMappings);
230  const QString amf = ui->tvp_AircraftModels->derivedModel()->hasFilter() ? "F" : "";
231  QString a = ui->tw_SpecializedViews->tabBar()->tabText(am);
232  QString c = ui->tw_SpecializedViews->tabBar()->tabText(cm);
235  ui->tw_SpecializedViews->tabBar()->setTabText(am, a);
236  ui->tw_SpecializedViews->tabBar()->setTabText(cm, c);
237  }
238 
239  void CMappingComponent::onChangedSimulatedAircraftInView(const CVariant &object, const CPropertyIndex &index)
240  {
241  if (!index.contains(CSimulatedAircraft::IndexEnabled)) { return; } // we only deal with enabled/disabled here
242  const CSimulatedAircraft sa = object.to<CSimulatedAircraft>(); // changed in GUI
243  const CSimulatedAircraft saFromBackend =
245  if (!saFromBackend.hasValidCallsign()) { return; } // obviously deleted
246  const bool nowEnabled = sa.isEnabled();
247  if (saFromBackend.isEnabled() == nowEnabled) { return; } // already same value
248  CLogMessage(this).info(u"Request to %1 aircraft '%2'")
249  << (nowEnabled ? "enable" : "disable") << saFromBackend.getCallsign().toQString();
250  sGui->getIContextNetwork()->updateAircraftEnabled(saFromBackend.getCallsign(), nowEnabled);
251  }
252 
253  void CMappingComponent::onAircraftSelectedInView(const QModelIndex &index)
254  {
255  const CSimulatedAircraft simAircraft = ui->tvp_RenderedAircraft->at(index);
256  ui->cb_AircraftEnabled->setChecked(simAircraft.isEnabled());
257  ui->le_Callsign->setText(simAircraft.getCallsign().asString());
258  ui->completer_ModelStrings->setModel(simAircraft.getModel());
259  }
260 
261  CCallsign CMappingComponent::validateRenderedCallsign()
262  {
263  const QString cs = ui->le_Callsign->text().trimmed();
264  if (!CCallsign::isValidAircraftCallsign(cs))
265  {
266  this->showOverlayMessage(CStatusMessage(this).validationError(u"Invalid callsign for mapping"),
267  OverlayMessageMs);
268  return CCallsign();
269  }
270 
271  const CCallsign callsign(cs);
272  const bool hasCallsign = ui->tvp_RenderedAircraft->container().containsCallsign(callsign);
273  if (!hasCallsign)
274  {
275  const CStatusMessage msg = CStatusMessage(this).validationError(u"Unmapped callsign '%1' for mapping")
276  << callsign.asString();
277  this->showOverlayMessage(msg);
278  return CCallsign();
279  }
280  return callsign;
281  }
282 
283  void CMappingComponent::onModelSetSimulatorChanged(const CSimulatorInfo &simulator)
284  {
285  if (!sGui || this->isSimulatorAvailable()) { return; }
287 
288  // completer will be changed in onModelSetChanged
289  }
290 
291  void CMappingComponent::onSimulatorPluginChanged(const CSimulatorPluginInfo &pluginInfo)
292  {
293  Q_UNUSED(pluginInfo);
294  ui->comp_SimulatorSelector->setToConnectedSimulator(50);
295  }
296 
297  void CMappingComponent::onSimulatorStatusChanged(int status)
298  {
299  const ISimulator::SimulatorStatus simStatus = static_cast<ISimulator::SimulatorStatus>(status);
300 
301  // make sure the selector represents connected simulator
302  if (simStatus.testFlag(ISimulator::Connected) && sGui && sGui->getIContextSimulator())
303  {
304  ui->comp_SimulatorSelector->setToConnectedSimulator(50);
305  }
306  }
307 
308  void CMappingComponent::doMatchingsAgain()
309  {
310  using namespace std::chrono_literals;
311 
312  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextSimulator()) { return; }
313  if (!sGui->getIContextSimulator()->isSimulatorAvailable()) { return; }
314  const int rematchedNumber = sGui->getIContextSimulator()->doMatchingsAgain();
315 
316  const QString info = QStringLiteral("Triggered re-matching of %1 aircraft").arg(rematchedNumber);
317  this->showOverlayHTMLMessage(info, 5s);
318  CLogMessage(this).info(info);
319  }
320 
321  void CMappingComponent::onSaveAircraft()
322  {
324  {
325  return;
326  }
327  const CCallsign callsign(this->validateRenderedCallsign());
328  if (callsign.isEmpty()) { return; }
329  const QString modelString = ui->completer_ModelStrings->getModelString();
330  if (modelString.isEmpty())
331  {
332  this->showOverlayHTMLMessage(CStatusMessage(this).validationError(u"Missing model for mapping"),
333  OverlayMessageMs);
334  return;
335  }
336 
337  // model in current view (data already in UI)
338  bool hasModel = ui->tvp_AircraftModels->container().containsModelString(modelString);
339  if (!hasModel && sGui && sGui->getIContextSimulator())
340  {
341  hasModel = sGui->getIContextSimulator()->isKnownModelInSet(modelString);
342  }
343 
344  if (!hasModel)
345  {
346  this->showOverlayMessage(
347  CStatusMessage(this).validationError(u"Invalid model for mapping, reloading model set"),
348  OverlayMessageMs);
349  if (ui->tvp_AircraftModels->isEmpty()) { this->onModelsUpdateRequested(); }
350  return;
351  }
352 
353  const CSimulatedAircraft aircraftFromBackend =
355  const bool enabled = ui->cb_AircraftEnabled->isChecked();
356  bool changed = false;
357 
358  // changed model?
359  if (aircraftFromBackend.getModelString() != modelString)
360  {
362  if (models.isEmpty())
363  {
364  const CStatusMessage msg = CStatusMessage(this).validationError(u"No model for title: '%1'")
365  << modelString;
366  this->showOverlayMessage(msg, OverlayMessageMs);
367  return;
368  }
369 
370  CAircraftModel model(models.front());
371  if (models.size() > 1)
372  {
373  if (models.containsModelString(modelString))
374  {
375  model = models.findByModelString(modelString).front(); // exact match
376  }
377  else
378  {
379  const CStatusMessage msg = CStatusMessage(this).validationInfo(u"Ambigious title: '%1', using '%2'")
380  << modelString << model.getModelString();
381  this->showOverlayMessage(msg, OverlayMessageMs);
382  }
383  }
384  model.setModelType(CAircraftModel::TypeManuallySet);
385  CLogMessage(this).info(u"Requesting changes for '%1'") << callsign.asString();
386 
387  // enable in any case
388  sGui->getIContextNetwork()->updateAircraftEnabled(aircraftFromBackend.getCallsign(), true);
389  changed =
390  sGui->getIContextNetwork()->updateAircraftModel(aircraftFromBackend.getCallsign(), model, identifier());
391  }
392  if (aircraftFromBackend.isEnabled() != enabled)
393  {
394  changed = sGui->getIContextNetwork()->updateAircraftEnabled(aircraftFromBackend.getCallsign(), enabled);
395  }
396 
397  if (!changed)
398  {
399  this->showOverlayHTMLMessage(CLogMessage(this).info(u"Model mapping, nothing to change"), OverlayMessageMs);
400  }
401  }
402 
403  void CMappingComponent::onResetAircraft()
404  {
405  using namespace std::chrono_literals;
406 
408  {
409  return;
410  }
411  const CCallsign callsign(this->validateRenderedCallsign());
412  if (callsign.isEmpty()) { return; }
413  const bool reset = sGui->getIContextSimulator()->resetToModelMatchingAircraft(callsign);
414  const CStatusMessage msg = reset ? CStatusMessage(this).info(u"Model reset for '%1'") << callsign.toQString() :
415  CStatusMessage(this).info(u"Reset failed for '%1'") << callsign.toQString();
416  this->showOverlayHTMLMessage(msg, 3s);
417  }
418 
419  void CMappingComponent::onModelPreviewChanged(int state)
420  {
421  Q_UNUSED(state);
422  this->closeOverlay();
423  }
424 
425  void CMappingComponent::onModelsUpdateRequested()
426  {
427  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextSimulator()) { return; }
429 
431  const bool hasDisabledModels = !disabledModels.isEmpty();
432 
433  ui->tvp_AircraftModels->setHighlightColor(Qt::red);
434  ui->tvp_AircraftModels->setHighlight(hasDisabledModels);
435  ui->tvp_AircraftModels->setHighlightModels(disabledModels);
436  ui->tvp_AircraftModels->updateContainerMaybeAsync(modelSet);
437  ui->tw_SpecializedViews->setCurrentIndex(TabAircraftModels);
438  }
439 
440  void CMappingComponent::onTempDisableModelsForMatchingRequested(const CAircraftModelList &models)
441  {
442  if (models.isEmpty()) { return; }
443  if (sGui && sGui->getIContextSimulator())
444  {
446  const CStatusMessage m = CLogMessage(this).info(u"Disabled %1 model(s): %2")
447  << models.size() << models.getCallsignsAsString(", ", true);
448  this->showOverlayHTMLMessage(m, OverlayMessageMs);
449  this->onModelsUpdateRequested();
450  }
451  }
452 
453  void CMappingComponent::onRemoteAircraftModelChanged(const CSimulatedAircraft &aircraft,
454  const CIdentifier &originator)
455  {
456  if (CIdentifiable::isMyIdentifier(originator)) { return; }
457  this->tokenBucketUpdateAircraft(aircraft);
458  }
459 
460  void CMappingComponent::onConnectionStatusChanged(const CConnectionStatus &from, const CConnectionStatus &to)
461  {
462  Q_UNUSED(from);
463  if (to.isDisconnected())
464  {
465  this->tokenBucketUpdate();
466  ui->tvp_RenderedAircraft->clear();
467  }
468  else if (to.isConnected())
469  {
470  if (sGui && sGui->getIContextNetwork())
471  {
472  const CServer server = sGui->getIContextNetwork()->getConnectedServer();
473  const bool sendFast = server.getFsdSetup().sendInterimPositions();
474  ui->tvp_RenderedAircraft->configureMenuFastPositionUpdates(sendFast);
475  }
476  }
477  }
478 
479  CSimulatorInfo CMappingComponent::getConnectedOrSelectedSimulator() const
480  {
481  if (this->isSimulatorAvailable()) { return sGui->getIContextSimulator()->isSimulatorAvailable(); }
482  return ui->comp_SimulatorSelector->getValue();
483  }
484 
485  bool CMappingComponent::isSimulatorAvailable() const
486  {
487  if (!sGui || !sGui->getIContextSimulator()) { return false; }
489  }
490 
491  void CMappingComponent::showAircraftModelDetails(bool show)
492  {
493  QList<int> sizes = ui->sp_MappingComponentSplitter->sizes();
494  Q_ASSERT_X(sizes.size() == 2, Q_FUNC_INFO, "Wrong splitter sizes");
495  const int total = sizes[0] + sizes[1];
496  QList<int> newSizes({ 0, 0 });
497  if (show)
498  {
499  newSizes[0] = qRound(total * 0.8);
500  newSizes[1] = qRound(total * 0.2);
501  }
502  else
503  {
504  newSizes[0] = total;
505  newSizes[1] = 0;
506  }
507  ui->sp_MappingComponentSplitter->setSizes(newSizes);
508  }
509 
510  void CMappingComponent::onAddingRemoteAircraftFailed(const CSimulatedAircraft &aircraft, bool disabled,
511  bool failover, const CStatusMessage &message)
512  {
513  this->tokenBucketUpdate();
514  Q_UNUSED(failover);
515  Q_UNUSED(aircraft);
516  Q_UNUSED(message);
517  Q_UNUSED(disabled);
518  }
519 
520  void CMappingComponent::onTabWidgetChanged(int index)
521  {
522  Q_UNUSED(index);
523  const TabWidget w = static_cast<TabWidget>(index);
524  const bool show = (w == TabAircraftModels) || (w == TabRenderedAircraft);
525  this->showAircraftModelDetails(show);
526  }
527 
528  void CMappingComponent::updateRenderedAircraftView(bool forceUpdate)
529  {
530  if (!sGui || sGui->isShuttingDown()) { return; }
531  m_updateTimer.start(); // restart
532  if (!forceUpdate && !this->isVisibleWidget())
533  {
534  m_missedRenderedAircraftUpdate = true;
535  return;
536  }
537 
538  m_missedRenderedAircraftUpdate = false;
539  m_updateTimer.start(); // restart
541  {
543  ui->tvp_RenderedAircraft->updateContainerMaybeAsync(aircraft);
544  }
545  else { ui->tvp_RenderedAircraft->clear(); }
546  }
547 
548  void CMappingComponent::timerUpdate()
549  {
550  // timer update to update position, speed ...
551  this->updateRenderedAircraftView(false); // unforced
552  }
553 
554  void CMappingComponent::tokenBucketUpdateAircraft(const CSimulatedAircraft &aircraft)
555  {
556  Q_UNUSED(aircraft);
557  this->tokenBucketUpdate();
558  }
559 
560  void CMappingComponent::tokenBucketUpdate()
561  {
562  if (!m_bucket.tryConsume()) { return; }
563  this->updateRenderedAircraftView(true); // forced update
564  }
565 
566  void CMappingComponent::settingsChanged()
567  {
568  const CViewUpdateSettings settings = m_settings.get();
569  const int ms = settings.getRenderingUpdateTime().toMs();
570  m_updateTimer.setInterval(ms);
571  }
572 
573  void CMappingComponent::onNetworkConnectionStatusChanged(const CConnectionStatus &from, const CConnectionStatus &to)
574  {
575  Q_UNUSED(from);
576  if (to.isDisconnected())
577  {
578  ui->tvp_RenderedAircraft->clear();
579  m_updateTimer.stop();
580  }
581  else if (to.isConnected())
582  {
583  ui->comp_SimulatorSelector->setReadOnly(true);
584  m_updateTimer.start();
585  }
586  }
587 } // namespace swift::gui::components
const context::IContextNetwork * getIContextNetwork() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
virtual swift::misc::simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const swift::misc::aviation::CCallsign &callsign) const =0
Aircraft for given callsign.
virtual bool updateAircraftModel(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, const swift::misc::CIdentifier &originator)=0
Change model (for remote aircraft)
virtual bool updateAircraftEnabled(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)=0
Enable/disable rendering.
virtual swift::misc::simulation::CSimulatedAircraftList getAircraftInRange() const =0
Aircraft list.
virtual swift::misc::network::CServer getConnectedServer() const =0
Server which is connected, if not connected empty default object.
virtual bool resetToModelMatchingAircraft(const swift::misc::aviation::CCallsign &callsign)=0
Reset model by matching it again.
virtual bool isKnownModelInSet(const QString &modelstring) const =0
Known model?
virtual void disableModelsForMatching(const swift::misc::simulation::CAircraftModelList &removedModels, bool incremental)=0
Remove a model for matching.
virtual swift::misc::simulation::CAircraftModelList getDisabledModelsForMatching() const =0
The disabled models for matching.
bool isSimulatorAvailable() const
Simulator avialable (driver available)?
virtual int doMatchingsAgain()=0
Repeat all matchings.
virtual swift::misc::simulation::CAircraftModelList getModelSetModelsStartingWith(const QString &modelString) const =0
Models for model string.
virtual swift::misc::simulation::CAircraftModelList getModelSet() const =0
Installed models in simulator eco system.
bool isSimulatorSimulating() const
Is available simulator simulating? Returns false if no simulator is available.
virtual ISimulator::SimulatorStatus getSimulatorStatus() const =0
Simulator combined status.
virtual void setModelSetLoaderSimulator(const swift::misc::simulation::CSimulatorInfo &simulator)=0
Set the model set loader simulator directly.
static QString replaceTabCountValue(const QString &oldName, int count)
Replace count in name such as "stations (4)".
Definition: guiutility.cpp:522
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 setForceSmall(bool force)
Force small (smaller layout)
void setReducedInfo(bool reduced)
Display reduced information.
Using this class provides a QFrame with the overlay functionality already integrated.
void requestTextMessageWidget(const swift::misc::aviation::CCallsign &callsign)
Request a text message widget.
int countAircraftModels() const
Numer of models.
int countCurrentMappings() const
Number of current mappings.
void requestValidationDialog()
Request the validation dialog.
swift::misc::simulation::CAircraftModelList findModelsStartingWith(const QString &modelName, Qt::CaseSensitivity cs)
Find models starting with.
void changed(const swift::misc::simulation::CSimulatorInfo &simulator)
Value has been changed.
Settings about view update rates.
const swift::misc::physical_quantities::CTime & getRenderingUpdateTime() const
Get time.
CheckBox for single column.
Base class with a member CIdentifier to be inherited by a class which has an identity in the environm...
Definition: identifiable.h:24
const CIdentifier & identifier() const
Get identifier.
Definition: identifiable.h:27
Value object encapsulating information identifying a component of a modular distributed swift process...
Definition: identifier.h:29
static const QString & guiComponent()
GUI components.
Definition: logcategories.h:94
static const QString & mapping()
Mapping.
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 & validationInfo(const char16_t(&format)[N])
Set the severity to info, 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.
bool contains(int index) const
Contains index?
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
reference front()
Access the first element.
Definition: sequence.h:225
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Streamable status message, e.g.
bool tryConsume(int numTokens=1, qint64 msSinceEpoch=-1)
Try to consume a number of tokens.
Definition: tokenbucket.cpp:14
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Definition: variant.h:66
Value object encapsulating information of a callsign.
Definition: callsign.h:30
const QString & asString() const
Get callsign (normalized)
Definition: callsign.h:96
QString getCallsignsAsString(const QString &separator, bool sorted=false) const
Get callsigns as strings.
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:76
Value object encapsulating information about a connection status.
bool isConnected() const
Query status.
bool isDisconnected() const
Query status.
bool sendInterimPositions() const
FSD setup flags.
Definition: fsdsetup.h:103
Value object encapsulating information of a server.
Definition: server.h:28
const CFsdSetup & getFsdSetup() const
Get FSD setup.
Definition: server.h:140
int toMs() const
Convenience functions when used with timers etc.
Definition: time.cpp:117
Aircraft model (used by another pilot, my models on disk)
Definition: aircraftmodel.h:71
Value object encapsulating a list of aircraft models.
CAircraftModelList findByModelString(const QString &modelString, Qt::CaseSensitivity sensitivity=Qt::CaseInsensitive) const
Find by model string.
bool containsModelString(const QString &modelString, Qt::CaseSensitivity sensitivity=Qt::CaseInsensitive) const
Contains model string?
Comprehensive information of an aircraft.
const aviation::CCallsign & getCallsign() const
Get callsign.
const simulation::CAircraftModel & getModel() const
Get model (model used for mapping)
bool isEnabled() const
Enabled? Enable means it shall be displayed in the simulator.
const QString & getModelString() const
Get model string.
Value object encapsulating a list of aircraft.
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
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
Filter to search data sets.
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