swift
Loading...
Searching...
No Matches
simulatoremulatedmonitordialog.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2017 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
6#include <QIntValidator>
7
8#include "simulatoremulated.h"
9#include "ui_simulatoremulatedmonitordialog.h"
10
13#include "gui/guiapplication.h"
14#include "misc/logmessage.h"
15
16using namespace swift::config;
17using namespace swift::misc;
18using namespace swift::misc::aviation;
19using namespace swift::misc::simulation;
20using namespace swift::gui;
21using namespace swift::gui::components;
22using namespace swift::gui::editors;
23
24namespace swift::simplugin::emulated
25{
31
33 : QDialog(parent), CIdentifiable("Emulated driver dialog"), ui(new Ui::CSimulatorEmulatedMonitorDialog)
34 {
35 Q_ASSERT_X(simulator, Q_FUNC_INFO, "Need simulator");
36
37 ui->setupUi(this);
38 ui->tw_SwiftMonitorDialog->setCurrentIndex(0);
39 ui->comp_LogComponent->setMaxLogMessages(500);
41
42 m_simulator = simulator;
43 m_uiUpdateTimer.setObjectName(this->objectName() + ":uiUpdateTimer");
44 m_uiUpdateTimer.start(2500);
45
47 &CSimulatorEmulatedMonitorDialog::setInternalAircraftUiValues, Qt::QueuedConnection);
48 connect(&m_uiUpdateTimer, &QTimer::timeout, this, &CSimulatorEmulatedMonitorDialog::timerBasedUiUpdates);
49
50 connect(ui->cb_Connected, &QCheckBox::released, this,
51 &CSimulatorEmulatedMonitorDialog::onSimulatorValuesChanged);
52 connect(ui->cb_Paused, &QCheckBox::released, this, &CSimulatorEmulatedMonitorDialog::onSimulatorValuesChanged);
53 connect(ui->cb_Simulating, &QCheckBox::released, this,
54 &CSimulatorEmulatedMonitorDialog::onSimulatorValuesChanged);
55
56 connect(ui->editor_Situation, &CSituationForm::changeAircraftSituation, this,
57 &CSimulatorEmulatedMonitorDialog::changeSituationFromUi, Qt::QueuedConnection);
58 connect(ui->editor_AircraftParts, &CAircraftPartsForm::changeAircraftParts, this,
59 &CSimulatorEmulatedMonitorDialog::changePartsFromUi, Qt::QueuedConnection);
61 &CSimulatorEmulatedMonitorDialog::changeComFromUi, Qt::QueuedConnection);
62 connect(ui->editor_Com, &CCockpitComForm::changedSelcal, this,
63 &CSimulatorEmulatedMonitorDialog::changeSelcalFromUi, Qt::QueuedConnection);
64 connect(ui->comp_ComTransmissions, &CCockpitComTransmissionComponent::changedValues, this,
65 &CSimulatorEmulatedMonitorDialog::onSavedComTransmissionValues, Qt::QueuedConnection);
66
67 connect(ui->pb_ResetStatistics, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::resetStatistics);
68 connect(ui->pb_InterpolatorStopLog, &QPushButton::clicked, this,
69 &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
70 connect(ui->pb_InterpolatorWriteLog, &QPushButton::clicked, this,
71 &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
72 connect(ui->pb_InterpolatorClearLog, &QPushButton::clicked, this,
73 &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
74 connect(ui->pb_InterpolatorShowLogs, &QPushButton::clicked, this,
75 &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
76 connect(ui->pb_InterpolatorStartLog, &QPushButton::clicked, this,
77 &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
78 connect(ui->pb_InterpolatorFetch, &QPushButton::clicked, this,
79 &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
80 connect(ui->pb_EmitAddedFailed, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::emitSignal);
81 connect(ui->pb_AddAutoPublishData, &QPushButton::clicked, this,
82 &CSimulatorEmulatedMonitorDialog::addAutoPublishTestData);
83
84 ui->led_Receiving->setToolTips("receiving", "idle");
85 ui->led_Receiving->setShape(CLedWidget::Rounded);
86 ui->led_Sending->setToolTips("sending", "idle");
87 ui->led_Sending->setShape(CLedWidget::Rounded);
88 ui->led_Fetching->setToolTips("fetching interpolated", "not fetching interpolated");
89 ui->led_Fetching->setShape(CLedWidget::Rounded);
90
91 ui->le_InterpolatorTimeMs->setValidator(new QIntValidator(10, 20000, ui->le_InterpolatorTimeMs));
92
93 this->enableInterpolationLogButtons(false);
94 this->setSimulatorUiValues();
95 this->setInternalAircraftUiValues();
97 }
98
100
102 {
103 ui->comp_LogComponent->appendStatusMessagesToList(statusMessage);
104 }
105
106 void
108 {
109 ui->comp_LogComponent->appendStatusMessagesToList(statusMessages);
110 }
111
113 const QString &p2, const QString &p3)
114 {
115 ui->led_Receiving->blink();
116 this->appendFunctionCall(function, p1, p2, p3);
117 }
118
120 const QString &p2, const QString &p3)
121 {
122 ui->led_Sending->blink();
123 this->appendFunctionCall(function, p1, p2, p3);
124 }
125
126 void CSimulatorEmulatedMonitorDialog::appendFunctionCall(const QString &function, const QString &p1,
127 const QString &p2, const QString &p3)
128 {
129 static const QString c1("%1 %2");
130 static const QString c2("%1 %2 %3");
131 static const QString c3("%1 %2 %3 %4");
132
133 CStatusMessage msg;
134 if (!p3.isEmpty())
135 {
136 msg = CStatusMessage(this, CStatusMessage::SeverityInfo, c3.arg(function, p1, p2, p3));
137 }
138 else if (!p2.isEmpty())
139 {
140 msg = CStatusMessage(this, CStatusMessage::SeverityInfo, c2.arg(function, p1, p2));
141 }
142 else if (!p1.isEmpty())
143 {
144 msg = CStatusMessage(this, CStatusMessage::SeverityInfo, c1.arg(function, p1));
145 }
146 else
147 {
148 msg = CStatusMessage(this, CStatusMessage::SeverityInfo, function);
149 }
150 this->appendStatusMessageToList(msg);
151 }
152
154 {
155 ui->pte_StatusMessages->setPlainText(message.toQString(true));
156 }
157
159 {
160 ui->pte_TextMessages->setPlainText(message.toQString(true));
161 }
162
164 {
165 if (!info.isSingleSimulator())
166 {
167 return;
168 }
169 this->setWindowTitle("Emulated driver : " + info.toQString());
170 this->setSimulatorUiValues();
171 }
172
173 void CSimulatorEmulatedMonitorDialog::onSimulatorValuesChanged()
174 {
175 m_simulator->setCombinedStatus(ui->cb_Connected->isChecked(), ui->cb_Simulating->isChecked(),
176 ui->cb_Paused->isChecked());
177 }
178
179 void CSimulatorEmulatedMonitorDialog::onSavedComTransmissionValues(CComSystem::ComUnit unit)
180 {
181 if (!this->canUseSimulator())
182 {
183 return;
184 }
185 const CSimulatedAircraft ownAircraft = m_simulator->getOwnAircraft();
186 CComSystem com = ownAircraft.getComSystem(unit);
187 ui->comp_ComTransmissions->updateComSystem(com, unit);
188 m_simulator->changeInternalCom(com, unit);
189 }
190
191 void CSimulatorEmulatedMonitorDialog::changeComFromUi(const CSimulatedAircraft &aircraft)
192 {
193 if (!this->canUseSimulator())
194 {
195 return;
196 }
197 m_simulator->changeInternalCom(aircraft);
198 }
199
200 void CSimulatorEmulatedMonitorDialog::changeSelcalFromUi(const CSelcal &selcal)
201 {
202 if (!this->canUseSimulator())
203 {
204 return;
205 }
206 m_simulator->changeInternalSelcal(selcal);
207 }
208
209 void CSimulatorEmulatedMonitorDialog::changeSituationFromUi()
210 {
211 if (!this->canUseSimulator())
212 {
213 return;
214 }
215 const CAircraftSituation s(ui->editor_Situation->getSituation());
216 m_simulator->changeInternalSituation(s);
217 }
218
219 void CSimulatorEmulatedMonitorDialog::changePartsFromUi()
220 {
221 if (!this->canUseSimulator())
222 {
223 return;
224 }
225 const CAircraftParts p(ui->editor_AircraftParts->getAircraftPartsFromGui());
226 m_simulator->changeInternalParts(p);
227 }
228
229 void CSimulatorEmulatedMonitorDialog::setSimulatorUiValues()
230 {
231 ui->cb_Connected->setChecked(m_simulator->isConnected());
232 ui->cb_Paused->setChecked(m_simulator->isPaused());
233 ui->cb_Simulating->setChecked(m_simulator->isSimulating());
234
235 ui->le_Simulator->setText(m_simulator->getSimulatorInfo().toQString(true));
236 ui->le_SimulatorPlugin->setText(m_simulator->getSimulatorPluginInfo().toQString(true));
237 }
238
239 void CSimulatorEmulatedMonitorDialog::setInternalAircraftUiValues()
240 {
241 const CSimulatedAircraft internal(m_simulator->getInternalOwnAircraft());
242 ui->editor_Situation->setSituation(internal.getSituation());
243 ui->editor_AircraftParts->setAircraftParts(internal.getParts());
244 ui->editor_Com->setValue(internal);
245 ui->comp_ComTransmissions->setComSystems(internal);
246 }
247
248 void CSimulatorEmulatedMonitorDialog::timerBasedUiUpdates()
249 {
250 if (!this->canUseSimulator())
251 {
252 return;
253 }
254
255 ui->le_PhysicallyAddedAircraft->setText(QString::number(m_simulator->getStatisticsPhysicallyAddedAircraft()));
256 ui->le_PhysicallyRemovedAircraft->setText(QString::number(m_simulator->aircraftSituationsAdded()));
257 ui->le_SituationAdded->setText(QString::number(m_simulator->aircraftSituationsAdded()));
258 ui->le_PartsAdded->setText(QString::number(m_simulator->aircraftPartsAdded()));
259 ui->le_AircraftRendered->setText(QString::number(m_simulator->m_renderedAircraft.size()));
260 ui->le_PartsEnabledAircraft->setText(QString::number(m_simulator->getRemoteAircraftSupportingPartsCount()));
261 }
262
263 void CSimulatorEmulatedMonitorDialog::resetStatistics()
264 {
265 if (!this->canUseSimulator())
266 {
267 return;
268 }
269
270 m_simulator->resetAircraftStatistics();
271 ui->le_PhysicallyAddedAircraft->clear();
272 ui->le_PhysicallyRemovedAircraft->clear();
273 ui->le_SituationAdded->clear();
274 ui->le_PartsAdded->clear();
275 }
276
277 void CSimulatorEmulatedMonitorDialog::interpolatorLogButton()
278 {
279 const QObject *sender = QObject::sender();
280 bool ok = false;
281 if (sender == ui->pb_InterpolatorStopLog)
282 {
283 ok = m_simulator->parseCommandLine(".drv logint off", this->identifier());
284 }
285 else if (sender == ui->pb_InterpolatorWriteLog)
286 {
287 ok = m_simulator->parseCommandLine(".drv logint write", this->identifier());
288 }
289 else if (sender == ui->pb_InterpolatorClearLog)
290 {
291 ok = m_simulator->parseCommandLine(".drv logint clear", this->identifier());
292 }
293 else if (sender == ui->pb_InterpolatorShowLogs)
294 {
295 ok = m_simulator->parseCommandLine(".drv logint show", this->identifier());
296 }
297 else if (sender == ui->pb_InterpolatorStartLog)
298 {
299 const CCallsign cs = ui->comp_LogInterpolatorCallsign->getCallsign();
300 if (cs.isValid())
301 {
302 ok = m_simulator->parseCommandLine(".drv logint " + cs.asString(), this->identifier());
303 }
304 else
305 {
306 CLogMessage(this).warning(u"Need a (valid) callsign to write a log");
307 ok = true; // already a warning
308 }
309 }
310 else if (sender == ui->pb_InterpolatorFetch)
311 {
312 // toggle fetching
313 const int timeMs = m_simulator->isInterpolatorFetching() ? -1 : ui->le_InterpolatorTimeMs->text().toInt();
314 const bool fetching = m_simulator->setInterpolatorFetchTime(timeMs);
315 ui->led_Fetching->setOn(fetching);
316 ui->pb_InterpolatorFetch->setText(fetching ? "Stop" : "Fetch");
317 this->enableInterpolationLogButtons(fetching);
318 ok = true;
319 }
320 else
321 {
322 Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled button");
323 }
324 if (!ok)
325 {
326 CLogMessage(this).warning(u"Cannot parse command for button: %1") << sender->objectName();
327 }
328 }
329
330 void CSimulatorEmulatedMonitorDialog::enableInterpolationLogButtons(bool enable)
331 {
332 ui->pb_InterpolatorClearLog->setEnabled(enable);
333 ui->pb_InterpolatorShowLogs->setEnabled(enable);
334 ui->pb_InterpolatorStartLog->setEnabled(enable);
335 ui->pb_InterpolatorStopLog->setEnabled(enable);
336 ui->pb_InterpolatorWriteLog->setEnabled(enable);
337 }
338
339 void CSimulatorEmulatedMonitorDialog::emitSignal()
340 {
341 if (!this->canUseSimulator())
342 {
343 return;
344 }
345
346 const CCallsign cs = ui->comp_CallsignCompleter->getCallsign();
347 const QObject *sender = QObject::sender();
348 if (sender == ui->pb_EmitAddedFailed && cs.isValid())
349 {
350 const CSimulatedAircraft aircraft = m_simulator->getAircraftInRangeForCallsign(cs);
351 const CStatusMessage msg(this, CStatusMessage::SeverityError,
352 "Simulated driver driver failed for " + cs.asString());
353 emit m_simulator->physicallyAddingRemoteModelFailed(aircraft, true, ui->cb_Failover->isChecked(), msg);
354 }
355 }
356
357 void CSimulatorEmulatedMonitorDialog::addAutoPublishTestData()
358 {
359 if (!this->canUseSimulator())
360 {
361 return;
362 }
363 m_simulator->m_autoPublishing.testData();
364 }
365
366 bool CSimulatorEmulatedMonitorDialog::canUseSimulator() const
367 {
368 return (m_simulator && sGui && !sGui->isShuttingDown());
369 }
370} // namespace swift::simplugin::emulated
bool isShuttingDown() const
Is application shutting down?
void changedValues(swift::misc::aviation::CComSystem::ComUnit unit)
Values changed for unit.
void changeAircraftParts()
Change coordinate.
void changedCockpitValues(const swift::misc::simulation::CSimulatedAircraft &aircraft)
GUI values changed.
void changedSelcal(const swift::misc::aviation::CSelcal &selcal)
SELCAL value changed.
void changeAircraftSituation()
Aircraft situation to be changed.
CIdentifiable(const QString &objectName)
Use literal based object name.
const CIdentifier & identifier() const
Get identifier.
static const QString & driver()
Driver.
static const QString & plugin()
Plugin.
Streamable status message, e.g.
static constexpr auto SeverityInfo
Status severities.
static constexpr auto SeverityError
Status severities.
Status messages, e.g. from Core -> GUI.
const QString & asString() const
Get callsign (normalized).
Definition callsign.h:96
bool isValid() const
Valid callsign?
Definition callsign.cpp:512
COM system (aka "radio").
Definition comsystem.h:37
QString toQString(bool i18n=false) const
Cast as QString.
Definition mixinstring.h:74
Value object encapsulating information of a text message.
Definition textmessage.h:31
CSimulatedAircraft getOwnAircraft() const
Own aircraft.
Comprehensive information of an aircraft.
aviation::CComSystem getComSystem(aviation::CComSystem::ComUnit unit) const
Get COM unit.
Simple hardcoded info about the corresponding simulator.
bool isSingleSimulator() const
Single simulator selected.
CSimulatorInfo getSimulatorInfo() const
Get the represented simulator.
void internalAircraftChanged()
Internal aircraft changed.
bool changeInternalCom(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Simulator internal change of COM values.
void setCombinedStatus(bool connected, bool simulating, bool paused)
UI setter.
CSimulatorEmulatedMonitorDialog(CSimulatorEmulated *simulator, QWidget *parent=nullptr)
Ctor.
void appendStatusMessageToList(const swift::misc::CStatusMessage &statusMessage)
Append status message.
void appendReceivingCall(const QString &function, const QString &p1={}, const QString &p2={}, const QString &p3={})
Receiving call to be written in log widget.
void displayStatusMessage(const swift::misc::CStatusMessage &message)
Display status message.
void updateWindowTitleAndUiValues(const swift::misc::simulation::CSimulatorInfo &info)
The title.
void appendStatusMessagesToList(const swift::misc::CStatusMessageList &statusMessages)
Append status messages.
void appendSendingCall(const QString &function, const QString &p1={}, const QString &p2={}, const QString &p3={})
Sending call to be written in log widget.
void displayTextMessage(const swift::misc::network::CTextMessage &message)
Display text message.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
High level reusable GUI components.
GUI related classes.
Free functions in swift::misc.
void clicked(bool checked)
QDialog(QWidget *parent, Qt::WindowFlags f)
QObject(QObject *parent)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QObject * sender() const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QueuedConnection
WindowContextHelpButtonHint
void timeout()
QWidget(QWidget *parent, Qt::WindowFlags f)
void setWindowFlags(Qt::WindowFlags type)
void setWindowTitle(const QString &)