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;
69  this, [this](auto &&msg) { addFsdMessage(std::forward<decltype(msg)>(msg)); });
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  {
201  const auto mode = ui->cb_FileWritingMode->currentData().value<CRawFsdMessageSettings::FileWriteMode>();
202  m_setting.setProperty(vatsim::CRawFsdMessageSettings::IndexFileWriteMode, CVariant::fromValue(mode));
203  }
204 
205  void CRawFsdMessagesComponent::addFsdMessage(const CRawFsdMessage &rawFsdMessage)
206  {
207  if (m_buffer.size() == m_maxDisplayedMessages) { m_buffer.pop_front(); }
208  m_buffer.push_backMaxElements(rawFsdMessage, m_maxDisplayedMessages);
209 
210  if (!m_filterPacketType.isEmpty() && !rawFsdMessage.isPacketType(m_filterPacketType)) { return; }
211  if (!m_filterString.isEmpty() && !rawFsdMessage.containsString(m_filterString)) { return; }
212  ui->pte_RawFsdMessages->appendPlainText(rawFsdMessageToString(rawFsdMessage));
213  }
214 
215  void CRawFsdMessagesComponent::clearAllMessages()
216  {
217  ui->pte_RawFsdMessages->clear();
218  m_buffer.clear();
219  }
220 
221  void CRawFsdMessagesComponent::readSettings()
222  {
223  const vatsim::CRawFsdMessageSettings setting = m_setting.get();
224  const bool enable = setting.areRawFsdMessagesEnabled();
225  if (enable)
226  {
227  ui->pb_EnableDisable->setText("Disable");
228  ui->lbl_EnabledDisabled->setText("Enabled (Display + File)");
229  ui->lbl_EnabledDisabled->setStyleSheet("background: green;");
230  }
231  else
232  {
233  ui->pb_EnableDisable->setText("Enable");
234  ui->lbl_EnabledDisabled->setText("Disabled (Display + File)");
235  ui->lbl_EnabledDisabled->setStyleSheet("background: darkred;");
236  }
237  ui->le_FileDir->setText(setting.getFileDir());
239  ui->cb_FileWritingMode->setCurrentIndex(static_cast<int>(mode));
240  }
241 
242  QString CRawFsdMessagesComponent::rawFsdMessageToString(const CRawFsdMessage &rawFsdMessage)
243  {
244  return QStringLiteral("%1 %2").arg(rawFsdMessage.getFormattedUtcTimestampHmsz(), rawFsdMessage.getRawMessage());
245  }
246 } // 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
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
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
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.
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:14
Free functions in swift::misc.
void clicked(bool checked)
void currentIndexChanged(int index)
void currentTextChanged(const QString &text)
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options)
void toggled(bool on)
virtual QWidget * widget() const const
void returnPressed()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QFuture< typename qValueType< Iterator >::value_type > filtered(Iterator begin, Iterator end, KeepFunctor &&filterFunction)
QVariant fromValue(T &&value)
virtual void setVisible(bool visible)