swift
Loading...
Searching...
No Matches
simulatedaircraftview.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 <QPointer>
7#include <QStringBuilder>
8#include <QtGlobal>
9
10#include "config/buildconfig.h"
13#include "gui/guiapplication.h"
14#include "gui/menus/menuaction.h"
18#include "misc/icons.h"
20
21using namespace swift::config;
22using namespace swift::misc;
23using namespace swift::misc::physical_quantities;
24using namespace swift::misc::aviation;
25using namespace swift::misc::simulation;
26using namespace swift::core::context;
27using namespace swift::gui::models;
28using namespace swift::gui::menus;
29
30namespace swift::gui::views
31{
37
39 {
40 Q_ASSERT(m_model);
41 m_model->setAircraftMode(mode);
42 this->setSortIndicator();
43 }
44
45 void CSimulatedAircraftView::configureMenu(bool menuRecalculate, bool menuHighlightAndFollow,
46 bool menuEnableAircraft, bool menuFastPositionUpdates, bool menuGndFlag,
47 bool menuFlightPlan)
48 {
49 m_withRecalculate = menuRecalculate;
50 m_withMenuEnableAircraft = menuEnableAircraft;
51 m_withMenuFastPosition = menuFastPositionUpdates;
52 m_withMenuHighlightAndFollow = menuHighlightAndFollow;
53 m_withMenuEnableGndFlag = menuGndFlag;
54 m_withMenuFlightPlan = menuFlightPlan;
55 }
56
58 {
59 m_withMenuFastPosition = menuFastPositionUpdates;
60 }
61
63 {
64 // sub menus, only adding the path, the content will be added below
65 // => configureMenu
66 menuActions.addMenuDisplayModels();
67 menuActions.addMenuRenderModels();
68 menuActions.addMenuDataTransfer();
69
70 if (m_menus.testFlag(MenuDisableModelsTemp) && this->hasSelection())
71 {
72 menuActions.addAction(CIcons::delete16(), "Temp.disable model from set",
74 { this, &CSimulatedAircraftView::requestTempDisable });
75 }
76
77 if (m_withRecalculate)
78 {
79 menuActions.addAction(CIcons::appInterpolation16(), "Re-calculate all aircraft",
81 { this, &CSimulatedAircraftView::recalculateAllAircraft });
82 menuActions.addAction(CIcons::appInterpolation16(), "Re-matching all aircraft",
84 { this, &CSimulatedAircraftView::doMatchingsAgain });
85 if (this->hasSelection())
86 {
87 menuActions.addAction(CIcons::appInterpolation16(), "Re-matching selected",
89 { this, &CSimulatedAircraftView::doMatchingsAgainForSelected });
90 }
91 }
92
93 if (m_withMenuEnableAircraft && !this->isEmpty())
94 {
95 menuActions.addAction(CIcons::appAircraft16(), "Enable all aircraft",
97 { this, &CSimulatedAircraftView::enableAllDisabledAircraft });
98 menuActions.addAction(CIcons::appAircraft16(), "Re-enable unrendered aircraft",
100 { this, &CSimulatedAircraftView::reEnableAllUnrenderedAircraft });
101 menuActions.addAction(CIcons::appAircraft16(), "Disable all aircraft",
103 { this, &CSimulatedAircraftView::disableAllEnabledAircraft });
104 }
105
106 if (this->hasSelection())
107 {
108 const bool hasContexts = sGui && sGui->supportsContexts();
109 if (hasContexts)
110 {
111 const CSimulatedAircraft aircraft(this->selectedObject());
112 Q_ASSERT(!aircraft.getCallsign().isEmpty());
113 menuActions.addMenuCom();
114 menuActions.addAction(CIcons::appTextMessages16(), "Show text messages", CMenuAction::pathClientCom(),
115 { this, &CSimulatedAircraftView::requestTextMessage });
116
117 if (m_withMenuFlightPlan && networkContext() && networkContext()->isConnected())
118 {
120 { this, &CSimulatedAircraftView::showFlightPlanDialog });
121 }
122 if (m_withMenuEnableAircraft)
123 {
124 menuActions.addAction(CIcons::appAircraft16(),
125 aircraft.isEnabled() ? "Disable aircraft" : "Enabled aircraft",
127 { this, &CSimulatedAircraftView::toggleEnabledAircraft });
128 }
129 if (m_withMenuHighlightAndFollow)
130 {
131 menuActions.addAction(CIcons::appAircraft16(), "Follow in simulator",
133 { this, &CSimulatedAircraftView::requestFollowInSimulator });
134 if (!menuActions.isEmpty())
135 {
137 }
138 if (aircraft.isPartsSynchronized())
139 {
140 menuActions.addAction(CIcons::appAircraft16(), "Temp.disable parts",
142 { this, &CSimulatedAircraftView::requestDisableParts });
143 menuActions.addAction(CIcons::appAircraft16(), "Re/enabled parts",
145 { this, &CSimulatedAircraftView::requestEnableParts });
146 }
147 menuActions.addAction(CIcons::appAircraft16(), "Zero 0 pitch on ground",
149 { this, &CSimulatedAircraftView::request0PitchOnGround });
150 menuActions.addAction(CIcons::appAircraft16(), "Remove pitch manipulation",
152 { this, &CSimulatedAircraftView::requestNullPitchOnGround });
153 }
154 if (m_withMenuEnableGndFlag)
155 {
156 menuActions.addAction(CIcons::geoPosition16(),
157 aircraft.isSupportingGndFlag() ? "Disable gnd.flag" : "Enabled gnd.flag",
159 { this, &CSimulatedAircraftView::toggleSupportingGndFlag });
160 }
161 if (m_withMenuFastPosition)
162 {
163 menuActions.addAction(CIcons::globe16(),
164 aircraft.fastPositionUpdates() ? "Normal updates" :
165 "Fast position updates (send)",
167 { this, &CSimulatedAircraftView::toggleFastPositionUpdates });
168 }
169
170 const bool any = m_withMenuEnableAircraft || m_withMenuFastPosition || m_withMenuHighlightAndFollow ||
171 m_withMenuEnableGndFlag || m_withMenuFlightPlan;
172 if (any && (sApp && sApp->isDeveloperFlagSet()))
173 {
174 menuActions.addAction(CIcons::appSimulator16(), "Show position log.",
176 { this, &CSimulatedAircraftView::showPositionLogInSimulator });
177 }
178 } // contexts
179 }
180 CViewBase::customMenu(menuActions);
181 }
182
183 void CSimulatedAircraftView::requestTextMessage()
184 {
185 const CSimulatedAircraft aircraft(this->selectedObject());
186 if (aircraft.getCallsign().isEmpty())
187 {
188 return;
189 }
190 emit this->requestTextMessageWidget(aircraft.getCallsign());
191 }
192
193 void CSimulatedAircraftView::toggleEnabledAircraft()
194 {
195 CSimulatedAircraft aircraft(this->selectedObject());
196 if (aircraft.getCallsign().isEmpty())
197 {
198 return;
199 }
200 aircraft.setEnabled(!aircraft.isEnabled());
201 this->updateAircraftEnabled(aircraft);
202 }
203
204 void CSimulatedAircraftView::toggleFastPositionUpdates()
205 {
206 CSimulatedAircraft aircraft(this->selectedObject());
207 if (aircraft.getCallsign().isEmpty())
208 {
209 return;
210 }
211 aircraft.toggleFastPositionUpdates();
212 this->enableFastPositionUpdates(aircraft);
213 }
214
215 void CSimulatedAircraftView::toggleSupportingGndFlag()
216 {
217 CSimulatedAircraft aircraft(this->selectedObject());
218 if (aircraft.getCallsign().isEmpty())
219 {
220 return;
221 }
222 aircraft.setSupportingGndFlag(!aircraft.isSupportingGndFlag());
223 this->updateAircraftSupportingGndFLag(aircraft);
224 }
225
226 void CSimulatedAircraftView::requestFollowInSimulator()
227 {
228 const CSimulatedAircraft aircraft(this->selectedObject());
229 if (aircraft.getCallsign().isEmpty())
230 {
231 return;
232 }
233 this->followAircraftInSimulator(aircraft);
234 }
235
236 void CSimulatedAircraftView::requestEnableParts()
237 {
238 const CSimulatedAircraft aircraft(this->selectedObject());
239 if (aircraft.getCallsign().isEmpty())
240 {
241 return;
242 }
243 this->enableParts(aircraft, true);
244 }
245
246 void CSimulatedAircraftView::requestDisableParts()
247 {
248 const CSimulatedAircraft aircraft(this->selectedObject());
249 if (aircraft.getCallsign().isEmpty())
250 {
251 return;
252 }
253 this->enableParts(aircraft, false);
254 }
255
256 void CSimulatedAircraftView::request0PitchOnGround()
257 {
258 const CSimulatedAircraft aircraft(this->selectedObject());
259 if (aircraft.getCallsign().isEmpty())
260 {
261 return;
262 }
263 this->setPitchOnGround(aircraft, CAngle(0, CAngleUnit::deg()));
264 }
265
266 void CSimulatedAircraftView::requestNullPitchOnGround()
267 {
268 const CSimulatedAircraft aircraft(this->selectedObject());
269 if (aircraft.getCallsign().isEmpty())
270 {
271 return;
272 }
273 this->setPitchOnGround(aircraft, CAngle::null());
274 }
275
276 void CSimulatedAircraftView::requestTempDisable()
277 {
278 if (!m_menus.testFlag(MenuDisableModelsTemp))
279 {
280 return;
281 }
282 if (!this->hasSelection())
283 {
284 return;
285 }
286 const CAircraftModelList models(this->selectedObjects().getModels());
287 emit this->requestTempDisableModelsForMatching(models);
289 u"Temp.disabled " % models.getModelStringList(true).join(" ")));
290 }
291
292 void CSimulatedAircraftView::showPositionLogInSimulator()
293 {
294 IContextSimulator *simContext = simulatorContext();
295 if (!simContext)
296 {
297 return;
298 }
299 const CSimulatedAircraft aircraft(this->selectedObject());
300 if (aircraft.getCallsign().isEmpty())
301 {
302 return;
303 }
304
305 const CIdentifier i(this->objectName());
306 const QString dotCmd(".drv pos " + aircraft.getCallsignAsString());
307 simContext->parseCommandLine(dotCmd, i);
308 }
309
310 void CSimulatedAircraftView::enableAllDisabledAircraft()
311 {
312 if (!sGui || sGui->isShuttingDown())
313 {
314 return;
315 }
316 const CSimulatedAircraftList aircraft = this->container().findByEnabled(false);
317 this->enableOrDisableAircraft(aircraft, true);
318 }
319
320 void CSimulatedAircraftView::disableAllEnabledAircraft()
321 {
322 if (!sGui || sGui->isShuttingDown())
323 {
324 return;
325 }
326 const CSimulatedAircraftList aircraft = this->container().findByEnabled(true);
327 this->enableOrDisableAircraft(aircraft, false);
328 }
329
330 void CSimulatedAircraftView::reEnableAllUnrenderedAircraft()
331 {
332 if (!sGui || sGui->isShuttingDown())
333 {
334 return;
335 }
336 const CSimulatedAircraftList aircraft = this->container().findByRendered(false);
337 this->enableOrDisableAircraft(aircraft, true);
338 }
339
340 void CSimulatedAircraftView::enableOrDisableAircraft(const CSimulatedAircraftList &aircraft, bool newEnabled)
341 {
342 if (aircraft.isEmpty())
343 {
344 return;
345 }
346
347 const QPointer<CSimulatedAircraftView> myself(this);
348 for (const CSimulatedAircraft &sa : aircraft)
349 {
350 QTimer::singleShot(10, this, [=, this] {
351 if (!myself)
352 {
353 return;
354 }
355 if (!sGui || sGui->isShuttingDown())
356 {
357 return;
358 }
359 CSimulatedAircraft enabledAircraft(sa);
360 enabledAircraft.setEnabled(newEnabled);
361 this->updateAircraftEnabled(enabledAircraft);
362 });
363 }
364 }
365
366 void CSimulatedAircraftView::followAircraftInSimulator(const CSimulatedAircraft &aircraft)
367 {
368 IContextSimulator *simContext = simulatorContext();
369 if (!simContext)
370 {
371 return;
372 }
373 simContext->followAircraft(aircraft.getCallsign());
374 }
375
376 void CSimulatedAircraftView::enableParts(const CSimulatedAircraft &aircraft, bool enabled)
377 {
378 IContextSimulator *simContext = simulatorContext();
379 if (!simContext || !aircraft.hasCallsign())
380 {
381 return;
382 }
383 CInterpolationAndRenderingSetupPerCallsign setup =
385 if (setup.isAircraftPartsEnabled() == enabled)
386 {
387 return;
388 }
390 setup.setCallsign(aircraft.getCallsign());
391 simContext->setInterpolationAndRenderingSetupsPerCallsign(setup, true);
392 }
393
394 void CSimulatedAircraftView::setPitchOnGround(const CSimulatedAircraft &aircraft,
395 const physical_quantities::CAngle &pitch)
396 {
397 IContextSimulator *simContext = simulatorContext();
398 if (!simContext || !aircraft.hasCallsign())
399 {
400 return;
401 }
402 CInterpolationAndRenderingSetupPerCallsign setup =
404 if (setup.getPitchOnGround() == pitch)
405 {
406 return;
407 }
408 setup.setPitchOnGround(pitch);
409 setup.setCallsign(aircraft.getCallsign());
410 simContext->setInterpolationAndRenderingSetupsPerCallsign(setup, true);
411 }
412
413 bool CSimulatedAircraftView::isSupportingAircraftParts(const CCallsign &cs) const
414 {
415 const IContextNetwork *netContext = networkContext();
416 if (!netContext)
417 {
418 return false;
419 }
420 return netContext->isRemoteAircraftSupportingParts(cs);
421 }
422
423 void CSimulatedAircraftView::recalculateAllAircraft()
424 {
425 IContextSimulator *simContext = simulatorContext();
426 if (!simContext)
427 {
428 return;
429 }
430 simContext->recalculateAllAircraft();
431 }
432
433 void CSimulatedAircraftView::doMatchingsAgain()
434 {
435 IContextSimulator *simContext = simulatorContext();
436 if (!simContext)
437 {
438 return;
439 }
440 const int rematchedNumber = simContext->doMatchingsAgain();
441 CLogMessage(this).info(u"Triggered re-matching of %1 aircraft") << rematchedNumber;
442 }
443
444 void CSimulatedAircraftView::doMatchingsAgainForSelected()
445 {
446 IContextSimulator *simContext = simulatorContext();
447 if (!simContext)
448 {
449 return;
450 }
451 if (!this->hasSelection())
452 {
453 return;
454 }
455 const CCallsign cs = this->selectedObject().getCallsign();
456 if (simContext->doMatchingAgain(cs))
457 {
458 CLogMessage(this).info(u"Triggered re-matching of '%1'") << cs.asString();
459 }
460 }
461
462 void CSimulatedAircraftView::enableFastPositionUpdates(const CSimulatedAircraft &aircraft)
463 {
464 IContextNetwork *nwContext = networkContext();
465 if (!nwContext)
466 {
467 return;
468 }
469 nwContext->updateFastPositionEnabled(aircraft.getCallsign(), aircraft.fastPositionUpdates());
470 }
471
472 void CSimulatedAircraftView::updateAircraftEnabled(const CSimulatedAircraft &aircraft)
473 {
474 IContextNetwork *nwContext = networkContext();
475 if (!nwContext)
476 {
477 return;
478 }
479 nwContext->updateAircraftEnabled(aircraft.getCallsign(), aircraft.isEnabled());
480 }
481
482 void CSimulatedAircraftView::updateAircraftSupportingGndFLag(const CSimulatedAircraft &aircraft)
483 {
484 IContextNetwork *nwContext = networkContext();
485 if (!nwContext)
486 {
487 return;
488 }
489 nwContext->updateAircraftSupportingGndFLag(aircraft.getCallsign(), aircraft.isSupportingGndFlag());
490 }
491
492 void CSimulatedAircraftView::showFlightPlanDialog()
493 {
494 if (!m_withMenuFlightPlan)
495 {
496 return;
497 }
498 if (!networkContext() || !networkContext()->isConnected())
499 {
500 return;
501 }
502
503 const CSimulatedAircraft aircraft = this->selectedObject();
504 if (!aircraft.hasCallsign())
505 {
506 return;
507 }
508
509 const CCallsign cs = aircraft.getCallsign();
510 if (!m_fpDialog)
511 {
512 m_fpDialog = new CFlightPlanDialog(this);
513 }
514 m_fpDialog->showFlightPlan(cs);
515 }
516
517 IContextSimulator *CSimulatedAircraftView::simulatorContext()
518 {
520 {
521 return nullptr;
522 }
523 return sGui->getIContextSimulator();
524 }
525
526 IContextNetwork *CSimulatedAircraftView::networkContext()
527 {
529 {
530 return nullptr;
531 }
532 return sGui->getIContextNetwork();
533 }
534} // namespace swift::gui::views
static CAngleUnit deg()
Degrees.
Definition units.h:276
const context::IContextNetwork * getIContextNetwork() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
virtual bool parseCommandLine(const QString &commandLine, const swift::misc::CIdentifier &originator)=0
Parse a given command line.
virtual bool updateAircraftEnabled(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)=0
Enable/disable rendering.
virtual bool updateFastPositionEnabled(const swift::misc::aviation::CCallsign &callsign, bool enableFastPositionSending)=0
Change fast position updates.
virtual bool updateAircraftSupportingGndFLag(const swift::misc::aviation::CCallsign &callsign, bool supportGndFlag)=0
Enable/disable support of gnd. flag.
virtual bool isRemoteAircraftSupportingParts(const swift::misc::aviation::CCallsign &callsign) const =0
Parts supported?
virtual bool doMatchingAgain(const swift::misc::aviation::CCallsign &callsign)=0
Repeat the matching callsign.
virtual void recalculateAllAircraft()=0
Recalculate all aircraft.
virtual bool setInterpolationAndRenderingSetupsPerCallsign(const swift::misc::simulation::CInterpolationSetupList &setups, bool ignoreSameAsGlobal)=0
Set all setups per callsign.
virtual int doMatchingsAgain()=0
Repeat all matchings.
virtual swift::misc::simulation::CInterpolationAndRenderingSetupPerCallsign getInterpolationAndRenderingSetupPerCallsignOrDefault(const swift::misc::aviation::CCallsign &callsign) const =0
Get the setup for callsign, if not existing the global setup.
virtual bool followAircraft(const swift::misc::aviation::CCallsign &callsign)=0
Follow aircraft im simulator view.
bool displayInStatusBar(const swift::misc::CStatusMessage &message)
direct access to main application window
static const QString & pathClientFollowInSim()
Client follow in simulator.
Definition menuaction.h:223
static const QString & pathClientSimulationRender()
Client simulation/display related.
Definition menuaction.h:244
static const QString & pathClientSimulationTransfer()
Client simulation/display related.
Definition menuaction.h:251
static const QString & pathClientCom()
Client COM related.
Definition menuaction.h:209
static const QString & pathClientFlightPlan()
Client flight plan.
Definition menuaction.h:216
static const QString & pathClientSimulationDisplay()
Client simulation/display related.
Definition menuaction.h:237
Bunch of CMenuAction objects.
Definition menuaction.h:384
void addSeparator(const QString &path)
Add a separator.
CMenuAction addMenuDisplayModels()
Add display model menu.
CMenuAction addMenuCom()
Add COM model menu.
CMenuAction addAction(const CMenuAction &menuAction)
Add menu action.
CMenuAction addMenuRenderModels()
Add render model menu.
CMenuAction addMenuDataTransfer()
Add data transfer menu.
void customMenu(menus::CMenuActions &menuActions)
Method creating the menu.
void setAircraftMode(models::CSimulatedAircraftListModel::AircraftMode mode)
Mode.
CSimulatedAircraftView(QWidget *parent=nullptr)
Constructor.
void requestTextMessageWidget(const swift::misc::aviation::CCallsign &callsign)
Request a text message.
void requestTempDisableModelsForMatching(const swift::misc::simulation::CAircraftModelList &models)
Disable for matching.
void configureMenuFastPositionUpdates(bool menuFastPositionUpdates)
Configure fast position updates menu.
void configureMenu(bool menuRecalculate, bool menuHighlightAndFollow, bool menuEnableAircraft, bool menuFastPositionUpdates, bool menuGndFlag, bool menuFlightPlan)
Configure the menu.
void customMenu(menus::CMenuActions &menuActions)
Method creating the menu.
Definition viewbase.cpp:785
Menu m_menus
Default menu settings.
Definition viewbase.h:603
@ MenuRefresh
allow refreshing the view via menu
Definition viewbase.h:122
bool hasSelection() const
Selection (selected rows).
static const QPixmap & globe16()
Globe.
static const QPixmap & geoPosition16()
Geo position.
static const QPixmap & appAircraft16()
Application aircrafts.
static const QPixmap & appSimulator16()
Application simulator.
static const QPixmap & appFlightPlan16()
Application flight plan.
static const QPixmap & delete16()
Delete.
static const QPixmap & appTextMessages16()
Application text messages.
static const QPixmap & appInterpolation16()
Application interpolation.
bool isEmpty() const
Synonym for empty.
Definition sequence.h:285
static constexpr auto SeverityInfo
Status severities.
const QString & asString() const
Get callsign (normalized).
Definition callsign.h:96
bool isEmpty() const
Is empty?
Definition callsign.h:63
const physical_quantities::CAngle & getPitchOnGround() const
Force a given pitch on ground.
bool setPitchOnGround(const physical_quantities::CAngle &pitchOnGround)
Force a given pitch on ground.
bool setEnabledAircraftParts(bool enabled)
Set enabled aircraft parts.
bool isAircraftPartsEnabled() const
Aircraft parts enabled (still requires the other aircraft to send parts).
void setCallsign(const aviation::CCallsign &callsign)
Set callsign.
Comprehensive information of an aircraft.
bool isPartsSynchronized() const
Have parts been synchronized with a remote client?
bool isSupportingGndFlag() const
Is supporting gnd.flag?
bool fastPositionUpdates() const
Support fast position updates.
const aviation::CCallsign & getCallsign() const
Get callsign.
bool hasCallsign() const
Callsign not empty, no further checks.
bool isEnabled() const
Enabled? Enable means it shall be displayed in the simulator.
Q_REQUIRED_RESULT CSimulatedAircraftList findByRendered(bool rendered) const
Rendered / not rendered aircraft.
Q_REQUIRED_RESULT CSimulatedAircraftList findByEnabled(bool enabled) const
Enabled / disabled aircraft.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Models to be used with views, mainly QTableView.
Views, mainly QTableView.
Free functions in swift::misc.
QObject * parent() const const