swift
internalscomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QCheckBox>
7 #include <QDateTime>
8 #include <QDesktopServices>
9 #include <QMessageBox>
10 #include <QPushButton>
11 #include <QSpinBox>
12 #include <QString>
13 #include <QTextEdit>
14 #include <Qt>
15 #include <QtGlobal>
16 
17 #include "ui_internalscomponent.h"
18 
19 #include "config/buildconfig.h"
26 #include "gui/guiapplication.h"
27 #include "gui/uppercasevalidator.h"
28 #include "misc/aviation/callsign.h"
29 #include "misc/crashhandler.h"
30 #include "misc/logmessage.h"
31 #include "misc/math/mathutils.h"
32 #include "misc/network/client.h"
36 #include "misc/statusmessage.h"
37 
38 using namespace swift::config;
39 using namespace swift::misc;
40 using namespace swift::misc::aviation;
41 using namespace swift::misc::network;
42 using namespace swift::misc::math;
43 using namespace swift::misc::physical_quantities;
44 using namespace swift::misc::simulation;
45 
46 namespace swift::gui::components
47 {
48  CInternalsComponent::CInternalsComponent(QWidget *parent) : QWidget(parent), ui(new Ui::CInternalsComponent)
49  {
50  ui->setupUi(this);
51  ui->tw_Internals->setCurrentIndex(0);
52 
53  ui->le_TxtMsgFrom->setValidator(new CUpperCaseValidator(ui->le_TxtMsgFrom));
54  ui->le_TxtMsgTo->setValidator(new CUpperCaseValidator(ui->le_TxtMsgFrom));
55  ui->le_AtisCallsign->setValidator(new CUpperCaseValidator(ui->le_AtisCallsign));
56 
57  connect(ui->cb_DebugContextAudio, &QCheckBox::checkStateChanged, this, &CInternalsComponent::enableDebug);
58  connect(ui->cb_DebugContextApplication, &QCheckBox::checkStateChanged, this, &CInternalsComponent::enableDebug);
59  connect(ui->cb_DebugContextNetwork, &QCheckBox::checkStateChanged, this, &CInternalsComponent::enableDebug);
60  connect(ui->cb_DebugContextOwnAircraft, &QCheckBox::checkStateChanged, this, &CInternalsComponent::enableDebug);
61  connect(ui->cb_DebugContextSimulator, &QCheckBox::checkStateChanged, this, &CInternalsComponent::enableDebug);
62 
63  connect(ui->pb_SendTextMessageDirectly, &QPushButton::released, this, &CInternalsComponent::sendTextMessage,
65  connect(ui->pb_SendTextMessageDeferred, &QPushButton::released, this, &CInternalsComponent::sendTextMessage,
67 
68  connect(ui->tb_LogStatusMessage, &QPushButton::released, this, &CInternalsComponent::logStatusMessage);
69  connect(ui->le_StatusMessage, &QLineEdit::returnPressed, this, &CInternalsComponent::logStatusMessage);
70 
71  connect(ui->pb_LatestInterpolationLog, &QPushButton::released, this, &CInternalsComponent::showLogFiles);
72  connect(ui->pb_LatestPartsLog, &QPushButton::released, this, &CInternalsComponent::showLogFiles);
73  connect(ui->pb_SendAtis, &QPushButton::released, this, &CInternalsComponent::sendAtis);
74 
75  connect(ui->pb_NetworkUpdateAndReset, &QPushButton::released, this, &CInternalsComponent::networkStatistics);
76  connect(ui->pb_NetworkUpdate, &QPushButton::released, this, &CInternalsComponent::networkStatistics);
77  connect(ui->cb_NetworkStatistics, &QCheckBox::checkStateChanged, this,
78  &CInternalsComponent::onNetworkStatisticsToggled);
79 
80  if (sGui && sGui->isSupportingCrashpad())
81  {
82  ui->cb_CrashDumpUpload->setChecked(CCrashHandler::instance()->isCrashDumpUploadEnabled());
83  connect(ui->pb_SimulateCrash, &QPushButton::released, this, &CInternalsComponent::simulateCrash,
85  connect(ui->pb_SimulateAssert, &QPushButton::released, this, &CInternalsComponent::simulateAssert,
87  connect(ui->cb_CrashDumpUpload, &QCheckBox::toggled, this, &CInternalsComponent::onCrashDumpUploadToggled);
88  }
89  else
90  {
91  ui->pb_SimulateCrash->setEnabled(false);
92  ui->cb_CrashDumpUpload->setEnabled(false);
93  }
94 
95  this->contextFlagsToGui();
96  }
97 
99 
101  {
102  // force new data when visible
103  this->contextFlagsToGui();
105  }
106 
107  void CInternalsComponent::enableDebug(Qt::CheckState checkState)
108  {
109  Q_ASSERT(sGui->getIContextApplication());
110  Q_ASSERT(sGui->getIContextAudio());
111  Q_ASSERT(sGui->getIContextNetwork());
112  Q_ASSERT(sGui->getIContextOwnAircraft());
113  Q_ASSERT(sGui->getIContextSimulator());
114 
115  const bool debug = (checkState == Qt::Checked);
116  const QObject *sender = QObject::sender();
117 
118  if (sender == ui->cb_DebugContextApplication) { sGui->getIContextApplication()->setDebugEnabled(debug); }
119  else if (sender == ui->cb_DebugContextAudio) { sGui->getIContextAudio()->setDebugEnabled(debug); }
120  else if (sender == ui->cb_DebugContextNetwork) { sGui->getIContextNetwork()->setDebugEnabled(debug); }
121  else if (sender == ui->cb_DebugContextOwnAircraft) { sGui->getIContextOwnAircraft()->setDebugEnabled(debug); }
122  else if (sender == ui->cb_DebugContextSimulator) { sGui->getIContextSimulator()->setDebugEnabled(debug); }
123  }
124 
125  void CInternalsComponent::sendTextMessage()
126  {
127  if (!sGui || !sGui->getIContextNetwork()) { return; }
128  if (ui->le_TxtMsgFrom->text().isEmpty()) { return; }
129  if (ui->pte_TxtMsg->toPlainText().isEmpty()) { return; }
130  if (ui->le_TxtMsgTo->text().isEmpty() && ui->dsb_TxtMsgFrequency->text().isEmpty()) { return; }
131 
132  // send in some time
133  const QObject *senderObj = QObject::sender();
134  if (senderObj == ui->pb_SendTextMessageDeferred)
135  {
136  QTimer::singleShot(5000, this, &CInternalsComponent::sendTextMessage);
137  return;
138  }
139 
140  const CCallsign sender(ui->le_TxtMsgFrom->text().trimmed());
141  const CCallsign recipient(ui->le_TxtMsgTo->text().trimmed());
142  const QString msgTxt(ui->pte_TxtMsg->toPlainText().trimmed());
143  const double freqMHz = CMathUtils::round(ui->dsb_TxtMsgFrequency->value(), 3);
144  CTextMessage tm;
145  if (recipient.isEmpty() && freqMHz >= 117.995) // 118.000 actually plus epsilon
146  {
147  // remark: the internal double value can be still something like 127.999997
148  CFrequency f = CFrequency(freqMHz, CFrequencyUnit::MHz());
149  CComSystem::roundToChannelSpacing(f, CComSystem::ChannelSpacing8_33KHz);
150  tm = CTextMessage(msgTxt, f, sender);
151  }
152  else { tm = CTextMessage(msgTxt, sender, recipient); }
153  tm.setCurrentUtcTime();
155  }
156 
157  void CInternalsComponent::sendAtis()
158  {
159  if (!sGui || !sGui->getIContextNetwork()) { return; }
160  if (ui->le_AtisCallsign->text().isEmpty()) { return; }
161  if (ui->pte_Atis->toPlainText().isEmpty()) { return; }
162  const CCallsign cs(ui->le_AtisCallsign->text());
163  const QString text(ui->pte_Atis->toPlainText());
164 
165  const CInformationMessage im(CInformationMessage::ATIS, text);
167  }
168 
169  void CInternalsComponent::logStatusMessage()
170  {
171  if (ui->le_StatusMessage->text().isEmpty()) { return; }
172  CStatusMessage::StatusSeverity s = CStatusMessage::SeverityDebug;
173  if (ui->rb_StatusMessageError->isChecked()) { s = CStatusMessage::SeverityError; }
174  else if (ui->rb_StatusMessageWarning->isChecked()) { s = CStatusMessage::SeverityWarning; }
175  else if (ui->rb_StatusMessageInfo->isChecked()) { s = CStatusMessage::SeverityInfo; }
176  const CStatusMessage sm = CStatusMessage(this, s, ui->le_StatusMessage->text().trimmed());
177  CLogMessage::preformatted(sm);
178  }
179 
180  void CInternalsComponent::showLogFiles()
181  {
182  QString file;
183  const QObject *sender = QObject::sender();
184  if (sender == ui->pb_LatestInterpolationLog) { file = CInterpolationLogger::getLatestLogFiles().first(); }
185  else if (sender == ui->pb_LatestPartsLog) { file = CInterpolationLogger::getLatestLogFiles().last(); }
186 
187  if (file.isEmpty()) { return; }
189  }
190 
191  void CInternalsComponent::contextFlagsToGui()
192  {
193  ui->cb_DebugContextApplication->setChecked(sGui->getIContextApplication()->isDebugEnabled());
194  ui->cb_DebugContextNetwork->setChecked(sGui->getIContextNetwork()->isDebugEnabled());
195  ui->cb_DebugContextOwnAircraft->setChecked(sGui->getIContextOwnAircraft()->isDebugEnabled());
196  ui->cb_DebugContextSimulator->setChecked(sGui->getIContextSimulator()->isDebugEnabled());
197  }
198 
199  void CInternalsComponent::simulateCrash()
200  {
201  if (CBuildConfig::isReleaseBuild())
202  {
203  QMessageBox::information(this, "crash simulation", "Not possible in release builds!");
204  return;
205  }
206 
208  this, "crash simulation", "Really simulate crash?", QMessageBox::Yes | QMessageBox::No);
209  if (!sGui || reply != QMessageBox::Yes) { return; }
210  sGui->simulateCrash();
211  }
212 
213  void CInternalsComponent::simulateAssert()
214  {
215  if (CBuildConfig::isReleaseBuild())
216  {
217  QMessageBox::information(this, "ASSERT simulation", "Not possible in release builds!");
218  return;
219  }
220 
222  this, "ASSERT simulation", "Really create an ASSERT?", QMessageBox::Yes | QMessageBox::No);
223  if (!sGui || reply != QMessageBox::Yes) { return; }
224  sGui->simulateAssert();
225  }
226 
227  void CInternalsComponent::onCrashDumpUploadToggled(bool checked)
228  {
229  if (sGui && sGui->isSupportingCrashpad())
230  {
231  const bool current = CCrashHandler::instance()->isCrashDumpUploadEnabled();
232  if (current == checked) { return; }
233  sGui->enableCrashDumpUpload(checked);
234  }
235  }
236 
237  void CInternalsComponent::networkStatistics()
238  {
239  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextNetwork()) { return; }
240  const bool reset = (QObject::sender() == ui->pb_NetworkUpdateAndReset);
241  const QString statistics = sGui->getIContextNetwork()->getNetworkStatistics(reset, "\n");
242  ui->pte_NetworkCalls->setPlainText(statistics);
243  }
244 
245  void CInternalsComponent::onNetworkStatisticsToggled(bool checked)
246  {
247  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextNetwork()) { return; }
248  const bool on = sGui->getIContextNetwork()->setNetworkStatisticsEnable(checked);
249  CLogMessage(this).info(u"Network statistics is %1") << boolToOnOff(on);
250  }
251 } // namespace swift::gui::components
const context::IContextAudio * getIContextAudio() const
Direct access to contexts if a CCoreFacade has been initialized.
const context::IContextOwnAircraft * getIContextOwnAircraft() const
Direct access to contexts if a CCoreFacade has been initialized.
const context::IContextApplication * getIContextApplication() const
Direct access to contexts if a CCoreFacade has been initialized.
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.
void enableCrashDumpUpload(bool enable)
Enable crash upload.
bool isSupportingCrashpad() const
Has crashpad support?
void setDebugEnabled(bool debug)
Set debug flag.
Definition: context.cpp:53
bool isDebugEnabled() const
Debug enabled?
Definition: context.cpp:59
virtual QString getNetworkStatistics(bool reset, const QString &separator)=0
Statistics info.
virtual void testReceivedTextMessages(const swift::misc::network::CTextMessageList &textMessages)=0
Inject a text message as received.
virtual void testReceivedAtisMessage(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CInformationMessage &msg)=0
Inject an ATIS.
virtual bool setNetworkStatisticsEnable(bool enabled)=0
Statistics enable/disable.
Internals for debugging, statistics.
Class for emitting a log message.
Definition: logmessage.h:27
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Streamable status message, e.g.
void setCurrentUtcTime()
Set the current time as timestamp.
Value object encapsulating information of a callsign.
Definition: callsign.h:30
Value object encapsulating information message (ATIS, METAR, TAF)
Value object encapsulating information of a text message.
Definition: textmessage.h:31
Value object encapsulating a list of text messages.
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.
SWIFT_MISC_EXPORT const QString & boolToOnOff(bool v)
Bool to on/off.
StatusSeverity
Status severities.
Definition: statusmessage.h:35
void toggled(bool checked)
void checkStateChanged(Qt::CheckState state)
bool openUrl(const QUrl &url)
void returnPressed()
QMessageBox::StandardButton information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * sender() const const
QString first(qsizetype n) &&
bool isEmpty() const const
QString last(qsizetype n) &&
CheckState
QueuedConnection
QTextStream & reset(QTextStream &stream)
QUrl fromLocalFile(const QString &localFile)
virtual bool event(QEvent *event) override
virtual void showEvent(QShowEvent *event)