6 #include <QAbstractItemModel>
10 #include <QModelIndex>
12 #include <QPushButton>
13 #include <QStandardItemModel>
14 #include <QStringBuilder>
21 #include "ui_atcstationcomponent.h"
44 using namespace swift::gui::settings;
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;
51 using namespace swift::core::context;
55 CAtcStationComponent::CAtcStationComponent(QWidget *parent)
59 Q_ASSERT_X(
sGui, Q_FUNC_INFO,
"Need sGui");
61 ui->tw_Atc->setCurrentIndex(0);
62 ui->tw_Atc->tabBar()->setExpanding(
false);
63 ui->tw_Atc->tabBar()->setUsesScrollButtons(
true);
65 ui->le_AtcStationsOnlineMetar->setValidator(ucv);
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);
82 ui->tvp_AtcStationsOnline->setStationMode(CAtcStationListModel::StationsOnline);
83 ui->tvp_AtcStationsOnlineTree->setColumns(ui->tvp_AtcStationsOnline->getColumns());
86 ui->tvp_AtcStationsOnline->menuRemoveItems(CAtcStationView::MenuClear);
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);
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,
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,
118 connect(ui->tb_AtcStationsAtisReload, &QPushButton::clicked,
this, &CAtcStationComponent::requestAtisUpdates);
122 connect(ui->gb_Details, &QGroupBox::toggled,
this, &CAtcStationComponent::onDetailsToggled,
123 Qt::QueuedConnection);
129 &CAtcStationComponent::changedAtcStationsOnline, Qt::QueuedConnection);
131 &CAtcStationComponent::atcStationDisconnected, Qt::QueuedConnection);
133 &CAtcStationComponent::connectionStatusChanged, Qt::QueuedConnection);
137 ui->tvp_AtcStationsOnline->acceptClickSelection(
true);
138 ui->tvp_AtcStationsOnline->acceptRowSelection(
true);
146 ui->sp_AtcSplitter->setStretchFactor(0, 3);
147 ui->sp_AtcSplitter->setStretchFactor(1, 1);
153 &CAtcStationComponent::airportsRead);
154 this->airportsRead();
158 this->settingsChanged();
165 const int t =
static_cast<int>(tab);
166 ui->tw_Atc->setCurrentIndex(t);
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;
183 using namespace std::chrono_literals;
184 if (!this->canAccessContext()) {
return; }
185 Q_ASSERT(ui->tvp_AtcStationsOnline);
192 ui->tvp_AtcStationsOnline->hideLoadIndicator();
200 if (m_timestampOnlineStationsChanged > m_timestampLastReadOnlineStations)
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);
211 if (stationsCount < 1 && allStationsCount > 0)
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);
218 if (stationsCount < 1) { m_selectedCallsign.clear(); }
219 else if (!m_selectedCallsign.isEmpty() && onlineStations.
containsCallsign(m_selectedCallsign))
225 const CCallsign currentCs(ui->le_AtcStationsOnlineMetar->text());
228 this->triggerOnlineAtcStationSelected(lastSelected);
236 m_selectedCallsign.clear();
237 ui->tvp_AtcStationsOnline->clear();
238 this->updateTreeView();
239 this->setOnlineTabs(0, 0);
243 void CAtcStationComponent::atcStationDisconnected(
const CAtcStation &station)
246 ui->tvp_AtcStationsOnline->changedAtcStationConnectionStatus(station,
false);
249 void CAtcStationComponent::getMetarAsEntered() { this->
getMetar(
""); }
253 if (!this->canAccessContext()) {
return; }
255 ui->le_AtcStationsOnlineMetar->text().trimmed().toUpper() :
256 airportIcaoCode.trimmed().toUpper());
257 ui->le_AtcStationsOnlineMetar->setText(icao.
asString());
263 ui->te_AtcStationsOnlineInfo->setText(metarText);
265 else { ui->te_AtcStationsOnlineInfo->clear(); }
268 void CAtcStationComponent::changedAtcStationsOnline()
272 m_timestampOnlineStationsChanged = QDateTime::currentDateTimeUtc();
280 ui->tvp_AtcStationsOnline->clear();
281 this->updateTreeView();
282 m_updateTimer.start();
286 m_updateTimer.stop();
287 this->clearOnlineViews();
292 void CAtcStationComponent::testCreateDummyOnlineAtcStations(
int number)
298 void CAtcStationComponent::requestOnlineStationsUpdate()
300 m_timestampLastReadOnlineStations.setMSecsSinceEpoch(0);
304 void CAtcStationComponent::infoAreaTabBarChanged(
int index)
311 const QPointer<CAtcStationComponent> myself(
this);
319 void CAtcStationComponent::setOnlineTabs(
int count,
int filtered)
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);
335 if (unit != CComSystem::Com1 && unit != CComSystem::Com2) {
return; }
336 if (!CComSystem::isValidComFrequency(frequency)) {
return; }
340 void CAtcStationComponent::settingsChanged()
342 if (!this->canAccessContext()) {
return; }
346 m_updateTimer.setInterval(ms);
349 m_timestampOnlineStationsChanged = QDateTime::currentDateTimeUtc();
350 m_updateTimer.start(ms);
353 else { m_updateTimer.stop(); }
356 void CAtcStationComponent::airportsRead() { this->initCompleters(); }
358 void CAtcStationComponent::updateTreeView()
360 ui->tvp_AtcStationsOnlineTree->updateContainer(ui->tvp_AtcStationsOnline->container());
361 ui->tvp_AtcStationsOnlineTree->fullResizeToContents();
364 void CAtcStationComponent::initCompleters()
368 if (!airports.isEmpty())
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);
377 void CAtcStationComponent::onOnlineAtcStationVariantSelected(
const CVariant &
object)
379 ui->te_AtcStationsOnlineInfo->setText(
"");
380 if (!
object.isValid() || !
object.canConvert<CAtcStation>()) {
return; }
382 this->onOnlineAtcStationSelected(station);
385 void CAtcStationComponent::triggerOnlineAtcStationSelected(
const CAtcStation &station)
388 QPointer<CAtcStationComponent> myself(
this);
390 if (myself) { myself->onOnlineAtcStationSelected(station); }
394 void CAtcStationComponent::onOnlineAtcStationSelected(
const CAtcStation &station)
397 const QString infoMessage =
402 ui->te_AtcStationsOnlineInfo->setText(infoMessage);
407 void CAtcStationComponent::requestAtisUpdates()
409 using namespace std::chrono_literals;
411 if (!this->canAccessContext()) {
return; }
413 if (ui->tw_Atc->currentIndex() == TabAtcOnline)
415 ui->tvp_AtcStationsOnline->showOverlayHTMLMessage(
"Requested ATIS update", 5s);
417 else { ui->tvp_AtcStationsOnlineTree->showOverlayHTMLMessage(
"Requested ATIS update", 5s); }
420 bool CAtcStationComponent::canAccessContext()
const
426 void CAtcStationComponent::clearOnlineViews()
428 ui->tvp_AtcStationsOnline->clear();
429 ui->tvp_AtcStationsOnlineTree->clear();
430 m_selectedCallsign.
clear();
433 void CAtcStationComponent::showOverlayInlineTextMessage()
439 void CAtcStationComponent::onDetailsToggled(
bool checked)
441 QVBoxLayout *layout = this->vLayout();
446 if (!m_splitterSizes.isEmpty()) { ui->sp_AtcSplitter->setSizes(m_splitterSizes); }
450 m_splitterSizes = ui->sp_AtcSplitter->sizes();
451 if (m_splitterSizes.size() > 1)
454 ui->sp_AtcSplitter->getRange(1, &min, &max);
456 newSizes.push_back(qMax(0, m_splitterSizes.first() + m_splitterSizes.last() - min));
457 newSizes.push_back(min);
458 ui->sp_AtcSplitter->setSizes(newSizes);
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);
471 QVBoxLayout *CAtcStationComponent::vLayout()
const
473 QVBoxLayout *layout = qobject_cast<QVBoxLayout *>(this->layout());
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
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.
void changedInfoAreaTabBarIndex(int index)
Tab bar changed.
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 ~CAtcStationComponent()
Destructor.
virtual bool setParentDockWidgetInfoArea(swift::gui::CDockWidgetInfoArea *parentDockableWidget)
Corresponding dockable widget in info area.
void setTab(AtcTab tab)
Set tab.
void update()
Update stations.
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.
Base class with a member CIdentifier to be inherited by a class which has an identity in the environm...
const CIdentifier & identifier() const
Get identifier.
int sizeInt() const
Avoid compiler warnings when using with int.
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
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.
Value object encapsulating information about an ATC station.
const CCallsign & getCallsign() const
Get callsign.
bool hasAtis() const
Has ATIS?
const CInformationMessage & getMetar() const
Get METAR.
QString getCallsignAsString() const
Get callsign as string.
const CInformationMessage & getAtis() const
Get ATIS.
const physical_quantities::CFrequency & getFrequency() const
Get frequency.
bool hasMetar() const
Has METAR?
bool hasCallsign() const
Has callsign?
Value object for a list of ATC stations.
Value object encapsulating information of a callsign.
void clear()
Clear this callsign.
const QString & asString() const
Get callsign (normalized)
bool isEmpty() const
Is empty?
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.
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.
High level reusable GUI components.
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...