swift
atcstationcomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QAbstractItemModel>
7 #include <QCompleter>
8 #include <QGroupBox>
9 #include <QLineEdit>
10 #include <QModelIndex>
11 #include <QPointer>
12 #include <QPushButton>
13 #include <QStandardItemModel>
14 #include <QStringBuilder>
15 #include <QTabBar>
16 #include <QTableView>
17 #include <QTextEdit>
18 #include <QTimer>
19 #include <QTreeView>
20 
21 #include "ui_atcstationcomponent.h"
22 
25 #include "core/webdataservices.h"
26 #include "gui/dockwidgetinfoarea.h"
27 #include "gui/guiapplication.h"
28 #include "gui/guiutility.h"
29 #include "gui/infoarea.h"
32 #include "gui/uppercasevalidator.h"
34 #include "gui/views/viewbase.h"
37 #include "misc/icons.h"
38 #include "misc/logmessage.h"
40 #include "misc/weather/metar.h"
41 
42 using namespace swift::gui::models;
43 using namespace swift::gui::views;
44 using namespace swift::gui::settings;
45 using namespace swift::misc;
46 using namespace swift::misc::aviation;
47 using namespace swift::misc::network;
48 using namespace swift::misc::physical_quantities;
49 using namespace swift::misc::weather;
50 using namespace swift::core;
51 using namespace swift::core::context;
52 
53 namespace swift::gui::components
54 {
55  CAtcStationComponent::CAtcStationComponent(QWidget *parent)
57  ui(new Ui::CAtcStationComponent)
58  {
59  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Need sGui");
60  ui->setupUi(this);
61  ui->tw_Atc->setCurrentIndex(0);
62  ui->tw_Atc->tabBar()->setExpanding(false);
63  ui->tw_Atc->tabBar()->setUsesScrollButtons(true);
64  CUpperCaseValidator *ucv = new CUpperCaseValidator(ui->le_AtcStationsOnlineMetar);
65  ui->le_AtcStationsOnlineMetar->setValidator(ucv);
66 
67  // some icons
68  ui->tb_AtcStationsAtisReload->setIcon(CIcons::atis());
69  ui->tb_AtcStationsAtisReload->setText("ATIS");
70  ui->tb_AtcStationsAtisReload->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
71  ui->tb_AtcStationsLoadMetar->setIcon(CIcons::metar());
72  ui->tb_AtcStationsLoadMetar->setText("METAR");
73  ui->tb_AtcStationsLoadMetar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
74  ui->tb_Audio->setIcon(CIcons::appAudio16());
75  ui->tb_Audio->setText("Audio");
76  ui->tb_Audio->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
77  ui->tb_TextMessageOverlay->setIcon(CIcons::appTextMessages16());
78  ui->tb_TextMessageOverlay->setText("Text");
79  ui->tb_TextMessageOverlay->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
80 
81  // set station mode
82  ui->tvp_AtcStationsOnline->setStationMode(CAtcStationListModel::StationsOnline);
83  ui->tvp_AtcStationsOnlineTree->setColumns(ui->tvp_AtcStationsOnline->getColumns());
84 
85  // menus
86  ui->tvp_AtcStationsOnline->menuRemoveItems(CAtcStationView::MenuClear);
87 
88  // Signal / Slots
89  connect(ui->le_AtcStationsOnlineMetar, &QLineEdit::returnPressed, this,
90  &CAtcStationComponent::getMetarAsEntered);
91  connect(ui->tb_AtcStationsLoadMetar, &QPushButton::clicked, this, &CAtcStationComponent::getMetarAsEntered);
92  connect(ui->tb_Audio, &QPushButton::clicked, this, &CAtcStationComponent::requestAudioWidget);
93  connect(ui->tb_TextMessageOverlay, &QPushButton::clicked, this,
94  &CAtcStationComponent::showOverlayInlineTextMessage);
95 
96  connect(ui->tvp_AtcStationsOnline, &CAtcStationView::objectClicked, this,
97  &CAtcStationComponent::onOnlineAtcStationVariantSelected, Qt::QueuedConnection);
98  connect(ui->tvp_AtcStationsOnline, &CAtcStationView::objectSelected, this,
99  &CAtcStationComponent::onOnlineAtcStationVariantSelected, Qt::QueuedConnection);
100  connect(ui->tvp_AtcStationsOnline, &CAtcStationView::testRequestDummyAtcOnlineStations, this,
101  &CAtcStationComponent::testCreateDummyOnlineAtcStations);
102  connect(ui->tvp_AtcStationsOnline, &CAtcStationView::requestUpdate, this,
103  &CAtcStationComponent::requestOnlineStationsUpdate);
104  connect(ui->tvp_AtcStationsOnline, &CAtcStationView::requestNewBackendData, this,
105  &CAtcStationComponent::requestOnlineStationsUpdate);
106  connect(ui->tvp_AtcStationsOnline, &CAtcStationView::requestComFrequency, this,
107  &CAtcStationComponent::setComFrequency);
108  connect(ui->tvp_AtcStationsOnline, &CAtcStationView::requestTextMessageWidget, this,
110 
111  connect(ui->tvp_AtcStationsOnlineTree, &CAtcStationTreeView::requestComFrequency, this,
112  &CAtcStationComponent::setComFrequency);
113  connect(ui->tvp_AtcStationsOnlineTree, &CAtcStationTreeView::objectSelected, this,
114  &CAtcStationComponent::onOnlineAtcStationSelected, Qt::QueuedConnection);
115  connect(ui->tvp_AtcStationsOnlineTree, &CAtcStationTreeView::requestTextMessageWidget, this,
117 
118  connect(ui->tb_AtcStationsAtisReload, &QPushButton::clicked, this, &CAtcStationComponent::requestAtisUpdates);
119  connect(&m_updateTimer, &QTimer::timeout, this, &CAtcStationComponent::update);
120 
121  // Group box
122  connect(ui->gb_Details, &QGroupBox::toggled, this, &CAtcStationComponent::onDetailsToggled,
123  Qt::QueuedConnection);
124 
125  // runtime based connects
126  if (sGui)
127  {
128  connect(sGui->getIContextNetwork(), &IContextNetwork::changedAtcStationsOnlineDigest, this,
129  &CAtcStationComponent::changedAtcStationsOnline, Qt::QueuedConnection);
130  connect(sGui->getIContextNetwork(), &IContextNetwork::atcStationDisconnected, this,
131  &CAtcStationComponent::atcStationDisconnected, Qt::QueuedConnection);
132  connect(sGui->getIContextNetwork(), &IContextNetwork::connectionStatusChanged, this,
133  &CAtcStationComponent::connectionStatusChanged, Qt::QueuedConnection);
134  }
135 
136  // selection
137  ui->tvp_AtcStationsOnline->acceptClickSelection(true);
138  ui->tvp_AtcStationsOnline->acceptRowSelection(true);
139 
140  // before splitter
141  // QVBoxLayout *layout = this->vLayout();
142  // m_stretch.push_back(layout->stretch(0));
143  // m_stretch.push_back(layout->stretch(1));
144 
145  // no effect
146  ui->sp_AtcSplitter->setStretchFactor(0, 3);
147  ui->sp_AtcSplitter->setStretchFactor(1, 1);
148 
149  // web readers
150  if (sGui && sGui->hasWebDataServices())
151  {
152  connect(sGui->getWebDataServices(), &CWebDataServices::swiftDbAirportsRead, this,
153  &CAtcStationComponent::airportsRead);
154  this->airportsRead();
155  }
156 
157  // init settings
158  this->settingsChanged();
159  }
160 
162 
164  {
165  const int t = static_cast<int>(tab);
166  ui->tw_Atc->setCurrentIndex(t);
167  }
168 
169  int CAtcStationComponent::countOnlineStations() const { return ui->tvp_AtcStationsOnline->rowCount(); }
170 
172  {
174  const bool c = connect(this->getParentInfoArea(), &CInfoArea::changedInfoAreaTabBarIndex, this,
175  &CAtcStationComponent::infoAreaTabBarChanged, Qt::QueuedConnection);
176  Q_ASSERT_X(c, Q_FUNC_INFO, "failed connect");
177  Q_ASSERT_X(parentDockableWidget, Q_FUNC_INFO, "missing parent");
178  return c && parentDockableWidget;
179  }
180 
182  {
183  using namespace std::chrono_literals;
184  if (!this->canAccessContext()) { return; }
185  Q_ASSERT(ui->tvp_AtcStationsOnline);
186 
187  // check if component is visible, if we have already data then skip udpate
188  const bool hasData = this->countOnlineStations() > 0;
189  if (hasData && !this->isVisibleWidget())
190  {
191  // Update skipped, as not visible
192  ui->tvp_AtcStationsOnline->hideLoadIndicator();
193  return;
194  }
195 
196  // online stations, only when connected
198  {
199  // update
200  if (m_timestampOnlineStationsChanged > m_timestampLastReadOnlineStations)
201  {
202  CAtcStationList onlineStations = sGui->getIContextNetwork()->getAtcStationsOnline(true);
203  const int allStationsCount = onlineStations.sizeInt();
204  const int stationsCount = onlineStations.sizeInt();
205  ui->tvp_AtcStationsOnline->updateContainerMaybeAsync(onlineStations);
206  m_timestampLastReadOnlineStations = QDateTime::currentDateTimeUtc();
207  m_timestampOnlineStationsChanged = m_timestampLastReadOnlineStations;
208  this->updateTreeView();
209  this->setOnlineTabs(allStationsCount, stationsCount);
210 
211  if (stationsCount < 1 && allStationsCount > 0)
212  {
213  const QString msg = QStringLiteral("All %1 ATC stations are filtered").arg(allStationsCount);
214  ui->tvp_AtcStationsOnline->showOverlayHTMLMessage(msg, 5s);
215  ui->tvp_AtcStationsOnlineTree->showOverlayHTMLMessage(msg, 5s);
216  }
217 
218  if (stationsCount < 1) { m_selectedCallsign.clear(); }
219  else if (!m_selectedCallsign.isEmpty() && onlineStations.containsCallsign(m_selectedCallsign))
220  {
221  const CAtcStation lastSelected = onlineStations.findFirstByCallsign(m_selectedCallsign);
222  if (lastSelected.hasCallsign())
223  {
224  // avoid override of manually entered METAR callsigns
225  const CCallsign currentCs(ui->le_AtcStationsOnlineMetar->text());
226  if (currentCs.isEmpty() || currentCs == lastSelected.getCallsign())
227  {
228  this->triggerOnlineAtcStationSelected(lastSelected);
229  }
230  }
231  } // stations
232  }
233  }
234  else
235  {
236  m_selectedCallsign.clear();
237  ui->tvp_AtcStationsOnline->clear();
238  this->updateTreeView();
239  this->setOnlineTabs(0, 0);
240  }
241  }
242 
243  void CAtcStationComponent::atcStationDisconnected(const CAtcStation &station)
244  {
245  // trick here is, we want to display a station ASAP
246  ui->tvp_AtcStationsOnline->changedAtcStationConnectionStatus(station, false);
247  }
248 
249  void CAtcStationComponent::getMetarAsEntered() { this->getMetar(""); }
250 
251  void CAtcStationComponent::getMetar(const QString &airportIcaoCode)
252  {
253  if (!this->canAccessContext()) { return; }
254  const CAirportIcaoCode icao(airportIcaoCode.isEmpty() ?
255  ui->le_AtcStationsOnlineMetar->text().trimmed().toUpper() :
256  airportIcaoCode.trimmed().toUpper());
257  ui->le_AtcStationsOnlineMetar->setText(icao.asString());
258  if (!icao.hasValidIcaoCode(true)) { return; }
259  const CMetar metar(sGui->getIContextNetwork()->getMetarForAirport(icao));
260  if (metar.hasMessage())
261  {
262  const QString metarText = metar.getMessage() % u"\n\n" % metar.getMetarText();
263  ui->te_AtcStationsOnlineInfo->setText(metarText);
264  }
265  else { ui->te_AtcStationsOnlineInfo->clear(); }
266  }
267 
268  void CAtcStationComponent::changedAtcStationsOnline()
269  {
270  // just update timestamp, data will be pulled by timer
271  // the timestamp will tell if there are any newer data
272  m_timestampOnlineStationsChanged = QDateTime::currentDateTimeUtc();
273  }
274 
275  void CAtcStationComponent::connectionStatusChanged(const CConnectionStatus &from, const CConnectionStatus &to)
276  {
277  Q_UNUSED(from)
278  if (to.isConnected())
279  {
280  ui->tvp_AtcStationsOnline->clear();
281  this->updateTreeView();
282  m_updateTimer.start();
283  }
284  else if (to.isDisconnected())
285  {
286  m_updateTimer.stop();
287  this->clearOnlineViews();
288  this->update();
289  }
290  }
291 
292  void CAtcStationComponent::testCreateDummyOnlineAtcStations(int number)
293  {
294  if (!sGui || !sGui->getIContextNetwork()) { return; }
295  if (this->canAccessContext()) { sGui->getIContextNetwork()->testCreateDummyOnlineAtcStations(number); }
296  }
297 
298  void CAtcStationComponent::requestOnlineStationsUpdate()
299  {
300  m_timestampLastReadOnlineStations.setMSecsSinceEpoch(0); // mark as outdated
301  this->update();
302  }
303 
304  void CAtcStationComponent::infoAreaTabBarChanged(int index)
305  {
306  // ignore in those cases
307  if (!this->isVisibleWidget()) { return; }
308  if (this->isParentDockWidgetFloating()) { return; }
309 
310  // here I know I am the selected widget, update, but keep GUI responsive (-> timer)
311  const QPointer<CAtcStationComponent> myself(this);
312  QTimer::singleShot(1000, this, [=] {
313  if (!sApp || sApp->isShuttingDown() || !myself) { return; }
314  this->update();
315  });
316  Q_UNUSED(index)
317  }
318 
319  void CAtcStationComponent::setOnlineTabs(int count, int filtered)
320  {
321  const int io = ui->tw_Atc->indexOf(ui->tb_AtcStationsOnline);
322  const int it = ui->tw_Atc->indexOf(ui->tb_AtcStationsOnlineTree);
323  static const QString o = ui->tw_Atc->tabBar()->tabText(io);
324  static const QString t = ui->tw_Atc->tabBar()->tabText(it);
325  const bool isFiltered = filtered < count && filtered >= 0;
326  const QString filteredInfo =
327  isFiltered ? QStringLiteral(" (%1 of %2)").arg(filtered).arg(count) : QStringLiteral(" (%1)").arg(count);
328  ui->tw_Atc->tabBar()->setTabText(io, o % filteredInfo);
329  ui->tw_Atc->tabBar()->setTabText(it, t % filteredInfo);
330  }
331 
332  void CAtcStationComponent::setComFrequency(const physical_quantities::CFrequency &frequency,
333  CComSystem::ComUnit unit)
334  {
335  if (unit != CComSystem::Com1 && unit != CComSystem::Com2) { return; }
336  if (!CComSystem::isValidComFrequency(frequency)) { return; }
338  }
339 
340  void CAtcStationComponent::settingsChanged()
341  {
342  if (!this->canAccessContext()) { return; }
343  const CViewUpdateSettings settings = m_settingsView.get();
344  const int ms = settings.getAtcUpdateTime().toMs();
345  const bool connected = sGui->getIContextNetwork()->isConnected();
346  m_updateTimer.setInterval(ms);
347  if (connected)
348  {
349  m_timestampOnlineStationsChanged = QDateTime::currentDateTimeUtc();
350  m_updateTimer.start(ms); // restart
351  this->update();
352  }
353  else { m_updateTimer.stop(); }
354  }
355 
356  void CAtcStationComponent::airportsRead() { this->initCompleters(); }
357 
358  void CAtcStationComponent::updateTreeView()
359  {
360  ui->tvp_AtcStationsOnlineTree->updateContainer(ui->tvp_AtcStationsOnline->container());
361  ui->tvp_AtcStationsOnlineTree->fullResizeToContents();
362  }
363 
364  void CAtcStationComponent::initCompleters()
365  {
366  if (!sGui || !sGui->getWebDataServices()) { return; }
367  const QStringList airports = sGui->getWebDataServices()->getAirports().allIcaoCodes(true);
368  if (!airports.isEmpty())
369  {
370  QCompleter *airportCompleter = new QCompleter(airports, this);
371  const int w5chars = airportCompleter->popup()->fontMetrics().size(Qt::TextSingleLine, "FooBa").width();
372  airportCompleter->popup()->setMinimumWidth(w5chars * 5);
373  ui->le_AtcStationsOnlineMetar->setCompleter(airportCompleter);
374  }
375  }
376 
377  void CAtcStationComponent::onOnlineAtcStationVariantSelected(const CVariant &object)
378  {
379  ui->te_AtcStationsOnlineInfo->setText(""); // reset
380  if (!object.isValid() || !object.canConvert<CAtcStation>()) { return; }
381  const CAtcStation station = object.valueOrDefault(CAtcStation());
382  this->onOnlineAtcStationSelected(station);
383  }
384 
385  void CAtcStationComponent::triggerOnlineAtcStationSelected(const CAtcStation &station)
386  {
387  // pass copy, not reference -> can crash
388  QPointer<CAtcStationComponent> myself(this);
389  QTimer::singleShot(500, this, [=] {
390  if (myself) { myself->onOnlineAtcStationSelected(station); }
391  });
392  }
393 
394  void CAtcStationComponent::onOnlineAtcStationSelected(const CAtcStation &station)
395  {
396  if (!station.hasCallsign()) { return; }
397  const QString infoMessage =
398  station.getCallsignAsString() % u": " %
399  station.getFrequency().valueRoundedWithUnit(CFrequencyUnit::MHz(), 3) %
400  (station.hasAtis() ? u"\n\n" % station.getAtis().getMessage() : QStringLiteral("")) %
401  (station.hasMetar() ? u"\n\n" % station.getMetar().getMessage() : QStringLiteral(""));
402  ui->te_AtcStationsOnlineInfo->setText(infoMessage);
403  ui->le_AtcStationsOnlineMetar->setText(station.getCallsign().asString());
404  m_selectedCallsign = station.getCallsign();
405  }
406 
407  void CAtcStationComponent::requestAtisUpdates()
408  {
409  using namespace std::chrono_literals;
410 
411  if (!this->canAccessContext()) { return; }
413  if (ui->tw_Atc->currentIndex() == TabAtcOnline)
414  {
415  ui->tvp_AtcStationsOnline->showOverlayHTMLMessage("Requested ATIS update", 5s);
416  }
417  else { ui->tvp_AtcStationsOnlineTree->showOverlayHTMLMessage("Requested ATIS update", 5s); }
418  }
419 
420  bool CAtcStationComponent::canAccessContext() const
421  {
422  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextNetwork()) { return false; }
423  return true;
424  }
425 
426  void CAtcStationComponent::clearOnlineViews()
427  {
428  ui->tvp_AtcStationsOnline->clear();
429  ui->tvp_AtcStationsOnlineTree->clear();
430  m_selectedCallsign.clear();
431  }
432 
433  void CAtcStationComponent::showOverlayInlineTextMessage()
434  {
435  // COverlayMessagesFrame::showOverlayInlineTextMessage(TextMessagesCom1);
436  emit requestTextMessageEntryTab(TextMessagesCom1);
437  }
438 
439  void CAtcStationComponent::onDetailsToggled(bool checked)
440  {
441  QVBoxLayout *layout = this->vLayout();
442  if (layout)
443  {
444  if (checked)
445  {
446  if (!m_splitterSizes.isEmpty()) { ui->sp_AtcSplitter->setSizes(m_splitterSizes); }
447  }
448  else
449  {
450  m_splitterSizes = ui->sp_AtcSplitter->sizes();
451  if (m_splitterSizes.size() > 1)
452  {
453  int min, max;
454  ui->sp_AtcSplitter->getRange(1, &min, &max);
455  QList<int> newSizes;
456  newSizes.push_back(qMax(0, m_splitterSizes.first() + m_splitterSizes.last() - min));
457  newSizes.push_back(min);
458  ui->sp_AtcSplitter->setSizes(newSizes);
459  }
460  }
461  }
462 
463  ui->te_AtcStationsOnlineInfo->setVisible(checked);
464  ui->le_AtcStationsOnlineMetar->setVisible(checked);
465  ui->tb_AtcStationsAtisReload->setVisible(checked);
466  ui->tb_AtcStationsLoadMetar->setVisible(checked);
467  ui->tb_TextMessageOverlay->setVisible(checked);
468  ui->tb_Audio->setVisible(checked);
469  }
470 
471  QVBoxLayout *CAtcStationComponent::vLayout() const
472  {
473  QVBoxLayout *layout = qobject_cast<QVBoxLayout *>(this->layout());
474  return layout;
475  }
476 } // namespace swift::gui::components
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
const context::IContextOwnAircraft * getIContextOwnAircraft() const
Direct access to contexts if a CCoreFacade has been initialized.
bool hasWebDataServices() const
Web data services available?
const context::IContextNetwork * getIContextNetwork() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isShuttingDown() const
Is application shutting down?
CWebDataServices * getWebDataServices() const
Get the web data services.
swift::misc::aviation::CAirportList getAirports() const
Get airports.
virtual void testCreateDummyOnlineAtcStations(int number)=0
Create dummy ATC stations for performance tests etc.
virtual void requestAtisUpdates()=0
Request ATIS updates (for all stations)
virtual swift::misc::weather::CMetar getMetarForAirport(const swift::misc::aviation::CAirportIcaoCode &airportIcaoCode) const =0
Get METAR, if not available request it (code such as EDDF, KLAX)
virtual swift::misc::aviation::CAtcStationList getAtcStationsOnline(bool recalculateDistance) const =0
The ATC list with online ATC controllers.
virtual bool isConnected() const =0
Network connected?
virtual bool updateActiveComFrequency(const swift::misc::physical_quantities::CFrequency &frequency, swift::misc::aviation::CComSystem::ComUnit comUnit, const swift::misc::CIdentifier &originator)=0
Tune in a COM frequency.
Specialized class for dock widgets serving as info area.
CInfoArea * getParentInfoArea() const
The parent info area.
bool isParentDockWidgetFloating() const
Is the parent dockable widget floating?
virtual bool setParentDockWidgetInfoArea(CDockWidgetInfoArea *parentDockableWidget)
Corresponding dockable widget in info area.
void changedInfoAreaTabBarIndex(int index)
Tab bar changed.
Using this class provides a QFrame with the overlay and dock widget functionality already integrated.
void requestTextMessageWidget(const swift::misc::aviation::CCallsign &callsign)
Request a text message widget.
void requestTextMessageEntryTab(components::TextMessageTab tab)
Request an text message entry.
int countOnlineStations() const
Number of online stations.
void getMetar(const QString &airportIcaoCode)
Get METAR for given ICAO airport code.
virtual bool setParentDockWidgetInfoArea(swift::gui::CDockWidgetInfoArea *parentDockableWidget)
Corresponding dockable widget in info area.
void requestAudioWidget()
Request audio widget.
Settings about view update rates.
const swift::misc::physical_quantities::CTime & getAtcUpdateTime() const
Get time.
T get() const
Get a copy of the current value.
Definition: valuecache.h:408
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
int sizeInt() const
Avoid compiler warnings when using with int.
Definition: sequence.h:276
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Definition: variant.h:66
Value object encapsulating information of airport ICAO data.
bool hasValidIcaoCode(bool strict) const
Has valid code?
const QString & asString() const
Get code.
QStringList allIcaoCodes(bool sorted) const
All ICAO codes.
Definition: airportlist.cpp:63
Value object encapsulating information about an ATC station.
Definition: atcstation.h:38
const CCallsign & getCallsign() const
Get callsign.
Definition: atcstation.h:84
bool hasAtis() const
Has ATIS?
Definition: atcstation.h:78
const CInformationMessage & getMetar() const
Get METAR.
Definition: atcstation.h:187
QString getCallsignAsString() const
Get callsign as string.
Definition: atcstation.h:90
const CInformationMessage & getAtis() const
Get ATIS.
Definition: atcstation.h:178
const physical_quantities::CFrequency & getFrequency() const
Get frequency.
Definition: atcstation.h:135
bool hasMetar() const
Has METAR?
Definition: atcstation.cpp:46
bool hasCallsign() const
Has callsign?
Definition: atcstation.h:87
Value object for a list of ATC stations.
Value object encapsulating information of a callsign.
Definition: callsign.h:30
void clear()
Clear this callsign.
Definition: callsign.cpp:45
const QString & asString() const
Get callsign (normalized)
Definition: callsign.h:96
bool isEmpty() const
Is empty?
Definition: callsign.h:63
const QString & getMessage() const
Get message.
OBJ findFirstByCallsign(const CCallsign &callsign, const OBJ &ifNotFound={}) const
Find the first aircraft by callsign, if none return given one.
bool containsCallsign(const CCallsign &callsign) const
Contains callsign?
Value object encapsulating information about a connection status.
bool isConnected() const
Query status.
bool isDisconnected() const
Query status.
QString valueRoundedWithUnit(const MU &unit, int digits=-1, bool withGroupSeparator=false, bool i18n=false) const
Value to QString with the given unit, e.g. "5.00m".
int toMs() const
Convenience functions when used with timers etc.
Definition: time.cpp:117
Value object encapsulating information about METAR FIXME: runway visibilities FIXME: runway wind shea...
Definition: metar.h:38
QString getMetarText() const
Returns the METAR in a descriptive text.
Definition: metar.cpp:65
bool hasMessage() const
Has METAR message.
Definition: metar.cpp:23
const QString & getMessage() const
Get METAR message.
Definition: metar.h:54
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
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