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);
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,
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.
void clicked(bool checked)
QAbstractItemView * popup() const const
QDateTime currentDateTimeUtc()
void setMSecsSinceEpoch(qint64 msecs)
QSize size(int flags, const QString &text, int tabStops, int *tabArray) const const
void toggled(bool on)
void returnPressed()
T & first()
bool isEmpty() const const
T & last()
void push_back(QList< T >::parameter_type value)
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
int width() const const
QString arg(Args &&... args) const const
void clear()
bool isEmpty() const const
QString toUpper() const const
QString trimmed() const const
QueuedConnection
TextSingleLine
ToolButtonTextBesideIcon
void setInterval(int msec)
void start()
void stop()
void timeout()
QFontMetrics fontMetrics() const const
QLayout * layout() const const
void setMinimumWidth(int minw)