SoDaRadio-5.0.3-master:8901fb5
mainwindow.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2017 Matthew H. Reilly (kb1vc)
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9  Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11  Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in
13  the documentation and/or other materials provided with the
14  distribution.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #include "mainwindow.hpp"
30 #include "ui_mainwindow.h"
31 #include "version.h"
32 #include <boost/version.hpp>
33 #include <uhd/version.hpp>
34 #include <iostream>
35 #include <boost/format.hpp>
36 
37 #include <QString>
38 #include <QMessageBox>
39 #include <QtCoreVersion>
40 
41 #include "soda_comboboxes.hpp"
42 #include "soda_listener.hpp"
43 #include "../common/GuiParams.hxx"
44 
45 using namespace GUISoDa;
46 
47 MainWindow::MainWindow(QWidget *parent, SoDa::GuiParams & params) :
48  QMainWindow(parent),
49  ui(new Ui::MainWindow)
50 {
51  ui->setupUi(this);
52 
53  // setup the listener.
54  listener = new GUISoDa::Listener(this, QString::fromStdString(params.getServerSocketBasename()));
55 
56  setupSpectrum();
58 
61  setupLogGPS();
62 
63  setupSettings();
66 
67 
68  // connect(listener, SIGNAL(repHWMBVersion(const QString &)),
69  // this, SLOT(setWindowTitle(const QString &)));
71  [=](const QString & hw) {
72  this->setWindowTitle(QString("SoDa Radio V %1 -- SDR %2").arg(SoDaRadio_VERSION).arg(hw));
73  });
74 
75  connect(listener, SIGNAL(initSetupComplete()),
76  this, SLOT(restoreSettings()));
77 
78  connect(listener, SIGNAL(fatalError(const QString &)),
79  this, SLOT(handleFatalError(const QString &)));
80 
81  listener->init();
82  listener->start();
83 
84  connect(ui->aboutSoDa_btn, SIGNAL(clicked(bool)),
85  this, SLOT(displayAppInfo(bool)));
86 
87  settings_p = new QSettings("kb1vc.org", "SoDaRadioQT", this);
88 
89  current_band_selector = ui->bandSel_cb->currentText();
90  auto_bandswitch_target = QString("");
91 
92  hlib_server = new HamlibServer(this, params.getHamlibPortNumber());
93 
94  hlib_server->start();
95 
96  setupHamlib();
97 }
98 
100 {
101  saveConfig();
102  delete ui;
103 }
104 
106 {
107  (void) dummy;
108 
109  QMessageBox::about(this, QString("SoDaRadio"),
110  QString("<h1>SoDaRadio</h1> \
111 <p>An all-mode SDR application for the Ettus USRP platform.</p> \
112 <ul> \
113 <li>SoDaRadio Version: %1</li><li>Git ID: %2</li>\
114 <li>USRP Hardware Driver Version: %3</li>\
115 <li>Qt Version: %4</li> \
116 <li>Boost Version: %5</li> \
117 <li>Sources and Such: https://kb1vc.github.io/SoDaRadio/</li> \
118 <li>Maintainer: kb1vc@kb1vc.org</li> \
119 </ul>\
120 <h2>License:</h2> \
121 <p> \
122 Copyright (c) 2017 Matthew H. Reilly (kb1vc) \
123 All rights reserved.</p> \
124 <p>Redistribution and use in source and binary forms, with or without \
125 modification, are permitted provided that the following conditions are \
126 met:</p> \
127 <p><b>Redistributions of source code must retain the above copyright \
128  notice, this list of conditions and the following disclaimer. \
129  Redistributions in binary form must reproduce the above copyright \
130  notice, this list of conditions and the following disclaimer in \
131  the documentation and/or other materials provided with the \
132  distribution.</b></p> \
133 <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \
134 \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \
135 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR \
136 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \
137 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \
138 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \
139 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \
140 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY \
141 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \
142 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \
143 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \
144 </p>").arg(SoDaRadio_VERSION).arg(SoDaRadio_GIT_ID).arg(UHD_VERSION_ABI_STRING).arg(QTCORE_VERSION_STR).arg(BOOST_LIB_VERSION));
145 }
146 
147 void MainWindow::widgetSaveRestore(QObject * op, const QString & par, bool save)
148 {
149  QObjectList wlist = op->children();
150  for(QObjectList::iterator cp = wlist.begin(); cp != wlist.end(); ++cp) {
151  QString my_name = (*cp)->objectName();
152  QString my_class = (*cp)->metaObject()->className();
153 
154  QString my_pathname = par + "." + my_name;
155  if(my_class == "QComboBox") {
156  if(QComboBox * cb = qobject_cast<QComboBox*>(*cp)) {
157  if(save) {
158  int ci = cb->currentIndex();
159  settings_p->setValue(my_pathname, ci);
160  }
161  else {
162  // restore!
163  int nvalue = settings_p->value(my_pathname, 0).toInt();
164  cb->setCurrentIndex(nvalue);
165  }
166  }
167  }
168  else if(my_class == "QSlider") {
169  if(QSlider * cb = qobject_cast<QSlider*>(*cp)) {
170  if(save) {
171  double cv = cb->value();
172  settings_p->setValue(my_pathname, cv);
173  }
174  else {
175  // restore!
176  double nvalue = settings_p->value(my_pathname, 0).toDouble();
177  cb->setValue(nvalue);
178  }
179  }
180  }
181  else if(my_class == "GUISoDa::FreqLabel") {
182  if(FreqLabel * cb = qobject_cast<FreqLabel *>(*cp)) {
183  if(save) {
184  double cv = cb->getFreq();
185  settings_p->setValue(my_pathname, cv);
186  }
187  else {
188  // restore!
189  double nvalue = settings_p->value(my_pathname, 144.2e6).toDouble();
190  cb->setFreqUpdate(nvalue);
191  }
192  }
193  }
194  else if(my_class == "QCheckBox") {
195  if(QCheckBox * cb = qobject_cast<QCheckBox *>(*cp)) {
196  if(save) {
197  bool cv = cb->isChecked();
198  settings_p->setValue(my_pathname, cv);
199  }
200  else {
201  // restore!
202  bool nvalue = settings_p->value(my_pathname, 0).toBool();
203  cb->setChecked(nvalue);
204  }
205  }
206  }
207  else if((my_class == "QSpinBox") || (my_class == "SoDaNoEditSpinbox")) {
208  if(QSpinBox * cb = qobject_cast<QSpinBox*>(*cp)) {
209  if(save) {
210  int cv = cb->value();
211  settings_p->setValue(my_pathname, cv);
212  }
213  else {
214  // restore!
215  int nvalue = settings_p->value(my_pathname, 0).toInt();
216  cb->setValue(nvalue);
217  }
218  }
219  }
220  else if(my_class == "QLineEdit") {
221  if(QLineEdit * cb = qobject_cast<QLineEdit*>(*cp)) {
222  if(save) {
223  QString cv = cb->text();
224  settings_p->setValue(my_pathname, cv);
225  }
226  else {
227  // restore!
228  QString nvalue = settings_p->value(my_pathname, "").toString();
229  cb->setText(nvalue);
230  }
231  }
232  }
233  else if(my_class == "GUISoDa::WFall") {
234  if(GUISoDa::WFall * cb = qobject_cast<GUISoDa::WFall*>(*cp)) {
235  if(save) {
236  double cv = cb->freqCenter();
237  settings_p->setValue(my_pathname, cv);
238  }
239  else {
240  // restore!
241  double nvalue = settings_p->value(my_pathname, 0).toDouble();
242  cb->setFreqCenter(nvalue);
243  }
244  }
245  }
246  else if(my_class == "GUISoDa::Spect") {
247  if(GUISoDa::Spect * cb = qobject_cast<GUISoDa::Spect*>(*cp)) {
248  if(save) {
249  double cv = cb->freqCenter();
250  settings_p->setValue(my_pathname, cv);
251  }
252  else {
253  // restore!
254  double nvalue = settings_p->value(my_pathname, 0).toDouble();
255  cb->setFreqCenter(nvalue);
256  }
257  }
258  }
259  else if(my_class == "GUISoDa::IntValComboBox") {
260  if(GUISoDa::IntValComboBox * cb = qobject_cast<GUISoDa::IntValComboBox*>(*cp)) {
261  if(save) {
262  int cv = cb->value();
263  settings_p->setValue(my_pathname, cv);
264  }
265  else {
266  // restore!
267  int nvalue = settings_p->value(my_pathname, 0).toInt();
268  cb->setValue(nvalue);
269  }
270  }
271  }
272  else if((my_class == "GUISoDa::WFallSpanComboBox") ||
273  (my_class == "GUISoDa::WFallDynRangeComboBox")) {
274  if(GUISoDa::ValComboBox * cb = qobject_cast<GUISoDa::ValComboBox*>(*cp)) {
275  if(save) {
276  double cv = cb->value();
277  settings_p->setValue(my_pathname, cv);
278  }
279  else {
280  // restore!
281  double nvalue = settings_p->value(my_pathname, 0).toDouble();
282  cb->setValue(nvalue);
283  }
284  }
285  }
286  else if(my_class == "QTabBar") {
287  if(QTabBar * cb = qobject_cast<QTabBar*>(*cp)) {
288  if(save) {
289  int cv = cb->currentIndex();
290  settings_p->setValue(my_pathname, cv);
291  }
292  else {
293  // restore!
294  int nvalue = settings_p->value(my_pathname, 0).toInt();
295  cb->setCurrentIndex(nvalue);
296  }
297  }
298  }
299  else if((my_class == "QAction") ||
300  (my_class == "QBoxLayout") ||
301  (my_class == "QDoubleValidator") ||
302  (my_class == "QFormLayout") ||
303  (my_class == "QGroupBox") ||
304  (my_class == "QHBoxLayout") ||
305  (my_class == "QHeaderView") ||
306  (my_class == "QItemSelectionModel") ||
307  (my_class == "QLabel") ||
308  (my_class == "QLocalSocket") ||
309  (my_class == "QMainWindowLayout") ||
310  (my_class == "QNativeSocketEngine") ||
311  (my_class == "QPlainTextDocumentLayout") ||
312  (my_class == "QPlainTextEdit") ||
313  (my_class == "QPlainTextEditControl") ||
314  (my_class == "QPropertyAnimation") ||
315  (my_class == "QPushButton") ||
316  (my_class == "QScrollBar") ||
317  (my_class == "QSettings") ||
318  (my_class == "QSocketNotifier") ||
319  (my_class == "QSplitter") ||
320  (my_class == "QSplitterHandle") ||
321  (my_class == "QStackedLayout") ||
322  (my_class == "QStackedWidget") ||
323  (my_class == "QStandardItemModel") ||
324  (my_class == "QStyledItemDelegate") ||
325  (my_class == "QTableCornerButton") ||
326  (my_class == "QTableModel") ||
327  (my_class == "QTabWidget") ||
328  (my_class == "QTcpSocket") ||
329  (my_class == "QTextDocument") ||
330  (my_class == "QTextDocumentLayout") ||
331  (my_class == "QTextFrame") ||
332  (my_class == "QTextImageHandler") ||
333  (my_class == "QToolButton") ||
334  (my_class == "QValidator") ||
335  (my_class == "QVBoxLayout") ||
336  (my_class == "QWidget") ||
337  (my_class == "QWidgetLineControl") ||
338  (my_class == "QWidgetTextControl") ||
339  (my_class == "QwtPlotCanvas") ||
340  (my_class == "QwtPlotPicker") ||
341  (my_class == "QwtScaleWidget") ||
342  (my_class == "QwtTextLabel")) {
343  // do nothing.
344  }
345  widgetSaveRestore((*cp), my_pathname, save);
346  }
347 }
348 
350 {
351  settings_p->beginGroup("Radio");
352  bandMapSaveRestore(band_map, false);
353  widgetSaveRestore(this, "SoDaRadioQT.", false);
354  settings_p->endGroup();
355 }
356 
357 void MainWindow::handleFatalError(const QString & err_string)
358 {
359  QMessageBox mbox(QMessageBox::Critical,
360  tr("Fatal Error"),
361  tr("%1 has encountered an error that is beyond safe recovery.\n"
362  "Please press OK button to quit. (Though this is -not- OK.\n"
363  "Send a note when you get a chance to kb1vc@kb1vc.org").arg(qApp->applicationDisplayName()),
364  QMessageBox::Ok, this);
365  mbox.setDetailedText(err_string);
366  mbox.exec();
367  qApp->quit();
368 }
void restoreSettings()
Definition: mainwindow.cpp:349
GUISoDa::Listener * listener
Definition: mainwindow.hpp:151
Ui::MainWindow * ui
Definition: mainwindow.hpp:149
QString auto_bandswitch_target
Definition: mainwindow.hpp:144
MainWindow(QWidget *parent, SoDa::GuiParams &params)
Definition: mainwindow.cpp:47
void handleFatalError(const QString &err_string)
pop up a notification box and then bail out.
Definition: mainwindow.cpp:357
void setupSpectrum()
QSettings * settings_p
Definition: mainwindow.hpp:137
bool init()
connect to radio server sockets and initialize listener state
void displayAppInfo(bool dummy)
Definition: mainwindow.cpp:105
void setupMidControls()
void setupTopControls()
void widgetSaveRestore(QObject *op, const QString &par, bool save)
Definition: mainwindow.cpp:147
void repHWMBVersion(const QString &version)
GUISoDa::HamlibServer * hlib_server
Definition: mainwindow.hpp:153
void start()
initiate transfers on the socket.
void setupWaterFall()
GUISoDa::BandMap band_map
Definition: mainwindow.hpp:141
void bandMapSaveRestore(GUISoDa::BandMap &bmap, bool save)
QString current_band_selector
Definition: mainwindow.hpp:143