swift
rawfsdmessagescomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2018 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QDir>
7 #include <QFileDialog>
8 #include <QStringList>
9 #include <QtGlobal>
10 
11 #include "ui_rawfsdmessagescomponent.h"
12 
14 #include "gui/guiapplication.h"
15 #include "misc/directoryutils.h"
16 
17 using namespace swift::misc;
18 using namespace swift::misc::network;
19 using namespace swift::core;
20 using namespace swift::core::vatsim;
21 
22 namespace swift::gui::components
23 {
24  CRawFsdMessagesComponent::CRawFsdMessagesComponent(QWidget *parent)
25  : QFrame(parent), ui(new Ui::CRawFsdMessagesComponent)
26  {
27  ui->setupUi(this);
28  ui->cb_FileWritingMode->addItem(QApplication::translate("CRawFsdMessagesComponent", "None", nullptr),
29  QVariant::fromValue(CRawFsdMessageSettings::None));
30  ui->cb_FileWritingMode->addItem(QApplication::translate("CRawFsdMessagesComponent", "Truncate", nullptr),
31  QVariant::fromValue(CRawFsdMessageSettings::Truncate));
32  ui->cb_FileWritingMode->addItem(QApplication::translate("CRawFsdMessagesComponent", "Append", nullptr),
33  QVariant::fromValue(CRawFsdMessageSettings::Append));
34  ui->cb_FileWritingMode->addItem(QApplication::translate("CRawFsdMessagesComponent", "Timestamped", nullptr),
35  QVariant::fromValue(CRawFsdMessageSettings::Timestamped));
36 
37  ui->cb_FilterPacketType->addItem("");
38  ui->cb_FilterPacketType->addItems(CRawFsdMessage::getAllPacketTypes());
39  ui->pte_RawFsdMessages->setMaximumBlockCount(m_maxDisplayedMessages);
40  ui->le_MaxDisplayedMessages->setText(QString::number(m_maxDisplayedMessages));
41 
42  setupConnections();
43  expandFilters(false);
44  expandWritingToFile(false);
45  }
46 
48 
49  void CRawFsdMessagesComponent::setupConnections()
50  {
51 
52  connect(ui->le_FilterText, &QLineEdit::returnPressed, this, &CRawFsdMessagesComponent::changeStringFilter);
53  connect(ui->cb_FilterPacketType, &QComboBox::currentTextChanged, this,
54  &CRawFsdMessagesComponent::changePacketTypeFilter);
55  connect(ui->gb_Filter, &QGroupBox::toggled, this, &CRawFsdMessagesComponent::expandFilters);
56  connect(ui->gb_WriteToFile, &QGroupBox::toggled, this, &CRawFsdMessagesComponent::expandWritingToFile);
57  connect(ui->pb_SelectFileDir, &QPushButton::clicked, this, &CRawFsdMessagesComponent::selectFileDir);
58  connect(ui->le_MaxDisplayedMessages, &QLineEdit::returnPressed, this,
59  &CRawFsdMessagesComponent::changeMaxDisplayedMessages);
60  connect(ui->pb_EnableDisable, &QPushButton::clicked, this,
61  &CRawFsdMessagesComponent::enableDisableRawFsdMessages);
62  connect(ui->pb_ClearMessages, &QPushButton::clicked, this, &CRawFsdMessagesComponent::clearAllMessages);
63 
64  QValidator *validator = new QIntValidator(10, 200, this);
65  ui->le_MaxDisplayedMessages->setValidator(validator);
66 
67  using namespace std::placeholders;
68  QMetaObject::Connection c = sGui->getIContextNetwork()->connectRawFsdMessageSignal(
69  this, std::bind(&CRawFsdMessagesComponent::addFsdMessage, this, _1));
70  if (!c)
71  {
72  ui->pte_RawFsdMessages->appendPlainText(QStringLiteral("Could not connect to raw FSD message."));
73  ui->pte_RawFsdMessages->appendPlainText(
74  QStringLiteral("This is most likely because core is not running in this process."));
75  ui->pte_RawFsdMessages->appendPlainText(
76  QStringLiteral("Open this component again from the process running core."));
77  return;
78  }
79  m_signalConnections.append(c);
80 
81  readSettings();
82  // Connect them after settings are read. Otherwise they get called.
83  connect(ui->cb_FileWritingMode, qOverload<int>(&QComboBox::currentIndexChanged), this,
84  &CRawFsdMessagesComponent::changeFileWritingMode);
85  }
86 
87  void CRawFsdMessagesComponent::enableDisableRawFsdMessages()
88  {
90  bool enable;
91  if (ui->pb_EnableDisable->text() == "Enable")
92  {
93  enable = true;
94  ui->pb_EnableDisable->setText("Disable");
95  ui->lbl_EnabledDisabled->setText("Enabled (Display + File)");
96  ui->lbl_EnabledDisabled->setStyleSheet("background: green;");
97  }
98  else
99  {
100  enable = false;
101  ui->pb_EnableDisable->setText("Enable");
102  ui->lbl_EnabledDisabled->setText("Disabled (Display + File)");
103  ui->lbl_EnabledDisabled->setStyleSheet("background: darkred;");
104  }
105  m_setting.setProperty(vatsim::CRawFsdMessageSettings::IndexRawFsdMessagesEnabled, CVariant::fromValue(enable));
106  }
107 
108  void CRawFsdMessagesComponent::expandFilters(bool expand)
109  {
110  if (expand)
111  {
112  ui->gl_Filters->setHorizontalSpacing(7);
113  ui->gl_Filters->setVerticalSpacing(7);
114  ui->gl_Filters->setContentsMargins(11, 11, 11, 11);
115  }
116  else
117  {
118  ui->gl_Filters->setHorizontalSpacing(0);
119  ui->gl_Filters->setVerticalSpacing(0);
120  ui->gl_Filters->setContentsMargins(0, 0, 0, 0);
121  }
122 
123  for (int idx = 0; idx < ui->gl_Filters->count(); idx++)
124  {
125  QLayoutItem *const item = ui->gl_Filters->itemAt(idx);
126  if (item->widget()) { item->widget()->setVisible(expand); }
127  }
128  }
129 
130  void CRawFsdMessagesComponent::expandWritingToFile(bool expand)
131  {
132  if (expand)
133  {
134  ui->gl_WriteToFile->setHorizontalSpacing(7);
135  ui->gl_WriteToFile->setVerticalSpacing(7);
136  ui->gl_WriteToFile->setContentsMargins(11, 11, 11, 11);
137  }
138  else
139  {
140  ui->gl_WriteToFile->setHorizontalSpacing(0);
141  ui->gl_WriteToFile->setVerticalSpacing(0);
142  ui->gl_WriteToFile->setContentsMargins(0, 0, 0, 0);
143  }
144 
145  for (int idx = 0; idx < ui->gl_WriteToFile->count(); idx++)
146  {
147  QLayoutItem *const item = ui->gl_WriteToFile->itemAt(idx);
148  if (item->widget()) { item->widget()->setVisible(expand); }
149  }
150  }
151 
152  void CRawFsdMessagesComponent::changeStringFilter()
153  {
154  m_filterString = ui->le_FilterText->text();
155  filterDisplayedMessages();
156  }
157 
158  void CRawFsdMessagesComponent::changePacketTypeFilter(const QString &type)
159  {
160  m_filterPacketType = type;
161  filterDisplayedMessages();
162  }
163 
164  void CRawFsdMessagesComponent::changeMaxDisplayedMessages()
165  {
166  int maxDisplayedMessages = 0;
167  bool ok = false;
168  maxDisplayedMessages = ui->le_MaxDisplayedMessages->text().toInt(&ok);
169  if (ok)
170  {
171  m_maxDisplayedMessages = maxDisplayedMessages;
172  filterDisplayedMessages();
173  }
174  }
175 
176  void CRawFsdMessagesComponent::filterDisplayedMessages()
177  {
178  CRawFsdMessageList filtered = m_buffer;
179  if (!m_filterString.isEmpty()) { filtered = filtered.findByContainsString(m_filterString); }
180  if (!m_filterPacketType.isEmpty()) { filtered = filtered.findByPacketType(m_filterPacketType); }
181  ui->pte_RawFsdMessages->clear();
182  // Append only the last messages up to maximum display size. Erase everything before.
183  filtered.erase(filtered.begin(), filtered.end() - std::min(filtered.size(), m_maxDisplayedMessages));
184  for (const CRawFsdMessage &rawFsdMessage : filtered)
185  {
186  ui->pte_RawFsdMessages->appendPlainText(rawFsdMessageToString(rawFsdMessage));
187  }
188  }
189 
190  void CRawFsdMessagesComponent::selectFileDir()
191  {
192  QString fileDir = ui->le_FileDir->text();
193  fileDir = QFileDialog::getExistingDirectory(this, tr("Select File Directory"), fileDir);
194  if (fileDir.isEmpty()) { return; }
195  ui->le_FileDir->setText(fileDir);
196  m_setting.setProperty(vatsim::CRawFsdMessageSettings::IndexFileDir, CVariant::fromValue(fileDir));
197  }
198 
199  void CRawFsdMessagesComponent::changeFileWritingMode()
200  {
202  ui->cb_FileWritingMode->currentData().value<CRawFsdMessageSettings::FileWriteMode>();
203  m_setting.setProperty(vatsim::CRawFsdMessageSettings::IndexFileWriteMode, CVariant::fromValue(mode));
204  }
205 
206  void CRawFsdMessagesComponent::addFsdMessage(const CRawFsdMessage &rawFsdMessage)
207  {
208  if (m_buffer.size() == m_maxDisplayedMessages) { m_buffer.pop_front(); }
209  m_buffer.push_backMaxElements(rawFsdMessage, m_maxDisplayedMessages);
210 
211  if (!m_filterPacketType.isEmpty() && !rawFsdMessage.isPacketType(m_filterPacketType)) { return; }
212  if (!m_filterString.isEmpty() && !rawFsdMessage.containsString(m_filterString)) { return; }
213  ui->pte_RawFsdMessages->appendPlainText(rawFsdMessageToString(rawFsdMessage));
214  }
215 
216  void CRawFsdMessagesComponent::clearAllMessages()
217  {
218  ui->pte_RawFsdMessages->clear();
219  m_buffer.clear();
220  }
221 
222  void CRawFsdMessagesComponent::readSettings()
223  {
224  const vatsim::CRawFsdMessageSettings setting = m_setting.get();
225  const bool enable = setting.areRawFsdMessagesEnabled();
226  if (enable)
227  {
228  ui->pb_EnableDisable->setText("Disable");
229  ui->lbl_EnabledDisabled->setText("Enabled (Display + File)");
230  ui->lbl_EnabledDisabled->setStyleSheet("background: green;");
231  }
232  else
233  {
234  ui->pb_EnableDisable->setText("Enable");
235  ui->lbl_EnabledDisabled->setText("Disabled (Display + File)");
236  ui->lbl_EnabledDisabled->setStyleSheet("background: darkred;");
237  }
238  ui->le_FileDir->setText(setting.getFileDir());
240  ui->cb_FileWritingMode->setCurrentIndex(static_cast<int>(mode));
241  }
242 
243  QString CRawFsdMessagesComponent::rawFsdMessageToString(const CRawFsdMessage &rawFsdMessage)
244  {
245  return QStringLiteral("%1 %2").arg(rawFsdMessage.getFormattedUtcTimestampHmsz(), rawFsdMessage.getRawMessage());
246  }
247 } // namespace swift::gui::components
const context::IContextNetwork * getIContextNetwork() const
Direct access to contexts if a CCoreFacade has been initialized.
virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot)=0
Connect to receive raw fsd messages.
QString getFileDir() const
Get file directory.
FileWriteMode getFileWriteMode() const
Get file write mode.
bool areRawFsdMessagesEnabled() const
Are raw FSD messages enabled?
CStatusMessage setProperty(CPropertyIndexRef index, const CVariant &value, qint64 timestamp=0)
Write a property of the value. Must be called from the thread in which the owner lives.
Definition: valuecache.h:426
T get() const
Get a copy of the current value.
Definition: valuecache.h:408
iterator erase(iterator pos)
Remove the element pointed to by the given iterator.
Definition: sequence.h:382
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
iterator begin()
Returns iterator at the beginning of the sequence.
Definition: sequence.h:163
void clear()
Removes all elements in the sequence.
Definition: sequence.h:288
void push_backMaxElements(const T &value, int maxElements)
Insert as last element by keep maxElements.
Definition: sequence.h:322
iterator end()
Returns iterator one past the end of the sequence.
Definition: sequence.h:172
void pop_front()
Removes an element at the front of the sequence.
Definition: sequence.h:374
QString getFormattedUtcTimestampHmsz() const
As hh:mm:ss.zzz.
Value object for a raw FSD message.
Definition: rawfsdmessage.h:25
bool containsString(const QString &str) const
Does the raw message contain str?
const QString & getRawMessage() const
Get raw message.
Definition: rawfsdmessage.h:40
bool isPacketType(const QString &type) const
Returns true if the raw message is from the given PDU packet type.
Value object encapsulating a list raw FSD messages.
CRawFsdMessageList findByPacketType(const QString &type) const
Find by a given list of raw messages which are type.
CRawFsdMessageList findByContainsString(const QString &str) const
Find by a given list of models by strings.
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.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:13
Free functions in swift::misc.