SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
remoteinputgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2016 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include <stdint.h>
19 #include <sstream>
20 #include <iostream>
21 #include <cassert>
22 
23 #include <QDebug>
24 #include <QMessageBox>
25 #include <QTime>
26 #include <QDateTime>
27 #include <QString>
28 #include <QNetworkAccessManager>
29 #include <QNetworkReply>
30 #include <QJsonParseError>
31 #include <QJsonObject>
32 
33 #include "ui_remoteinputgui.h"
34 #include "gui/colormapper.h"
35 #include "gui/glspectrum.h"
36 #include "gui/crightclickenabler.h"
38 #include "dsp/dspengine.h"
39 #include "dsp/dspcommands.h"
40 #include "mainwindow.h"
41 #include "util/simpleserializer.h"
42 #include "device/deviceapi.h"
43 #include "device/deviceuiset.h"
44 #include "remoteinputgui.h"
45 
46 
47 RemoteInputGui::RemoteInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
48  QWidget(parent),
49  ui(new Ui::RemoteInputGui),
50  m_deviceUISet(deviceUISet),
51  m_settings(),
52  m_sampleSource(0),
53  m_acquisition(false),
54  m_streamSampleRate(0),
55  m_streamCenterFrequency(0),
56  m_lastEngineState(DeviceAPI::StNotStarted),
57  m_framesDecodingStatus(0),
58  m_bufferLengthInSecs(0.0),
59  m_bufferGauge(-50),
60  m_nbOriginalBlocks(128),
61  m_nbFECBlocks(0),
62  m_sampleBits(16), // assume 16 bits to start with
63  m_sampleBytes(2),
64  m_samplesCount(0),
65  m_tickCount(0),
66  m_addressEdited(false),
67  m_dataPortEdited(false),
68  m_countUnrecoverable(0),
69  m_countRecovered(0),
70  m_doApplySettings(true),
71  m_forceSettings(true),
72  m_txDelay(0.0)
73 {
74  m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
75  m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white);
76 
78  ui->setupUi(this);
79 
80  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
81  ui->centerFrequency->setValueRange(7, 0, 9999999U);
82 
83  ui->centerFrequencyHz->setColorMapper(ColorMapper(ColorMapper::GrayGold));
84  ui->centerFrequencyHz->setValueRange(3, 0, 999U);
85 
86  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
87  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
88 
90 
91  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
92  m_statusTimer.start(500);
93  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
94 
96 
97  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
99 
100  m_networkManager = new QNetworkAccessManager();
101  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
102 
103  m_eventsTime.start();
106 
107  m_forceSettings = true;
108  sendSettings();
109 }
110 
112 {
113  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
114  delete m_networkManager;
115  delete ui;
116 }
117 
119 {
120  m_doApplySettings = !block;
121 }
122 
124 {
125  delete this;
126 }
127 
128 void RemoteInputGui::setName(const QString& name)
129 {
130  setObjectName(name);
131 }
132 
133 QString RemoteInputGui::getName() const
134 {
135  return objectName();
136 }
137 
139 {
141  displaySettings();
142  m_forceSettings = true;
143  sendSettings();
144 }
145 
146 QByteArray RemoteInputGui::serialize() const
147 {
148  return m_settings.serialize();
149 }
150 
151 bool RemoteInputGui::deserialize(const QByteArray& data)
152 {
153  qDebug("RemoteInputGui::deserialize");
154 
155  if (m_settings.deserialize(data))
156  {
157  displaySettings();
158  m_forceSettings = true;
159  sendSettings();
160 
161  return true;
162  }
163  else
164  {
165  return false;
166  }
167 }
168 
170 {
172 }
173 
174 void RemoteInputGui::setCenterFrequency(qint64 centerFrequency)
175 {
176  (void) centerFrequency;
177 }
178 
180 {
182  {
184  m_settings = cfg.getSettings();
185  blockApplySettings(true);
186  displaySettings();
187  blockApplySettings(false);
188  return true;
189  }
191  {
192  m_acquisition = ((RemoteInput::MsgReportRemoteInputAcquisition&)message).getAcquisition();
194  return true;
195  }
197  {
199 
200  qDebug() << "RemoteInputGui::handleMessage: RemoteInput::MsgReportRemoteInputStreamData: "
201  << " : " << m_startingTimeStampms << " ms";
202 
204  return true;
205  }
207  {
209  m_framesDecodingStatus = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getFramesDecodingStatus();
210  m_allBlocksReceived = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).allBlocksReceived();
211  m_bufferLengthInSecs = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getBufferLengthInSecs();
212  m_bufferGauge = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getBufferGauge();
213  m_minNbBlocks = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getMinNbBlocks();
214  m_minNbOriginalBlocks = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getMinNbOriginalBlocks();
215  m_maxNbRecovery = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getMaxNbRecovery();
216  m_avgNbBlocks = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getAvgNbBlocks();
217  m_avgNbOriginalBlocks = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getAvgNbOriginalBlocks();
218  m_avgNbRecovery = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getAvgNbRecovery();
219  m_nbOriginalBlocks = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getNbOriginalBlocksPerFrame();
220  m_sampleBits = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getSampleBits();
221  m_sampleBytes = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getSampleBytes();
222 
223  int nbFECBlocks = ((RemoteInput::MsgReportRemoteInputStreamTiming&)message).getNbFECBlocksPerFrame();
224 
225  if (m_nbFECBlocks != nbFECBlocks) {
226  m_nbFECBlocks = nbFECBlocks;
227  }
228 
230  return true;
231  }
232  else if (RemoteInput::MsgStartStop::match(message))
233  {
235  blockApplySettings(true);
236  ui->startStop->setChecked(notif.getStartStop());
237  blockApplySettings(false);
238 
239  return true;
240  }
241  else
242  {
243  return false;
244  }
245 }
246 
248 {
249  Message* message;
250 
251  while ((message = m_inputMessageQueue.pop()) != 0)
252  {
253  //qDebug("RemoteInputGui::handleInputMessages: message: %s", message->getIdentifier());
254 
255  if (DSPSignalNotification::match(*message))
256  {
257  DSPSignalNotification* notif = (DSPSignalNotification*) message;
258 
259  if (notif->getSampleRate() != m_streamSampleRate) {
261  }
262 
264 
265  qDebug("RemoteInputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
266 
268  DSPSignalNotification *fwd = new DSPSignalNotification(*notif);
270 
271  delete message;
272  }
273  else
274  {
275  if (handleMessage(*message))
276  {
277  delete message;
278  }
279  }
280  }
281 }
282 
284 {
287  ui->deviceRateText->setText(tr("%1k").arg((float)m_streamSampleRate / 1000));
288  blockApplySettings(true);
289  ui->centerFrequency->setValue(m_streamCenterFrequency / 1000);
290  ui->centerFrequencyHz->setValue(m_streamCenterFrequency % 1000);
291  blockApplySettings(false);
292 }
293 
295 {
296  blockApplySettings(true);
297 
298  ui->centerFrequency->setValue(m_streamCenterFrequency / 1000);
299  ui->centerFrequencyHz->setValue(m_streamCenterFrequency % 1000);
300  ui->deviceRateText->setText(tr("%1k").arg(m_streamSampleRate / 1000.0));
301 
302  ui->apiAddress->setText(m_settings.m_apiAddress);
303  ui->apiPort->setText(tr("%1").arg(m_settings.m_apiPort));
304  ui->dataPort->setText(tr("%1").arg(m_settings.m_dataPort));
305  ui->dataAddress->setText(m_settings.m_dataAddress);
306 
307  ui->dcOffset->setChecked(m_settings.m_dcBlock);
308  ui->iqImbalance->setChecked(m_settings.m_iqCorrection);
309 
310  blockApplySettings(false);
311 }
312 
314 {
315  if(!m_updateTimer.isActive())
316  m_updateTimer.start(100);
317 }
318 
320 {
321  (void) checked;
322  m_settings.m_apiAddress = ui->apiAddress->text();
323 
324  bool ctlOk;
325  int udpApiPort = ui->apiPort->text().toInt(&ctlOk);
326 
327  if((ctlOk) && (udpApiPort >= 1024) && (udpApiPort < 65535)) {
328  m_settings.m_apiPort = udpApiPort;
329  }
330 
331  sendSettings();
332 
333  QString infoURL = QString("http://%1:%2/sdrangel").arg(m_settings.m_apiAddress).arg(m_settings.m_apiPort);
334  m_networkRequest.setUrl(QUrl(infoURL));
336 }
337 
339 {
340  (void) checked;
341  m_settings.m_dataAddress = ui->dataAddress->text();
342 
343  bool dataOk;
344  int udpDataPort = ui->dataPort->text().toInt(&dataOk);
345 
346  if((dataOk) && (udpDataPort >= 1024) && (udpDataPort < 65535)) {
347  m_settings.m_dataPort = udpDataPort;
348  }
349 
350  sendSettings();
351 }
352 
354 {
355  m_settings.m_apiAddress = ui->apiAddress->text();
356 
357  QString infoURL = QString("http://%1:%2/sdrangel").arg(m_settings.m_apiAddress).arg(m_settings.m_apiPort);
358  m_networkRequest.setUrl(QUrl(infoURL));
360 
361  sendSettings();
362 }
363 
365 {
366  m_settings.m_dataAddress = ui->dataAddress->text();
367  sendSettings();
368 }
369 
371 {
372  bool dataOk;
373  int udpDataPort = ui->dataPort->text().toInt(&dataOk);
374 
375  if((!dataOk) || (udpDataPort < 1024) || (udpDataPort > 65535))
376  {
377  return;
378  }
379  else
380  {
381  m_settings.m_dataPort = udpDataPort;
382  sendSettings();
383  }
384 }
385 
387 {
388  bool ctlOk;
389  int udpApiPort = ui->apiPort->text().toInt(&ctlOk);
390 
391  if((!ctlOk) || (udpApiPort < 1024) || (udpApiPort > 65535))
392  {
393  return;
394  }
395  else
396  {
397  m_settings.m_apiPort = udpApiPort;
398 
399  QString infoURL = QString("http://%1:%2/sdrangel").arg(m_settings.m_apiAddress).arg(m_settings.m_apiPort);
400  m_networkRequest.setUrl(QUrl(infoURL));
402 
403  sendSettings();
404  }
405 }
406 
408 {
409  m_settings.m_dcBlock = checked;
410  sendSettings();
411 }
412 
414 {
415  m_settings.m_iqCorrection = checked;
416  sendSettings();
417 }
418 
420 {
421  if (m_doApplySettings)
422  {
425  }
426 }
427 
429 {
430  if (checked) {
431  ui->record->setStyleSheet("QToolButton { background-color : red; }");
432  } else {
433  ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
434  }
435 
438 }
439 
441 {
442  (void) checked;
444  m_countRecovered = 0;
445  m_eventsTime.start();
448 }
449 
451 {
452  QString nstr = QString("%1").arg(m_countUnrecoverable, 3, 10, QChar('0'));
453  ui->eventUnrecText->setText(nstr);
454  nstr = QString("%1").arg(m_countRecovered, 3, 10, QChar('0'));
455  ui->eventRecText->setText(nstr);
456 }
457 
459 {
460  int elapsedTimeMillis = m_eventsTime.elapsed();
461  QTime recordLength(0, 0, 0, 0);
462  recordLength = recordLength.addSecs(elapsedTimeMillis/1000);
463  QString s_time = recordLength.toString("HH:mm:ss");
464  ui->eventCountsTimeText->setText(s_time);
465 }
466 
468 {
469 }
470 
472 {
473  bool updateEventCounts = false;
474  QDateTime dt = QDateTime::fromMSecsSinceEpoch(m_startingTimeStampms);
475  QString s_date = dt.toString("yyyy-MM-dd HH:mm:ss.zzz");
476  ui->absTimeText->setText(s_date);
477 
478  if (m_framesDecodingStatus == 2)
479  {
480  ui->allFramesDecoded->setStyleSheet("QToolButton { background-color : green; }");
481  }
482  else if (m_framesDecodingStatus == 1)
483  {
484  if (m_countRecovered < 999) m_countRecovered++;
485  updateEventCounts = true;
486  ui->allFramesDecoded->setStyleSheet("QToolButton { background:rgb(56,56,56); }");
487  }
488  else
489  {
491  updateEventCounts = true;
492  ui->allFramesDecoded->setStyleSheet("QToolButton { background-color : red; }");
493  }
494 
495  QString s = QString::number(m_bufferLengthInSecs, 'f', 1);
496  ui->bufferLenSecsText->setText(tr("%1").arg(s));
497 
498  s = QString::number(m_bufferGauge, 'f', 0);
499  ui->bufferRWBalanceText->setText(tr("%1").arg(s));
500 
501  ui->bufferGaugeNegative->setValue((m_bufferGauge < 0 ? -m_bufferGauge : 0));
502  ui->bufferGaugePositive->setValue((m_bufferGauge < 0 ? 0 : m_bufferGauge));
503 
504  s = QString::number(m_minNbBlocks, 'f', 0);
505  ui->minNbBlocksText->setText(tr("%1").arg(s));
506 
507  s = QString("%1").arg(m_maxNbRecovery, 2, 10, QChar('0'));
508  ui->maxNbRecoveryText->setText(tr("%1").arg(s));
509 
510  s = QString::number(m_nbOriginalBlocks + m_nbFECBlocks, 'f', 0);
511  QString s1 = QString("%1").arg(m_nbFECBlocks, 2, 10, QChar('0'));
512  ui->nominalNbBlocksText->setText(tr("%1/%2").arg(s).arg(s1));
513 
514  ui->sampleBitsText->setText(tr("%1b").arg(m_sampleBits));
515 
516  if (updateEventCounts)
517  {
519  }
520 
522 }
523 
525 {
526  if (m_doApplySettings)
527  {
528  qDebug() << "RemoteInputGui::updateHardware";
532  m_forceSettings = false;
533  m_updateTimer.stop();
534  }
535 }
536 
538 {
540  {
541  int state = m_deviceUISet->m_deviceAPI->state();
542 
543  if (m_lastEngineState != state)
544  {
545  switch(state)
546  {
548  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
549  break;
550  case DeviceAPI::StIdle:
551  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
552  break;
554  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
555  break;
556  case DeviceAPI::StError:
557  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
558  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
559  break;
560  default:
561  break;
562  }
563 
564  m_lastEngineState = state;
565  }
566 
567  ui->startStop->setEnabled(true);
568  }
569  else
570  {
571  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
572  ui->startStop->setChecked(false);
573  ui->startStop->setEnabled(false);
574  }
575 }
576 
577 void RemoteInputGui::networkManagerFinished(QNetworkReply *reply)
578 {
579  if (reply->error())
580  {
581  ui->apiAddressLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
582  ui->statusText->setText(reply->errorString());
583  return;
584  }
585 
586  QString answer = reply->readAll();
587 
588  try
589  {
590  QByteArray jsonBytes(answer.toStdString().c_str());
591  QJsonParseError error;
592  QJsonDocument doc = QJsonDocument::fromJson(jsonBytes, &error);
593 
594  if (error.error == QJsonParseError::NoError)
595  {
596  ui->apiAddressLabel->setStyleSheet("QLabel { background-color : green; }");
597  ui->statusText->setText(QString("API OK"));
598  analyzeApiReply(doc.object());
599  }
600  else
601  {
602  ui->apiAddressLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
603  QString errorMsg = QString("Reply JSON error: ") + error.errorString() + QString(" at offset ") + QString::number(error.offset);
604  ui->statusText->setText(QString("JSON error. See log"));
605  qInfo().noquote() << "RemoteInputGui::networkManagerFinished" << errorMsg;
606  }
607  }
608  catch (const std::exception& ex)
609  {
610  ui->apiAddressLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
611  QString errorMsg = QString("Error parsing request: ") + ex.what();
612  ui->statusText->setText("Error parsing request. See log for details");
613  qInfo().noquote() << "RemoteInputGui::networkManagerFinished" << errorMsg;
614  }
615 }
616 
617 void RemoteInputGui::analyzeApiReply(const QJsonObject& jsonObject)
618 {
619  QString infoLine;
620 
621  if (jsonObject.contains("version")) {
622  infoLine = jsonObject["version"].toString();
623  }
624 
625  if (jsonObject.contains("qtVersion")) {
626  infoLine += " Qt" + jsonObject["qtVersion"].toString();
627  }
628 
629  if (jsonObject.contains("architecture")) {
630  infoLine += " " + jsonObject["architecture"].toString();
631  }
632 
633  if (jsonObject.contains("os")) {
634  infoLine += " " + jsonObject["os"].toString();
635  }
636 
637  if (jsonObject.contains("dspRxBits") && jsonObject.contains("dspTxBits")) {
638  infoLine += QString(" %1/%2b").arg(jsonObject["dspRxBits"].toInt()).arg(jsonObject["dspTxBits"].toInt());
639  }
640 
641  if (infoLine.size() > 0) {
642  ui->infoText->setText(infoLine);
643  }
644 }
645 
647 {
648  BasicDeviceSettingsDialog dialog(this);
653 
654  dialog.move(p);
655  dialog.exec();
656 
661 
662  sendSettings();
663 }
virtual qint64 getCenterFrequency() const
bool isStreaming() const
QString getName() const
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
uint32_t m_countUnrecoverable
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
quint64 m_streamCenterFrequency
Center frequency of received stream.
void updateWithStreamTime()
DeviceSampleSource * getSampleSource()
Return pointer to the device sample source (single Rx) or nullptr.
Definition: deviceapi.cpp:213
void setUseReverseAPI(bool useReverseAPI)
MessageQueue * getInputMessageQueue()
QNetworkAccessManager * m_networkManager
uint32_t m_countRecovered
void updateSampleRateAndFrequency()
void on_dataApplyButton_clicked(bool checked)
Ui::RemoteInputGui * ui
QByteArray serialize() const
static MsgConfigureRemoteInput * create(const RemoteInputSettings &settings, bool force=false)
Definition: remoteinput.h:50
uint64_t m_startingTimeStampms
DeviceUISet * m_deviceUISet
virtual void setCenterFrequency(qint64 centerFrequency)
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
MessageQueue m_inputMessageQueue
void on_record_toggled(bool checked)
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
void handleInputMessages()
GLSpectrum * getSpectrum()
Direct spectrum getter.
Definition: deviceuiset.h:57
void on_dcOffset_toggled(bool checked)
engine is before initialization
Definition: deviceapi.h:53
int32_t m_bufferGauge
void openDeviceSettingsDialog(const QPoint &p)
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
EngineState state() const
Return the state of the device engine corresponding to the stream type.
Definition: deviceapi.cpp:277
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
engine is idle
Definition: deviceapi.h:54
void on_apiAddress_returnPressed()
bool deserialize(const QByteArray &data)
void setName(const QString &name)
virtual void setMessageQueueToGUI(MessageQueue *queue)
RemoteInputSettings m_settings
current settings
void on_dataAddress_returnPressed()
void analyzeApiReply(const QJsonObject &jsonObject)
bool m_allBlocksReceived
void updateWithAcquisition()
static bool match(const Message *message)
Definition: message.cpp:45
QTimer m_statusTimer
static MsgStartStop * create(bool startStop)
Definition: remoteinput.h:258
void on_apiPort_returnPressed()
void networkManagerFinished(QNetworkReply *reply)
int m_streamSampleRate
Sample rate of received stream.
virtual bool handleMessage(const Message &message)
QPalette m_paletteWhiteText
virtual void destroy()
QNetworkRequest m_networkRequest
void on_apiApplyButton_clicked(bool checked)
int getSampleRate() const
Definition: dspcommands.h:328
virtual ~RemoteInputGui()
static MsgFileRecord * create(bool startStop)
Definition: remoteinput.h:239
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
void on_iqImbalance_toggled(bool checked)
RemoteInputGui(DeviceUISet *deviceUISet, QWidget *parent=0)
float m_bufferLengthInSecs
void setReverseAPIAddress(const QString &address)
QTimer m_updateTimer
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
bool deserialize(const QByteArray &data)
float m_avgNbOriginalBlocks
void on_startStop_toggled(bool checked)
engine is running
Definition: deviceapi.h:56
QByteArray serialize() const
void blockApplySettings(bool block)
const RemoteInputSettings & getSettings() const
Definition: remoteinput.h:47
RemoteInput * m_sampleSource
engine is in error
Definition: deviceapi.h:57
QPalette m_paletteGreenText
void on_eventCountsReset_clicked(bool checked)
void on_dataPort_returnPressed()
int m_framesDecodingStatus