6 #include <QStringLiteral>
8 #include "ui_interpolationlogdisplay.h"
19 using namespace swift::core::context;
21 using namespace swift::gui::editors;
23 using namespace swift::misc::aviation;
24 using namespace swift::misc::geo;
25 using namespace swift::misc::network;
26 using namespace swift::misc::simulation;
27 using namespace swift::misc::physical_quantities;
31 const QStringList &CInterpolationLogDisplay::getLogCategories()
37 CInterpolationLogDisplay::CInterpolationLogDisplay(
QWidget *parent)
40 Q_ASSERT_X(
sGui, Q_FUNC_INFO,
"Need sGui");
43 ui->tw_LogTabs->setCurrentIndex(TabFlow);
44 constexpr
int timeSecs = 5;
45 ui->hs_UpdateTime->setValue(timeSecs);
46 this->onSliderChanged(timeSecs);
49 ui->led_Parts->setValues(CLedWidget::Yellow, CLedWidget::Black, shape,
"Parts received",
"", 14);
50 ui->led_Situation->setValues(CLedWidget::Yellow, CLedWidget::Black, shape,
"Situation received",
"", 14);
51 ui->led_Elevation->setValues(CLedWidget::Yellow, CLedWidget::Black, shape,
"Elevation received",
"", 14);
52 ui->led_Running->setValues(CLedWidget::Yellow, CLedWidget::Black, shape,
"Running",
"Stopped", 14);
53 ui->led_Updating->setValues(CLedWidget::Yellow, CLedWidget::Black, shape,
"Just updating",
"Idle", 14);
55 m_callsign = ui->comp_CallsignCompleter->getCallsign();
56 ui->tvp_InboundAircraftSituations->setWithMenuRequestElevation(
true);
59 ui->lv_ElevevationHistory->setModel(m_elvHistoryModel);
62 const int elvHistoryCount = 100;
63 m_elvHistoryCount = elvHistoryCount;
68 &CInterpolationLogDisplay::onCallsignEntered);
76 &CInterpolationLogDisplay::requestElevationClicked);
78 &CInterpolationLogDisplay::requestElevationClicked);
80 &CInterpolationLogDisplay::getLogAmdDisplayLastInterpolation);
84 &CInterpolationLogDisplay::requestRecalculateAll);
91 &CInterpolationLogDisplay::onElevationHistoryCountFinished);
93 connect(ui->tvp_InboundAircraftSituations, &CAircraftSituationView::requestElevation,
this,
94 &CInterpolationLogDisplay::requestElevation);
95 connect(ui->editor_ElevationCoordinate, &CCoordinateForm::changedCoordinate,
this,
96 &CInterpolationLogDisplay::requestElevationAtPosition);
105 if (simulator && simulator == m_simulator) {
return; }
109 m_simulator->disconnect(
this);
111 m_simulator = simulator;
112 if (!simulator) {
return; }
113 connect(m_simulator, &ISimulator::receivedRequestedElevation,
this,
115 connect(m_simulator, &ISimulator::requestedElevation,
this, &CInterpolationLogDisplay::onElevationRequested,
117 connect(m_simulator, &ISimulator::destroyed,
this, &CInterpolationLogDisplay::onSimulatorUnloaded);
118 connect(m_simulator, &ISimulator::simulatorStatusChanged,
this,
119 &CInterpolationLogDisplay::onSimulatorStatusChanged);
124 if (airspaceMonitor && airspaceMonitor == m_airspaceMonitor) {
return; }
125 if (m_airspaceMonitor)
128 m_airspaceMonitor->disconnect(
this);
130 m_airspaceMonitor = airspaceMonitor;
132 connect(m_airspaceMonitor, &CAirspaceMonitor::addedAircraftSituation,
this,
134 connect(m_airspaceMonitor, &CAirspaceMonitor::addedAircraftParts,
this, &CInterpolationLogDisplay::onPartsAdded,
138 void CInterpolationLogDisplay::updateLog()
140 ui->led_Updating->blink(250);
141 if (!this->checkLogPrerequisites())
143 ui->le_SimulatorSpecific->setText(m_simulator->getStatisticsSimulatorSpecific());
147 const SituationLog sLog = m_simulator->interpolationLogger().getLastSituationLog();
151 if (ui->tw_LogTabs->currentWidget() == ui->tb_TextLog)
153 const QString log = m_simulator->latestLoggedDataFormatted(m_callsign);
154 ui->te_TextLog->setText(log);
156 else if (ui->tw_LogTabs->currentWidget() == ui->tb_DataFlow && m_airspaceMonitor)
159 m_airspaceMonitor->getSimulatorCG(m_callsign).valueRoundedWithUnit(CLengthUnit::ft(), 1));
160 ui->le_CG->home(
false);
161 ui->le_Parts->setText(boolToYesNo(m_airspaceMonitor->isRemoteAircraftSupportingParts(m_callsign)));
163 static const QString msTimeStr(
"%1ms");
164 static const QString updateTimes(
"%1ms avg: %2ms max: %3ms");
165 const QString avgUpdateTimeRounded =
166 QString::number(m_simulator->getStatisticsAverageUpdateTimeMs(),
'f', 2);
168 ui->le_UpdateTimes->setText(updateTimes.arg(m_simulator->getStatisticsCurrentUpdateTimeMs())
169 .arg(avgUpdateTimeRounded)
170 .arg(m_simulator->getStatisticsMaxUpdateTimeMs()));
171 ui->le_UpdateTimes->home(
false);
172 ui->le_UpdateCount->setText(
QString::number(m_simulator->getStatisticsUpdateRuns()));
173 ui->le_UpdateReqTime->setText(msTimeStr.arg(m_simulator->getStatisticsAircraftUpdatedRequestedDeltaMs()));
174 ui->le_Limited->setText(m_simulator->updateAircraftLimitationInfo());
176 ui->le_SimulatorSpecific->setText(m_simulator->getStatisticsSimulatorSpecific());
177 ui->le_SimulatorSpecific->home(
false);
179 const CClient client = m_airspaceMonitor->getClientOrDefaultForCallsign(m_callsign);
182 this->displayElevationRequestReceive();
183 this->displayLastInterpolation(sLog);
185 else if (ui->tw_LogTabs->currentWidget() == ui->tb_Loopback) { this->displayLoopback(); }
188 void CInterpolationLogDisplay::getLogAmdDisplayLastInterpolation()
190 if (!this->canLog()) {
return; }
191 const SituationLog sLog = m_simulator->interpolationLogger().getLastSituationLog();
192 this->displayLastInterpolation(sLog);
195 void CInterpolationLogDisplay::displayLastInterpolation(
const SituationLog &sLog)
197 if (!this->checkLogPrerequisites()) {
return; }
202 ui->le_SceneryOffset->setText(
204 ui->le_SceneryOffsetCG->setText(
207 const PartsLog pLog = m_simulator->interpolationLogger().getLastPartsLog();
208 ui->te_LastInterpolatedParts->setText(pLog.
parts.
toQString(
true));
211 void CInterpolationLogDisplay::displayLoopback()
213 if (!m_simulator || m_callsign.
isEmpty()) {
return; }
214 ui->tvp_LoopbackAircraftSituations->updateContainerAsync(m_simulator->getLoopbackSituations(m_callsign));
215 ui->tvp_InterpolatedAircraftSituations->updateContainerAsync(m_lastInterpolations);
218 void CInterpolationLogDisplay::onSliderChanged(
int timeSecs)
221 ui->le_UpdateTime->setText(QStringLiteral(
"%1secs").arg(timeSecs));
224 void CInterpolationLogDisplay::onCallsignEntered()
233 const CCallsign cs = ui->comp_CallsignCompleter->getCallsign();
234 if (m_callsign == cs) {
return; }
247 m_simulator->setLogInterpolation(
false, m_callsign);
254 m_simulator->setLogInterpolation(
true, cs);
255 ui->comp_Parts->setCallsign(cs);
256 if (!this->start()) { this->initPartsView(); }
257 CLogMessage(
this).
info(u
"Starting logging (log.display) of '%1'") << m_callsign;
260 void CInterpolationLogDisplay::onPseudoElevationToggled(
bool checked)
262 if (!this->canLog()) {
return; }
263 m_simulator->setTestEnablePseudoElevation(checked);
266 if (!ui->le_ElevationTestValue->text().isEmpty())
269 const QString v = ui->le_ElevationTestValue->text();
273 m_simulator->setTestElevation(elvTest);
276 void CInterpolationLogDisplay::toggleStartStop()
278 const bool running = m_updateTimer.
isActive();
280 if (running) { this->stop(); }
284 this->onCallsignEntered();
288 void CInterpolationLogDisplay::followInSimulator()
290 if (m_callsign.
isEmpty()) {
return; }
291 if (!this->canLog()) {
return; }
292 m_simulator->followAircraft(m_callsign);
295 bool CInterpolationLogDisplay::start()
297 if (m_updateTimer.
isActive()) {
return false; }
299 const int interval = 1000 * ui->hs_UpdateTime->value();
300 m_updateTimer.
start(interval);
301 ui->pb_StartStop->setText(stopText());
302 ui->led_Running->setOn(
true);
304 this->initPartsView();
308 void CInterpolationLogDisplay::stop()
310 m_updateTimer.
stop();
311 ui->pb_StartStop->setText(startText());
312 ui->led_Running->setOn(
false);
315 bool CInterpolationLogDisplay::logCallsign(
const CCallsign &cs)
const
318 if (!m_airspaceMonitor || !m_simulator || m_callsign.
isEmpty()) {
return false; }
319 if (cs != m_callsign) {
return false; }
323 void CInterpolationLogDisplay::onAboutToShutdown()
325 m_updateTimer.
stop();
326 m_simulator =
nullptr;
329 void CInterpolationLogDisplay::onSimulatorUnloaded()
331 m_updateTimer.
stop();
332 m_simulator =
nullptr;
333 this->resetStatistics();
336 void CInterpolationLogDisplay::onSimulatorStatusChanged(ISimulator::SimulatorStatus status)
339 m_updateTimer.
stop();
340 this->resetStatistics();
345 static const QString info(
"times: %1 offset %2");
348 if (!this->logCallsign(cs)) {
return; }
353 ui->tvp_InboundAircraftSituations->updateContainerAsync(situations);
354 ui->tvp_Changes->updateContainerMaybeAsync(changes);
355 ui->le_InboundSituationsInfo->setText(info.arg(tsDiffMsMinMaxMean.
asString(), offsetMsMinMaxMean.
asString()));
356 ui->led_Situation->blink();
361 if (!this->logCallsign(callsign)) {
return; }
363 const CAircraftPartsList partsList = m_airspaceMonitor->remoteAircraftParts(callsign);
364 ui->tvp_InboundAircraftParts->updateContainerAsync(partsList);
365 ui->led_Parts->blink();
368 void CInterpolationLogDisplay::onElevationReceived(
const CElevationPlane &elevationPlane,
const CCallsign &callsign)
371 if (m_elvHistoryCount > 0)
378 m_elvHistoryModel->
setData(index, history);
380 const int c = m_elvHistoryModel->
rowCount();
381 if (m_elvHistoryCount < c) { m_elvHistoryModel->
removeRows(m_elvHistoryCount, c - m_elvHistoryCount); }
385 if (callsign == CInterpolationLogDisplay::pseudoCallsignElevation())
387 this->displayArbitraryElevation(elevationPlane);
391 if (!this->logCallsign(callsign)) {
return; }
394 m_elvReceivedLoggedCs++;
395 ui->le_Elevation->setText(elevationPlane.
toQString());
396 this->displayElevationRequestReceive();
397 ui->led_Elevation->blink();
400 void CInterpolationLogDisplay::onElevationRequested(
const CCallsign &callsign)
403 if (!this->logCallsign(callsign)) {
return; }
406 m_elvRequestedLoggedCs++;
407 this->displayElevationRequestReceive();
408 ui->led_Elevation->blink();
411 void CInterpolationLogDisplay::onInjectElevation()
413 if (!this->canLog()) {
return; }
414 const QString elv = ui->le_InjectElevation->text().trimmed();
418 if (situations.
isEmpty()) {
return; }
425 m_simulator->callbackReceivedRequestedElevation(ep, m_callsign,
false);
428 void CInterpolationLogDisplay::onElevationHistoryCountFinished()
430 const QString cs = ui->le_ElvHistoryCount->text().trimmed();
435 const int cc = cs.
toInt(&ok);
438 m_elvHistoryCount = c;
441 void CInterpolationLogDisplay::resetStatistics()
443 if (m_simulator) { m_simulator->resetAircraftStatistics(); }
446 void CInterpolationLogDisplay::resetLastSentValues()
448 if (m_simulator) { m_simulator->resetLastSentValues(); }
451 void CInterpolationLogDisplay::clear()
453 ui->tvp_InboundAircraftParts->clear();
454 ui->tvp_InboundAircraftSituations->clear();
455 ui->te_TextLog->clear();
457 ui->le_Elevation->clear();
458 ui->le_ElevationReqRec->clear();
459 ui->le_ElevationReqRec->setToolTip(
"elevation requested");
460 ui->le_Parts->clear();
461 ui->le_UpdateTimes->clear();
462 ui->le_UpdateTimes->clear();
463 ui->le_Limited->clear();
464 m_elvReceivedLoggedCs = m_elvRequestedLoggedCs = 0;
465 m_elvReceived = m_elvRequested = 0;
466 m_lastInterpolations.
clear();
468 this->clearElevationResults();
471 void CInterpolationLogDisplay::clearElevationResults()
473 ui->pte_ElevationAtPosition->clear();
474 if (m_elvHistoryModel) { m_elvHistoryModel->
removeRows(0, m_elvHistoryModel->
rowCount()); }
477 void CInterpolationLogDisplay::logPosCommand()
479 if (m_callsign.
isEmpty()) {
return; }
482 const QString cmd = QStringLiteral(
".drv logint clear") % m_callsign.
asString();
486 void CInterpolationLogDisplay::clearLogCommand()
490 const QString cmd = QStringLiteral(
".drv logint clear");
494 void CInterpolationLogDisplay::writeLogCommand()
498 const QString cmd = QStringLiteral(
".drv logint write");
502 bool CInterpolationLogDisplay::checkLogPrerequisites()
504 using namespace std::chrono_literals;
507 if (!this->
isVisible()) {
return false; }
509 if (m_callsign.isEmpty())
516 const bool canUpdateLog =
517 m_airspaceMonitor && m_simulator && m_simulator->isConnected() && !m_simulator->isShuttingDown();
526 if (!m_simulator->isLogCallsign(m_callsign))
540 void CInterpolationLogDisplay::initPartsView()
545 if (!myself) {
return; }
546 if (m_callsign.
isEmpty()) { return; }
551 void CInterpolationLogDisplay::displayElevationRequestReceive()
553 if (!m_airspaceMonitor) {
return; }
554 static const QString info(
"req. %1, %2/rec. %3, %4 | found/missed: '%5' | times: %6");
555 const QString foundMissed = m_airspaceMonitor->getElevationsFoundMissedInfo();
556 const QString reqTimes = m_airspaceMonitor->getElevationRequestTimesInfo();
557 const QString reqRec = info.
arg(m_elvRequestedLoggedCs)
559 .
arg(m_elvReceivedLoggedCs)
561 .
arg(foundMissed, reqTimes);
563 ui->le_ElevationReqRec->setText(reqRec);
564 ui->le_ElevationReqRec->setToolTip(reqRec);
565 ui->le_ElevationReqRec->home(
false);
568 void CInterpolationLogDisplay::displayArbitraryElevation(
const CElevationPlane &elevation)
570 ui->pte_ElevationAtPosition->appendPlainText(elevation.
toQString());
573 void CInterpolationLogDisplay::requestElevationClicked()
575 if (m_callsign.
isEmpty()) {
return; }
577 if (situations.
isEmpty()) {
return; }
583 if (!this->canLog()) {
return; }
584 m_simulator->requestElevationBySituation(situation);
587 void CInterpolationLogDisplay::requestElevationAtPosition()
589 if (!this->canLog()) {
return; }
591 const bool ok = m_simulator->requestElevation(coordinate, CInterpolationLogDisplay::pseudoCallsignElevation());
594 static const QString info(
"Requesting elevation: %1");
595 ui->pte_ElevationAtPosition->setPlainText(info.arg(coordinate.
toQString()));
599 static const QString info(
"Cannot request elevation");
600 ui->pte_ElevationAtPosition->setPlainText(info);
604 void CInterpolationLogDisplay::requestRecalculateAll()
606 if (!this->canLog()) {
return; }
610 bool CInterpolationLogDisplay::canLog()
const
615 const CCallsign &CInterpolationLogDisplay::pseudoCallsignElevation()
629 const QString &CInterpolationLogDisplay::startText()
631 static const QString start(
"start");
635 const QString &CInterpolationLogDisplay::stopText()
637 static const QString stop(
"stop");
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Keeps track of other entities in the airspace: aircraft, ATC stations, etc. Central instance of data ...
void aboutToShutdown()
About to shutdown.
CCoreFacade * getCoreFacade()
Get the facade.
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
bool supportsContexts(bool ignoreShutdownTest=false) const
Supports contexts.
context::CContextNetwork * getCContextNetwork()
Context for network.
Interface to a simulator.
Network context implementation.
CAirspaceMonitor * airspace() const
Airspace.
virtual bool parseCommandLine(const QString &commandLine, const swift::misc::CIdentifier &originator)=0
Parse a given command line.
virtual void recalculateAllAircraft()=0
Recalculate all aircraft.
bool showOverlayMessage(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Show single message.
Using this class provides a QFrame with the overlay functionality already integrated.
void editingFinishedDigest()
Editing finished.
Display live data of interpolation.
void setSimulator(swift::core::ISimulator *simulator)
Set simulator.
void setAirspaceMonitor(swift::core::CAirspaceMonitor *airspaceMonitor)
Set corresponding airspace monitor.
~CInterpolationLogDisplay()
Destructor.
void linkWithAirspaceMonitor()
If possible link with airspace monitor.
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.
static const QString & interpolator()
Interpolator.
static const QString & driver()
Driver.
Class for emitting a log message.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
bool isEmpty() const
Message empty.
Derived & validationError(const char16_t(&format)[N])
Set the severity to error, 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.
void clear()
Removes all elements in the sequence.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
MillisecondsMinMaxMean getTimestampDifferenceMinMaxMean() const
Difference of timestamp values.
OBJ latestAdjustedObject() const
Latest adjusted object.
MillisecondsMinMaxMean getOffsetMinMaxMean() const
Difference of timestamp values.
void push_frontKeepLatestAdjustedFirst(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Insert as first element by keeping maxElements and the latest first.
Value object encapsulating information of aircraft's parts.
Value object encapsulating a list of aircraft parts.
const physical_quantities::CLength & getGuessedSceneryDeviation() const
Scnenery deviation (if it can be calculated, otherwise physical_quantities::CLength::null)
physical_quantities::CLength getGuessedSceneryDeviationCG() const
Get scenery deviation under consideration of CG.
Value object encapsulating a list of aircraft parts.
Value object encapsulating information of an aircraft's situation.
const CCallsign & getCallsign() const
Corresponding callsign.
List of aircraft situations.
Altitude as used in aviation, can be AGL or MSL altitude.
void parseFromString(const QString &value)
Parse value from string.
Value object encapsulating information of a callsign.
void clear()
Clear this callsign.
const QString & asString() const
Get callsign (normalized)
bool isEmpty() const
Is empty?
Plane of same elevation, can be a single point or larger area (e.g. airport)
QString toQString(bool i18n=false) const
Cast as QString.
bool hasGndFlagCapability() const
Supports gnd.flag?
Physical unit length (length)
void parseFromString(const QString &value)
Parse value from string.
bool isNull() const
Is quantity null?
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".
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.
Views, mainly QTableView.
Free functions in swift::misc.
bool insertRow(int row, const QModelIndex &parent)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
void valueChanged(int value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QString arg(Args &&... args) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
int toInt(bool *ok, int base) const const
virtual bool removeRows(int row, int count, const QModelIndex &parent) override
virtual int rowCount(const QModelIndex &parent) const const override
virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override
QString toString(QStringView format) const const
void setInterval(int msec)
bool isActive() const const
Milliseconds minimum/maximum/mean.
QString asString() const
As string.
Log entry for parts interpolation.
aviation::CAircraftParts parts
parts to be logged
Log entry for situation interpolation.
aviation::CAircraftSituation situationCurrent
interpolated situation
aviation::CAircraftSituationChange change
change