swift
cockpitcomform.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 
4 #include "cockpitcomform.h"
5 
6 #include <QPushButton>
7 
8 #include "ui_cockpitcomform.h"
9 
11 #include "gui/guiapplication.h"
12 #include "misc/icons.h"
13 #include "misc/logmessage.h"
14 #include "misc/math/mathutils.h"
15 
16 using namespace swift::misc;
17 using namespace swift::misc::aviation;
18 using namespace swift::misc::audio;
19 using namespace swift::misc::physical_quantities;
20 using namespace swift::misc::math;
21 using namespace swift::misc::simulation;
22 using namespace swift::core::context;
23 using namespace swift::gui::components;
24 
25 namespace swift::gui::editors
26 {
27  CCockpitComForm::CCockpitComForm(QWidget *parent) : CForm(parent), ui(new Ui::CCockpitComForm)
28  {
29  ui->setupUi(this);
30  this->alignUiElementsHeight();
31 
32  // SELCAL pairs in cockpit
33  ui->frp_ComPanelSelcalSelector->clear();
34  connect(ui->tb_ComPanelSelcalTest, &QPushButton::clicked, this, &CCockpitComForm::testSelcal);
35  connect(ui->frp_ComPanelSelcalSelector, &CSelcalCodeSelector::valueChanged, this,
36  &CCockpitComForm::onSelcalChanged);
37 
38  // XPDR
39  connect(ui->cbp_ComPanelTransponderMode, &CTransponderModeSelector::transponderModeChanged, this,
41  connect(ui->cbp_ComPanelTransponderMode, &CTransponderModeSelector::transponderStateIdentEnded, this,
43 
44  // COM GUI events
45  connect(ui->tb_ComPanelCom1Toggle, &QPushButton::clicked, this, &CCockpitComForm::onGuiChangedCockpitValues);
46  connect(ui->tb_ComPanelCom2Toggle, &QPushButton::clicked, this, &CCockpitComForm::onGuiChangedCockpitValues);
47  connect(ui->ds_ComPanelCom1Active, &QDoubleSpinBox::editingFinished, this,
48  &CCockpitComForm::onGuiChangedCockpitValues);
49  connect(ui->ds_ComPanelCom2Active, &QDoubleSpinBox::editingFinished, this,
50  &CCockpitComForm::onGuiChangedCockpitValues);
51  connect(ui->ds_ComPanelCom1Standby, &QDoubleSpinBox::editingFinished, this,
52  &CCockpitComForm::onGuiChangedCockpitValues);
53  connect(ui->ds_ComPanelCom2Standby, &QDoubleSpinBox::editingFinished, this,
54  &CCockpitComForm::onGuiChangedCockpitValues);
55  connect(ui->sbp_ComPanelTransponder, &QDoubleSpinBox::editingFinished, this,
56  &CCockpitComForm::onGuiChangedCockpitValues);
57  connect(ui->cbp_ComPanelTransponderMode, &CTransponderModeSelector::transponderModeChanged, this,
58  &CCockpitComForm::onGuiChangedCockpitValues);
59  connect(ui->frp_ComPanelSelcalSelector, &CSelcalCodeSelector::valueChanged, this,
60  &CCockpitComForm::onGuiChangedCockpitValues);
61  connect(ui->tb_RequestTextMessageCom1, &QToolButton::released, this, &CCockpitComForm::requestCom1TextMessage);
62  connect(ui->tb_RequestTextMessageCom2, &QToolButton::released, this, &CCockpitComForm::requestCom2TextMessage);
63 
64  ui->tb_RequestTextMessageCom1->setIcon(CIcons::appTextMessages16());
65  ui->tb_RequestTextMessageCom2->setIcon(CIcons::appTextMessages16());
66 
67  this->initLeds();
68  }
69 
71 
72  void CCockpitComForm::setReadOnly(bool readonly)
73  {
74  ui->ds_ComPanelCom1Active->setReadOnly(readonly);
75  ui->ds_ComPanelCom2Active->setReadOnly(readonly);
76  ui->ds_ComPanelCom1Standby->setReadOnly(readonly);
77  ui->ds_ComPanelCom2Standby->setReadOnly(readonly);
78  ui->cbp_ComPanelTransponderMode->setDisabled(!readonly);
79  ui->tb_ComPanelCom1Toggle->setEnabled(!readonly);
80  ui->tb_ComPanelCom2Toggle->setEnabled(!readonly);
81  this->forceStyleSheetUpdate();
82  }
83 
85 
87  {
88  Q_UNUSED(nested)
89  CStatusMessageList msgs;
90  return msgs;
91  }
92 
94  {
95  ui->cbp_ComPanelTransponderMode->setSelectedTransponderModeStateIdent();
96  }
97 
99  {
100  this->setFrequencies(aircraft.getCom1System(), aircraft.getCom2System());
101  this->setSelcal(aircraft.getSelcal());
102  this->setTransponder(aircraft.getTransponder());
103  this->alignUiElementsHeight();
104  this->updateIntegratedFlagFromSimulatorContext();
105  }
106 
107  CSelcal CCockpitComForm::getSelcal() const { return ui->frp_ComPanelSelcalSelector->getSelcal(); }
108 
109  void CCockpitComForm::setSelcal(const CSelcal &selcal) { ui->frp_ComPanelSelcalSelector->setSelcal(selcal); }
110 
111  void CCockpitComForm::initLeds()
112  {
113  const CLedWidget::LedShape shape = CLedWidget::Rounded;
114 
115  ui->led_ComPanelCom1R->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "COM1 receive (sim)",
116  "COM1 not receiving", 14);
117  ui->led_ComPanelCom1T->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "COM1 transmit (sim)",
118  "COM1 not transmitting", 14);
119  ui->led_ComPanelCom1R->setTriStateValues(CLedWidget::Blue, "receive not synced");
120  ui->led_ComPanelCom1T->setTriStateValues(CLedWidget::Blue, "transmit not synced");
121 
122  ui->led_ComPanelCom2R->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "COM2 receive (sim)",
123  "COM2 not receiving", 14);
124  ui->led_ComPanelCom2T->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "COM2 transmit (sim)",
125  "COM2 not transmitting", 14);
126  ui->led_ComPanelCom2R->setTriStateValues(CLedWidget::Blue, "receive not synced");
127  ui->led_ComPanelCom2T->setTriStateValues(CLedWidget::Blue, "transmit not synced");
128  }
129 
130  CSimulatedAircraft CCockpitComForm::cockpitValuesToAircraftObject()
131  {
132  CSimulatedAircraft comAircraft;
133  CTransponder transponder = comAircraft.getTransponder();
134  CComSystem com1 = comAircraft.getCom1System();
135  CComSystem com2 = comAircraft.getCom2System();
136 
137  //
138  // Transponder
139  //
140  const QString transponderCode = QString::number(ui->sbp_ComPanelTransponder->value());
141  if (CTransponder::isValidTransponderCode(transponderCode)) { transponder.setTransponderCode(transponderCode); }
142  else
143  {
144  CLogMessage(this).validationWarning(u"Wrong transponder code, reset");
145  ui->sbp_ComPanelTransponder->setValue(transponder.getTransponderCode());
146  }
147  transponder.setTransponderMode(ui->cbp_ComPanelTransponderMode->getSelectedTransponderMode());
148 
149  //
150  // COM units
151  //
152  com1.setFrequencyActiveMHz(ui->ds_ComPanelCom1Active->value());
153  com1.setFrequencyStandbyMHz(ui->ds_ComPanelCom1Standby->value());
154  com2.setFrequencyActiveMHz(ui->ds_ComPanelCom2Active->value());
155  com2.setFrequencyStandbyMHz(ui->ds_ComPanelCom2Standby->value());
156  this->setFrequencies(com1, com2); // back annotation after rounding
157 
158  comAircraft.setCom1System(com1);
159  comAircraft.setCom2System(com2);
160  comAircraft.setTransponder(transponder);
161  return comAircraft;
162  }
163 
165  {
166  double freq = com1.getFrequencyActive().valueRounded(CFrequencyUnit::MHz(), 3);
167  if (!isFrequenceEqual(freq, ui->ds_ComPanelCom1Active->value())) { ui->ds_ComPanelCom1Active->setValue(freq); }
168 
169  freq = com2.getFrequencyActive().valueRounded(CFrequencyUnit::MHz(), 3);
170  if (!isFrequenceEqual(freq, ui->ds_ComPanelCom2Active->value())) { ui->ds_ComPanelCom2Active->setValue(freq); }
171 
172  freq = com1.getFrequencyStandby().valueRounded(CFrequencyUnit::MHz(), 3);
173  if (!isFrequenceEqual(freq, ui->ds_ComPanelCom1Standby->value()))
174  {
175  ui->ds_ComPanelCom1Standby->setValue(freq);
176  }
177 
178  freq = com2.getFrequencyStandby().valueRounded(CFrequencyUnit::MHz(), 3);
179  if (!isFrequenceEqual(freq, ui->ds_ComPanelCom2Standby->value()))
180  {
181  ui->ds_ComPanelCom2Standby->setValue(freq);
182  }
183 
184  this->updateIntegratedFlagFromSimulatorContext();
185  this->updateActiveCOMUnitLEDs(m_integratedWithSim, com1.isTransmitEnabled(), com1.isReceiveEnabled(),
186  com2.isTransmitEnabled(), com2.isReceiveEnabled());
187  }
188 
190  {
191  const int tc = transponder.getTransponderCode();
192  if (tc != ui->sbp_ComPanelTransponder->value()) { ui->sbp_ComPanelTransponder->setValue(tc); }
193 
194  if (transponder.getTransponderMode() != ui->cbp_ComPanelTransponderMode->getSelectedTransponderMode())
195  {
196  ui->cbp_ComPanelTransponderMode->setSelectedTransponderMode(transponder.getTransponderMode());
197  ui->comp_TransponderLeds->setMode(transponder.getTransponderMode());
198  }
199  }
200 
201  void CCockpitComForm::onGuiChangedCockpitValues()
202  {
203  const QObject *sender = QObject::sender();
204  if (sender == ui->tb_ComPanelCom1Toggle)
205  {
206  if (isFrequenceEqual(ui->ds_ComPanelCom1Standby->value(), ui->ds_ComPanelCom1Active->value())) { return; }
207  const double f = ui->ds_ComPanelCom1Active->value();
208  ui->ds_ComPanelCom1Active->setValue(ui->ds_ComPanelCom1Standby->value());
209  ui->ds_ComPanelCom1Standby->setValue(f);
210  }
211  else if (sender == ui->tb_ComPanelCom2Toggle)
212  {
213  if (isFrequenceEqual(ui->ds_ComPanelCom2Standby->value(), ui->ds_ComPanelCom2Active->value())) { return; }
214  const double f = ui->ds_ComPanelCom2Active->value();
215  ui->ds_ComPanelCom2Active->setValue(ui->ds_ComPanelCom2Standby->value());
216  ui->ds_ComPanelCom2Standby->setValue(f);
217  }
218 
219  this->alignUiElementsHeight();
220  const CSimulatedAircraft aircraft = this->cockpitValuesToAircraftObject();
221  emit this->changedCockpitValues(aircraft);
222  }
223 
224  void CCockpitComForm::onSelcalChanged()
225  {
226  const CSelcal selcal = ui->frp_ComPanelSelcalSelector->getSelcal();
227  emit this->changedSelcal(selcal);
228  }
229 
230  void CCockpitComForm::alignUiElementsHeight()
231  {
232  const int selcalH = ui->frp_ComPanelSelcalSelector->getComboBoxHeight();
233  if (selcalH > ui->ds_ComPanelCom1Standby->height())
234  {
235  ui->ds_ComPanelCom1Standby->setMinimumHeight(selcalH);
236  ui->ds_ComPanelCom2Standby->setMinimumHeight(selcalH);
237  }
238 
239  const int xpdrH = ui->cbp_ComPanelTransponderMode->height();
240  if (xpdrH > ui->ds_ComPanelCom1Active->height())
241  {
242  ui->ds_ComPanelCom1Active->setMinimumHeight(xpdrH);
243  ui->ds_ComPanelCom2Active->setMinimumHeight(xpdrH);
244  ui->sbp_ComPanelTransponder->setMinimumHeight(xpdrH);
245  }
246  }
247 
248  void CCockpitComForm::updateActiveCOMUnitLEDs(bool integratedWithSim, bool com1T, bool com1R, bool com2T,
249  bool com2R)
250  {
251  if (!integratedWithSim)
252  {
253  ui->led_ComPanelCom1R->setTriState();
254  ui->led_ComPanelCom1T->setTriState();
255  ui->led_ComPanelCom2R->setTriState();
256  ui->led_ComPanelCom2T->setTriState();
257  }
258  else
259  {
260  ui->led_ComPanelCom1R->setOn(com1R);
261  ui->led_ComPanelCom1T->setOn(com1T);
262  ui->led_ComPanelCom2R->setOn(com2R);
263  ui->led_ComPanelCom2T->setOn(com2T);
264  }
265  }
266 
267  void CCockpitComForm::updateIntegratedFlagFromSimulatorContext()
268  {
270  {
271  m_integratedWithSim = false;
272  return;
273  }
274  const bool integrated = sGui->getIContextSimulator()->getSimulatorSettings().isComIntegrated();
275  m_integratedWithSim = integrated;
276  }
277 
278  bool CCockpitComForm::isFrequenceEqual(double f1, double f2) { return CMathUtils::epsilonEqual(f1, f2); }
279 } // namespace swift::gui::editors
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
virtual swift::misc::simulation::settings::CSimulatorSettings getSimulatorSettings() const =0
Get the current simulator settings.
LedShape
Shapes.
Definition: led.h:51
virtual void setSelectOnly()
Read only, but entity can be selected (normally used in mapping). Use setReadOnly to reset this very ...
void transponderStateIdentEnded()
Ident phase ended.
swift::misc::aviation::CSelcal getSelcal() const
Get SELCAL.
void setFrequencies(const swift::misc::aviation::CComSystem &com1, const swift::misc::aviation::CComSystem &com2)
COM frequencies displayed.
void requestCom2TextMessage()
Request COM text messages.
void requestCom1TextMessage()
Request COM text messages.
void transponderModeChanged(swift::misc::aviation::CTransponder::TransponderMode newMode)
Mode / state has been changed.
virtual swift::misc::CStatusMessageList validate(bool nested=false) const
Validate, empty list means OK.
void setTransponderModeStateIdent()
Set to swift::misc::aviation::CTransponder::StateIdent.
void changedCockpitValues(const swift::misc::simulation::CSimulatedAircraft &aircraft)
GUI values changed.
void setSelcal(const swift::misc::aviation::CSelcal &selcal)
Set SELCAL.
void setTransponder(const swift::misc::aviation::CTransponder &transponder)
Set the XPDR values.
void testSelcal()
Request to test SELCAL.
void changedSelcal(const swift::misc::aviation::CSelcal &selcal)
SELCAL value changed.
virtual void setReadOnly(bool readonly)
Set editable.
void setValue(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Set all values.
Form base class.
Definition: form.h:27
void forceStyleSheetUpdate()
Forces a stylesheet update.
Definition: form.cpp:47
Class for emitting a log message.
Definition: logmessage.h:27
Derived & validationWarning(const char16_t(&format)[N])
Set the severity to warning, providing a format string, and adding the validation category.
Status messages, e.g. from Core -> GUI.
COM system (aka "radio")
Definition: comsystem.h:37
void setFrequencyActiveMHz(double frequencyMHz)
Set active frequency.
Definition: comsystem.cpp:25
void setFrequencyStandbyMHz(double frequencyMHz)
Set standby frequency.
Definition: comsystem.cpp:31
bool isTransmitEnabled() const
Enabled?
Definition: modulator.cpp:82
swift::misc::physical_quantities::CFrequency getFrequencyStandby() const
Standby frequency.
Definition: modulator.cpp:36
bool isReceiveEnabled() const
Enabled?
Definition: modulator.cpp:88
swift::misc::physical_quantities::CFrequency getFrequencyActive() const
Active frequency.
Definition: modulator.cpp:30
Value object for SELCAL.
Definition: selcal.h:31
void setTransponderCode(int transponderCode)
Set transponder code.
Definition: transponder.h:116
int getTransponderCode() const
Transponder code.
Definition: transponder.h:107
bool setTransponderMode(TransponderMode mode)
Set transponder mode.
Definition: transponder.cpp:97
TransponderMode getTransponderMode() const
Transponder mode.
Definition: transponder.h:95
double valueRounded(MU unit, int digits=-1) const
Rounded value in given unit.
Comprehensive information of an aircraft.
const aviation::CSelcal getSelcal() const
SELCAL.
const aviation::CComSystem & getCom2System() const
Get COM2 system.
const aviation::CTransponder & getTransponder() const
Get transponder.
void setCom1System(const aviation::CComSystem &comSystem)
Set COM1 system.
void setTransponder(const aviation::CTransponder &transponder)
Set transponder.
void setCom2System(const aviation::CComSystem &comSystem)
Set COM2 system.
const aviation::CComSystem & getCom1System() const
Get COM1 system.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
High level reusable GUI components.
Definition: aboutdialog.cpp:13
Free functions in swift::misc.