diff --git a/src/blackcore/context/contextnetworkimpl.h b/src/blackcore/context/contextnetworkimpl.h index 2c71c2a7c..eebe92334 100644 --- a/src/blackcore/context/contextnetworkimpl.h +++ b/src/blackcore/context/contextnetworkimpl.h @@ -124,6 +124,23 @@ namespace BlackCore virtual bool setClientGndCapability(const BlackMisc::Aviation::CCallsign &callsign, bool supportGndFlag) override; //! @} + //! \copydoc IContextNetwork::connectRawFsdMessageSignal + virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot) override; + + //! Gracefully shut down, e.g. for thread safety + void gracefulShutdown(); + + //! \protected + //! \remarks normally only for core facade internal usage + //! \remarks public so values can be logged/monitored + //! @{ + //! Network library + INetwork *network() const { return m_network; } + + //! Airspace + CAirspaceMonitor *airspace() const { return m_airspace; } + //! @} + public slots: // from context and provider interface //! \ingroup remoteaircraftprovider @@ -222,13 +239,6 @@ namespace BlackCore //! @} // --------------------- IContextNetwork implementations --------------------- - //! Gracefully shut down, e.g. for thread safety - void gracefulShutdown(); - - public: - //! \copydoc IContextNetwork::connectRawFsdMessageSignal - virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot) override; - protected: //! Constructor, with link to runtime CContextNetwork(CCoreFacadeConfig::ContextMode, CCoreFacade *runtime); @@ -236,14 +246,6 @@ namespace BlackCore //! Register myself in DBus CContextNetwork *registerWithDBus(BlackMisc::CDBusServer *server); - //! Network library - //! \remarks normally only for core facade internal usage - INetwork *network() const { return m_network; } - - //! Airspace - //! \remarks normally only for core facade internal usage - CAirspaceMonitor *airspace() const { return m_airspace; } - //! Set the provider void setSimulationEnvironmentProvider(BlackMisc::Simulation::ISimulationEnvironmentProvider *provider); diff --git a/src/blackgui/components/interpolationlogdisplay.cpp b/src/blackgui/components/interpolationlogdisplay.cpp index 27fa31505..b4cf28eba 100644 --- a/src/blackgui/components/interpolationlogdisplay.cpp +++ b/src/blackgui/components/interpolationlogdisplay.cpp @@ -9,11 +9,20 @@ #include "interpolationlogdisplay.h" #include "ui_interpolationlogdisplay.h" +#include "blackgui/guiapplication.h" +#include "blackcore/context/contextnetworkimpl.h" +#include "blackcore/airspacemonitor.h" #include "blackmisc/simulation/interpolationlogger.h" +#include "blackmisc/stringutils.h" using namespace BlackCore; +using namespace BlackCore::Context; +using namespace BlackMisc; using namespace BlackMisc::Aviation; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; using namespace BlackMisc::Simulation; +using namespace BlackMisc::PhysicalQuantities; namespace BlackGui { @@ -24,6 +33,7 @@ namespace BlackGui ui(new Ui::CInterpolationLogDisplay) { ui->setupUi(this); + ui->tw_LogTabs->setCurrentIndex(TabFlow); constexpr int timeSecs = 5; ui->hs_UpdateTime->setValue(timeSecs); this->onSliderChanged(timeSecs); @@ -32,6 +42,12 @@ namespace BlackGui connect(ui->pb_StartStop, &QPushButton::released, this, &CInterpolationLogDisplay::toggleStartStop); connect(ui->comp_CallsignCompleter, &CCallsignCompleter::validCallsignEntered, this, &CInterpolationLogDisplay::onCallsignEntered); + CLedWidget::LedShape shape = CLedWidget::Rounded; + ui->led_Parts->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "Parts received", "", 14); + ui->led_Situation->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "Situation received", "", 14); + ui->led_Elevation->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "Elevation received", "", 14); + ui->led_Running->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "Running", "Stopped", 14); + m_callsign = ui->comp_CallsignCompleter->getCallsign(); } @@ -40,21 +56,59 @@ namespace BlackGui void CInterpolationLogDisplay::setSimulator(CSimulatorCommon *simulatorCommon) { + if (simulatorCommon && simulatorCommon == m_simulatorCommon) { return; } // same + if (m_simulatorCommon) + { + this->disconnect(m_simulatorCommon); + m_simulatorCommon->disconnect(this); + } m_simulatorCommon = simulatorCommon; + connect(m_simulatorCommon, &CSimulatorCommon::receivedRequestedElevation, this, &CInterpolationLogDisplay::onElevationReceived); + connect(m_simulatorCommon, &CSimulatorCommon::requestedElevation, this, &CInterpolationLogDisplay::onElevationRequested); + } + + void CInterpolationLogDisplay::setAirspaceMonitor(CAirspaceMonitor *airspaceMonitor) + { + if (airspaceMonitor && airspaceMonitor == m_airspaceMonitor) { return; } // same + if (m_airspaceMonitor) + { + this->disconnect(m_airspaceMonitor); + m_airspaceMonitor->disconnect(this); + } + m_airspaceMonitor = airspaceMonitor; + + connect(m_airspaceMonitor, &CAirspaceMonitor::addedAircraftSituation, this, &CInterpolationLogDisplay::onSituationAdded, Qt::QueuedConnection); + connect(m_airspaceMonitor, &CAirspaceMonitor::addedAircraftParts, this, &CInterpolationLogDisplay::onPartsAdded, Qt::QueuedConnection); } void CInterpolationLogDisplay::updateLog() { - const bool hasLogger = m_simulatorCommon; - if (hasLogger && !m_callsign.isEmpty()) + if (!sGui || sGui->isShuttingDown()) { return; } + const bool hasLogger = m_simulatorCommon && m_airspaceMonitor; + if (!hasLogger || m_callsign.isEmpty()) + { + ui->te_TextLog->setText("No logger attached or no callsign"); + this->stop(); + this->clear(); + } + + // only display visible tab + if (ui->tw_LogTabs->currentWidget() == ui->tb_TextLog) { const QString log = m_simulatorCommon->latestLoggedDataFormatted(m_callsign); - ui->te_Log->setText(log); + ui->te_TextLog->setText(log); } - else + else if (ui->tw_LogTabs->currentWidget() == ui->tb_DataFlow) { - ui->te_Log->setText("No logger attached or no callsign"); - this->stop(); + ui->le_CG->setText(m_airspaceMonitor->getCG(m_callsign).valueRoundedWithUnit(CLengthUnit::ft(), 1)); + ui->le_CG->home(false); + ui->le_Parts->setText(boolToYesNo(m_airspaceMonitor->isRemoteAircraftSupportingParts(m_callsign))); + + static const QString avgUpdateTime("%1ms"); + ui->le_AvgUpdateTimeMs->setText(avgUpdateTime.arg(m_simulatorCommon->getStatisticsAverageUpdateTimeMs())); + + const CClient client = m_airspaceMonitor->getClientOrDefaultForCallsign(m_callsign); + ui->le_GndFlag->setText(boolToYesNo(client.hasGndFlagCapability())); } } @@ -73,12 +127,14 @@ namespace BlackGui this->stop(); return; } + if (m_callsign == cs) { return; } // clear last callsign if (!m_callsign.isEmpty()) { m_simulatorCommon->setLogInterpolation(false, m_callsign); // stop logging "old" callsign m_callsign = CCallsign(); // clear callsign + this->clear(); } // set new callsign or stop @@ -95,14 +151,8 @@ namespace BlackGui void CInterpolationLogDisplay::toggleStartStop() { const bool running = m_updateTimer.isActive(); - if (running) - { - this->stop(); - } - else - { - this->start(); - } + if (running) { this->stop(); } + else { this->start(); } } void CInterpolationLogDisplay::start() @@ -110,12 +160,79 @@ namespace BlackGui const int interval = ui->hs_UpdateTime->value() * 1000; m_updateTimer.start(interval); ui->pb_StartStop->setText(stopText()); + ui->led_Running->setOn(true); } void CInterpolationLogDisplay::stop() { m_updateTimer.stop(); ui->pb_StartStop->setText(startText()); + ui->led_Running->setOn(false); + } + + bool CInterpolationLogDisplay::logCallsign(const CCallsign &cs) const + { + if (!sGui || sGui->isShuttingDown()) { return false; } + if (!m_airspaceMonitor || !m_simulatorCommon || m_callsign.isEmpty()) { return false; } + if (cs != m_callsign) { return false; } + return true; + } + + void CInterpolationLogDisplay::onSituationAdded(const CAircraftSituation &situation) + { + const CCallsign cs = situation.getCallsign(); + if (!this->logCallsign(cs)) { return; } + const CAircraftSituationList situations = m_airspaceMonitor->remoteAircraftSituations(cs); + ui->tvp_AircraftSituations->updateContainerAsync(situations); + ui->led_Situation->blink(); + } + + void CInterpolationLogDisplay::onPartsAdded(const CCallsign &callsign, const CAircraftParts &parts) + { + if (!this->logCallsign(callsign)) { return; } + Q_UNUSED(parts); + const CAircraftPartsList partsList = m_airspaceMonitor->remoteAircraftParts(callsign); + ui->tvp_AircraftParts->updateContainerAsync(partsList); + ui->led_Parts->blink(); + } + + void CInterpolationLogDisplay::onElevationReceived(const CElevationPlane &plane, const CCallsign &callsign) + { + if (!this->logCallsign(callsign)) { return; } + m_elvReceived++; + ui->le_Elevation->setText(plane.toQString()); + ui->led_Elevation->blink(); + ui->le_ElevationRec->setText(QString::number(m_elvReceived)); + } + + void CInterpolationLogDisplay::onElevationRequested(const CCallsign &callsign) + { + if (!this->logCallsign(callsign)) { return; } + m_elvRequested++; + ui->led_Elevation->blink(); + ui->le_ElevationReq->setText(QString::number(m_elvRequested)); + } + + void CInterpolationLogDisplay::clear() + { + ui->tvp_AircraftParts->clear(); + ui->tvp_AircraftSituations->clear(); + ui->te_TextLog->clear(); + ui->le_CG->clear(); + ui->le_Elevation->clear(); + ui->le_ElevationRec->clear(); + ui->le_ElevationReq->clear(); + ui->le_Parts->clear(); + ui->le_AvgUpdateTimeMs->clear(); + m_elvReceived = m_elvRequested = 0; + } + + void CInterpolationLogDisplay::linkWithAirspaceMonitor() + { + if (!sGui || sGui->isShuttingDown() || !sGui->supportsContexts()) { return; } + if (!sGui->getCoreFacade() || !sGui->getCoreFacade()->getCContextNetwork()) { return; } + const CContextNetwork *cn = sGui->getCoreFacade()->getCContextNetwork(); + this->setAirspaceMonitor(cn->airspace()); } const QString &CInterpolationLogDisplay::startText() diff --git a/src/blackgui/components/interpolationlogdisplay.h b/src/blackgui/components/interpolationlogdisplay.h index 11aa700d1..bce85def5 100644 --- a/src/blackgui/components/interpolationlogdisplay.h +++ b/src/blackgui/components/interpolationlogdisplay.h @@ -20,6 +20,7 @@ #include #include +namespace BlackCore { class CAirspaceMonitor; } namespace Ui { class CInterpolationLogDisplay; } namespace BlackGui { @@ -33,6 +34,13 @@ namespace BlackGui Q_OBJECT public: + //! Tabs + enum Tab + { + TabFlow, + TabTextLog + }; + //! Constructor explicit CInterpolationLogDisplay(QWidget *parent = nullptr); @@ -42,6 +50,12 @@ namespace BlackGui //! Set simulator void setSimulator(BlackCore::CSimulatorCommon *simulatorCommon); + //! Set corresponding airspace monitor + void setAirspaceMonitor(BlackCore::CAirspaceMonitor *airspaceMonitor); + + //! If possible link with airspace monitor + void linkWithAirspaceMonitor(); + private: //! Update log. void updateLog(); @@ -61,10 +75,31 @@ namespace BlackGui //! Stop displaying void stop(); + //! Log the current callsign + bool logCallsign(const BlackMisc::Aviation::CCallsign &cs) const; + + //! \copydoc BlackCore::CAirspaceMonitor::addedAircraftSituation + void onSituationAdded(const BlackMisc::Aviation::CAircraftSituation &situation); + + //! \copydoc BlackCore::CAirspaceMonitor::addedAircraftSituation + void onPartsAdded(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts); + + //! \copydoc BlackCore::CSimulatorCommon::receivedRequestedElevation + void onElevationReceived(const BlackMisc::Geo::CElevationPlane &plane, const BlackMisc::Aviation::CCallsign &callsign); + + //! \copydoc BlackCore::CSimulatorCommon::requestedElevation + void onElevationRequested(const BlackMisc::Aviation::CCallsign &callsign); + + //! Clear + void clear(); + QScopedPointer ui; QTimer m_updateTimer; - QPointer m_simulatorCommon = nullptr; //!< related simulator + QPointer m_simulatorCommon; //!< related simulator + QPointer m_airspaceMonitor; //!< related airspace monitor BlackMisc::Aviation::CCallsign m_callsign; //!< current callsign + int m_elvRequested = 0; + int m_elvReceived = 0; static const QString &startText(); static const QString &stopText(); diff --git a/src/blackgui/components/interpolationlogdisplay.ui b/src/blackgui/components/interpolationlogdisplay.ui index 0fbf8e5b4..00b7f0af8 100644 --- a/src/blackgui/components/interpolationlogdisplay.ui +++ b/src/blackgui/components/interpolationlogdisplay.ui @@ -6,19 +6,57 @@ 0 0 - 640 - 480 + 800 + 600 Interpolation log. display - + + + 3 + + + 3 + + + 3 + + + 3 + - - + + + Log.callsign + + + + 3 + + + 3 + + + 3 + + + 3 + - + + + Qt::StrongFocus + + + + + + + true + + @@ -39,13 +77,6 @@ - - - - true - - - @@ -57,10 +88,328 @@ - - - true + + + Status + + + 3 + + + 3 + + + 3 + + + 3 + + + + + Running + + + + + + + + + + Qt::Horizontal + + + + 352 + 20 + + + + + + + + Situations + + + + + + + + + + Parts + + + + + + + + + + Elevation + + + + + + + + + + + + + 0 + + + + Data flow + + + + + + Inbound situations + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + + + + + + + Misc. + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + CG: + + + + + + + true + + + CG + + + + + + + Parts: + + + + + + + true + + + parts? + + + + + + + Gnd.flag: + + + + + + + true + + + gnd.flag? + + + + + + + Avg.time: + + + + + + + true + + + + + + + req.: + + + + + + + elevation requested + + + true + + + req. + + + + + + + Rec.: + + + + + + + elevation received + + + true + + + rec. + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Elevation: + + + + + + + true + + + elevation + + + + + + + + + + + + + Inbound parts + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + + + + + + + + Text log. + + + + + + true + + + + + @@ -72,7 +421,39 @@
blackgui/components/callsigncompleter.h
1 + + BlackGui::Views::CAircraftPartsView + QTableView +
blackgui/views/aircraftpartsview.h
+
+ + BlackGui::Views::CAircraftSituationView + QTableView +
blackgui/views/aircraftsituationview.h
+
+ + BlackGui::CLedWidget + QWidget +
blackgui/led.h
+ 1 +
+ + comp_CallsignCompleter + le_UpdateTime + hs_UpdateTime + le_CG + le_Parts + le_GndFlag + le_ElevationReq + le_Elevation + tvp_AircraftSituations + tvp_AircraftParts + tw_LogTabs + te_TextLog + le_ElevationRec + pb_StartStop + diff --git a/src/blackgui/components/interpolationlogdisplaydialog.cpp b/src/blackgui/components/interpolationlogdisplaydialog.cpp index 4d7ebf071..b94de0a28 100644 --- a/src/blackgui/components/interpolationlogdisplaydialog.cpp +++ b/src/blackgui/components/interpolationlogdisplaydialog.cpp @@ -17,13 +17,22 @@ namespace BlackGui { namespace Components { - CInterpolationLogDisplayDialog::CInterpolationLogDisplayDialog(CSimulatorCommon *simulatorCommon, QWidget *parent) : + CInterpolationLogDisplayDialog::CInterpolationLogDisplayDialog(CSimulatorCommon *simulatorCommon, CAirspaceMonitor *airspaceMonitor, QWidget *parent) : QDialog(parent), ui(new Ui::CInterpolationLogDisplayDialog) { ui->setupUi(this); this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); this->setSimulator(simulatorCommon); + + if (airspaceMonitor) + { + this->setAirspaceMonitor(airspaceMonitor); + } + else + { + ui->comp_InterpolationLogDisplay->linkWithAirspaceMonitor(); + } } CInterpolationLogDisplayDialog::~CInterpolationLogDisplayDialog() @@ -33,5 +42,10 @@ namespace BlackGui { ui->comp_InterpolationLogDisplay->setSimulator(simulatorCommon); } + + void CInterpolationLogDisplayDialog::setAirspaceMonitor(CAirspaceMonitor *airspaceMonitor) + { + ui->comp_InterpolationLogDisplay->setAirspaceMonitor(airspaceMonitor); + } } // ns } // ns diff --git a/src/blackgui/components/interpolationlogdisplaydialog.h b/src/blackgui/components/interpolationlogdisplaydialog.h index 06e0b466d..919f705e7 100644 --- a/src/blackgui/components/interpolationlogdisplaydialog.h +++ b/src/blackgui/components/interpolationlogdisplaydialog.h @@ -16,8 +16,12 @@ #include #include +namespace BlackCore +{ + class CSimulatorCommon; + class CAirspaceMonitor; +} namespace Ui { class CInterpolationLogDisplayDialog; } -namespace BlackCore { class CSimulatorCommon; } namespace BlackGui { namespace Components @@ -31,7 +35,9 @@ namespace BlackGui public: //! Constructor - explicit CInterpolationLogDisplayDialog(BlackCore::CSimulatorCommon *simulatorCommon, QWidget *parent = nullptr); + explicit CInterpolationLogDisplayDialog( + BlackCore::CSimulatorCommon *simulatorCommon, BlackCore::CAirspaceMonitor *airspaceMonitor, + QWidget *parent = nullptr); //! Destructor virtual ~CInterpolationLogDisplayDialog(); @@ -39,6 +45,9 @@ namespace BlackGui //! Set simulator void setSimulator(BlackCore::CSimulatorCommon *simulatorCommon); + //! Set airspace monitor + void setAirspaceMonitor(BlackCore::CAirspaceMonitor *airspaceMonitor); + private: QScopedPointer ui; }; diff --git a/src/blackgui/components/interpolationsetupcomponent.ui b/src/blackgui/components/interpolationsetupcomponent.ui index a2f9469a1..c9988ebce 100644 --- a/src/blackgui/components/interpolationsetupcomponent.ui +++ b/src/blackgui/components/interpolationsetupcomponent.ui @@ -6,8 +6,8 @@ 0 0 - 260 - 276 + 299 + 341 diff --git a/src/plugins/simulator/plugincommon/simulatorplugincommon.cpp b/src/plugins/simulator/plugincommon/simulatorplugincommon.cpp index acb64445b..92112f2a6 100644 --- a/src/plugins/simulator/plugincommon/simulatorplugincommon.cpp +++ b/src/plugins/simulator/plugincommon/simulatorplugincommon.cpp @@ -48,7 +48,7 @@ namespace BlackSimPlugin if (!m_interpolationDisplay) { QWidget *parentWidget = sGui ? sGui->mainApplicationWidget() : nullptr; - CInterpolationLogDisplayDialog *dialog = new CInterpolationLogDisplayDialog(this, parentWidget); + CInterpolationLogDisplayDialog *dialog = new CInterpolationLogDisplayDialog(this, nullptr, parentWidget); m_interpolationDisplay = dialog; } m_interpolationDisplay->show();