source: ntrip/trunk/BNC/bncwindow.cpp@ 628

Last change on this file since 628 was 628, checked in by mervart, 16 years ago

* empty log message *

File size: 33.2 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: bncWindow
30 *
31 * Purpose: This class implements the main application window.
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Dec-2005
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <unistd.h>
42#include "bncwindow.h"
43#include "bncapp.h"
44#include "bncgetthread.h"
45#include "bnctabledlg.h"
46#include "bnchlpdlg.h"
47#include "bnchtml.h"
48#include "bnctableitem.h"
49
50using namespace std;
51
52// Constructor
53////////////////////////////////////////////////////////////////////////////
54bncWindow::bncWindow() {
55
56 _caster = 0;
57
58 int ww = QFontMetrics(this->font()).width('w');
59
60 static const QStringList labels = QString("account,mountpoint,decoder,lat,long,nmea,bytes").split(",");
61
62 setMinimumSize(77*ww, 65*ww);
63
64 setWindowTitle(tr("BKG Ntrip Client (BNC) Version 1.5"));
65
66 // Create Actions
67 // --------------
68 _actHelp = new QAction(tr("&Help Contents"),this);
69 connect(_actHelp, SIGNAL(triggered()), SLOT(slotHelp()));
70
71 _actAbout = new QAction(tr("&About BNC"),this);
72 connect(_actAbout, SIGNAL(triggered()), SLOT(slotAbout()));
73
74 _actFontSel = new QAction(tr("Select &Font"),this);
75 connect(_actFontSel, SIGNAL(triggered()), SLOT(slotFontSel()));
76
77 _actSaveOpt = new QAction(tr("&Save Options"),this);
78 connect(_actSaveOpt, SIGNAL(triggered()), SLOT(slotSaveOptions()));
79
80 _actQuit = new QAction(tr("&Quit"),this);
81 connect(_actQuit, SIGNAL(triggered()), SLOT(close()));
82
83 _actAddMountPoints = new QAction(tr("Add &Mountpoints"),this);
84 connect(_actAddMountPoints, SIGNAL(triggered()), SLOT(slotAddMountPoints()));
85
86 _actDeleteMountPoints = new QAction(tr("&Delete Mountpoints"),this);
87 connect(_actDeleteMountPoints, SIGNAL(triggered()), SLOT(slotDeleteMountPoints()));
88 _actDeleteMountPoints->setEnabled(false);
89
90 _actGetData = new QAction(tr("Sta&rt"),this);
91 connect(_actGetData, SIGNAL(triggered()), SLOT(slotGetData()));
92
93 _actStop = new QAction(tr("Sto&p"),this);
94 connect(_actStop, SIGNAL(triggered()), SLOT(slotStop()));
95 _actStop->setEnabled(false);
96
97 _actwhatsthis= new QAction(tr("Help=Shift+F1"),this);
98 connect(_actwhatsthis, SIGNAL(triggered()), SLOT(slotWhatsThis()));
99
100 // Create Menus
101 // ------------
102 _menuFile = menuBar()->addMenu(tr("&File"));
103 _menuFile->addAction(_actFontSel);
104 _menuFile->addSeparator();
105 _menuFile->addAction(_actSaveOpt);
106 _menuFile->addSeparator();
107 _menuFile->addAction(_actQuit);
108
109 _menuHlp = menuBar()->addMenu(tr("&Help"));
110 _menuHlp->addAction(_actHelp);
111 _menuHlp->addAction(_actAbout);
112
113 // Tool (Command) Bar
114 // ------------------
115 QToolBar* toolBar = new QToolBar;
116 addToolBar(Qt::BottomToolBarArea, toolBar);
117 toolBar->setMovable(false);
118 toolBar->addAction(_actAddMountPoints);
119 toolBar->addAction(_actDeleteMountPoints);
120 toolBar->addAction(_actGetData);
121 toolBar->addAction(_actStop);
122 toolBar->addWidget(new QLabel(" "));
123 toolBar->addAction(_actwhatsthis);
124
125 // Canvas with Editable Fields
126 // ---------------------------
127 _canvas = new QWidget;
128 setCentralWidget(_canvas);
129
130 QGridLayout* layout = new QGridLayout;
131 _canvas->setLayout(layout);
132
133 QSettings settings;
134 _proxyHostLineEdit = new QLineEdit(settings.value("proxyHost").toString());
135 _proxyHostLineEdit->setMaximumWidth(12*ww);
136 _proxyHostLineEdit->setWhatsThis(tr("<p>You may want to run BNC in a Local Area Network (LAN). LANs are often protected by a proxy server. Enter your proxy server host IP name or number and port number in case one is operated in front of BNC. If you don't know the IP and port of your proxy server, check out the proxy server settings of your Internet browser or ask your network administrator.</p><p>Note that IP streaming may generally be denied in a LAN. In such a case you need to ask your network administrator for an appropriate modification of his security policy or for the installation of a TCP relay to involved NTRIP broadcasters. If that doesn't work out, run BNC outside your LAN on a host that is connected to the Internet through an Internet Service Provider (ISP).</p><p>Default values for 'Proxy host' and 'Proxy port' are empty option fields, assuming that no proxy server is operated in front of BNC.</p>"));
137 _proxyPortLineEdit = new QLineEdit(settings.value("proxyPort").toString());
138 _proxyPortLineEdit->setMaximumWidth(9*ww);
139 _proxyPortLineEdit->setWhatsThis(tr("<p>You may want to run BNC in a Local Area Network (LAN). LANs are often protected by a proxy server. Enter your proxy server host IP name or number and port number in case one is operated in front of BNC. If you don't know the IP and port of your proxy server, check out the proxy server settings of your Internet browser or ask your network administrator.</p><p>Note that IP streaming may generally be denied in a LAN. In such a case you need to ask your network administrator for an appropriate modification of his security policy or for the installation of a TCP relay to involved NTRIP broadcasters. If that doesn't work out, run BNC outside your LAN on a host that is connected to the Internet through an Internet Service Provider (ISP).</p><p>Default values for 'Proxy host' and 'Proxy port' are empty option fields, assuming that no proxy server is operated in front of BNC.</p>"));
140 _waitTimeSpinBox = new QSpinBox();
141 _waitTimeSpinBox->setMinimum(1);
142 _waitTimeSpinBox->setMaximum(30);
143 _waitTimeSpinBox->setSingleStep(1);
144 _waitTimeSpinBox->setSuffix(" sec");
145 _waitTimeSpinBox->setMaximumWidth(9*ww);
146 _waitTimeSpinBox->setValue(settings.value("waitTime").toInt());
147 _waitTimeSpinBox->setWhatsThis(tr("<p>BNC lets you output synchronized observations epoch by epoch. When feeding a real-time GNSS engine waiting for input, BNC ignores whatever is received later than 'Wait for full epoch' seconds. A value of 3 to 5 seconds could be an appropriate choice for that, depending on the latency of the incoming streams and the delay you can accept for your real-time GNSS product.</p><p>Note that 'Wait for full epoch' only concerns the ASCII output and the binary output and does not influence the RINEX file contents. Observations received later than 'Wait for full epoch' seconds will still be included in the RINEX files.</p>"));
148 _outFileLineEdit = new QLineEdit(settings.value("outFile").toString());
149 _outFileLineEdit->setWhatsThis(tr("<p>Enter the full path for a file to save synchronized observations in a plain ASCII format.</p><p>Note that the size of this file rapidly increases, mainly depending on the number of incoming streams. Thus, this output option is primarily meant for test and evaluation purposes. Devault value for 'ASCII output file' is an empty option field, meaning that no ASCII output file is created.</p>"));
150 _outPortLineEdit = new QLineEdit(settings.value("outPort").toString());
151 _outPortLineEdit->setMaximumWidth(9*ww);
152 _outPortLineEdit->setWhatsThis(tr("<p>BNC makes synchronized observations available in a binary format on your local host (IP 127.0.0.1) through an IP port. Enter an IP port number to activate this function.</p><p>Default is an empty option field, meaning that no binary output is generated.</p>"));
153 _outEphPortLineEdit = new QLineEdit(settings.value("outEphPort").toString());
154 _outEphPortLineEdit->setMaximumWidth(9*ww);
155 _outEphPortLineEdit->setWhatsThis(tr("<p>BNC makes broadcast ephemeris available in ASCII format on your local host through an IP port</p>"));
156 _rnxPathLineEdit = new QLineEdit(settings.value("rnxPath").toString());
157 _rnxPathLineEdit->setWhatsThis(tr("<p>Observations can be converted to RINEX. Enter a path for saving the RINEX files in a directory. If this directory does not exist, BNC will not create RINEX files.</p><p>Default value for 'RINEX directory' is an empty option field, meaning that streams are not converted to RINEX.</p>"));
158 _ephPathLineEdit = new QLineEdit(settings.value("ephPath").toString());
159 _ephPathLineEdit->setWhatsThis(tr("<p>Ephemeris data from RTCM Version 3.x streams can be converted to RINEX. Enter a path for saving the RINEX Navigation files in a directory. If this directory does not exist, BNC will not create RINEX Navigation files.</p><p>Default value for 'Ephemeris directory' is an empty option field, meaning that no RINEX Navigation files will be created.</p>"));
160
161 _rnxV3CheckBox = new QCheckBox();
162 _rnxV3CheckBox->setCheckState(Qt::CheckState(settings.value("rnxV3").toInt()));
163 _ephV3CheckBox = new QCheckBox();
164 _ephV3CheckBox->setCheckState(Qt::CheckState(settings.value("ephV3").toInt()));
165 _rnxScrpLineEdit = new QLineEdit(settings.value("rnxScript").toString());
166 _rnxScrpLineEdit->setWhatsThis(tr("<p>Whenever a RINEX file is saved, you may like to compress, copy or upload it immediately via FTP. For that you enter the full path of a script or batch file which is then called to carry out these operations. The full RINEX file path will be passed to the script as a command line parameter (%1 on Windows systems, $1 on Unix/Linux systems).</p><p>The triggering event for calling the script or batch file is the end of the 'RINEX file interval'. If that is superposed by a stream outage, the triggering event is the stream reconnect.</p><p>Default value for 'RINEX script' is an empty option field, meaning that no script or batch file shall be called."));
167 _rnxSkelLineEdit = new QLineEdit(settings.value("rnxSkel").toString());
168 _rnxSkelLineEdit->setMaximumWidth(5*ww);
169 _rnxSkelLineEdit->setWhatsThis(tr("<p>Whenever BNC starts generating RINEX files (and then once every day at midnight), it first tries to retrieve information needed for RINEX headers from so-called public RINEX header skeleton files which are derived from sitelogs. However, it may happen that public RINEX header skeleton files are not available, its contents is not up to date, or you need to have additional/optional records in the RINEX header.</p><p>For that BNC allows to introduce personal skeleton files that contain the header records you would like to see. You may derive a personal RINEX header skeleton file from the information given in an up to date sitelog. A file in the 'RINEX directory' with the extension 'RINEX skeleton extension' is interpreted by BNC as a personal RINEX header skeleton file for the affected stream.</p><p>Default value for 'RINEX skeleton extension' is 'SKL', meaning that BNC will include the contents of probably existing files with this extension into the affected RINEX file headers.</p>"));
170 _rnxAppendCheckBox = new QCheckBox();
171 _rnxAppendCheckBox->setCheckState(Qt::CheckState(
172 settings.value("rnxAppend").toInt()));
173 _rnxAppendCheckBox->setWhatsThis(tr("<p>When starting BNC, new RINEX files are created by default. Probably existing files will be overwritten. However, it may be desirable to append observations to already existing RINEX files following a restart of BNC after an intentional 'Stop', a system crash or a crash of BNC. Hit 'Append files' to continue with already existing files and thus save what has been recorded so far.</p><p>Note that option 'Append files' also concerns the 'ASCII output file' and the 'Log' file.</p>"));
174 _rnxIntrComboBox = new QComboBox();
175 _rnxIntrComboBox->setWhatsThis(tr("<p>Select an interval for the RINEX file generation.</p><p>Default for 'RINEX file interval' is '15 min', meaning that a new RINEX file is generated every 15 minutes.</p>"));
176 _rnxIntrComboBox->setMaximumWidth(9*ww);
177 _rnxIntrComboBox->setEditable(false);
178 _rnxIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
179 int ii = _rnxIntrComboBox->findText(settings.value("rnxIntr").toString());
180 if (ii != -1) {
181 _rnxIntrComboBox->setCurrentIndex(ii);
182 }
183 _ephIntrComboBox = new QComboBox();
184 _ephIntrComboBox->setWhatsThis(tr("<p>Select an interval for the ephemeris file generation.</p><p>Default for 'Ephemeris file interval' is '1 day', meaning that a new Ephemeris file is generated every day.</p>"));
185 _ephIntrComboBox->setMaximumWidth(9*ww);
186 _ephIntrComboBox->setEditable(false);
187 _ephIntrComboBox->addItems(QString("5 min,15 min,1 hour,1 day").split(","));
188 int jj = _ephIntrComboBox->findText(settings.value("ephIntr").toString());
189 if (jj != -1) {
190 _ephIntrComboBox->setCurrentIndex(jj);
191 }
192 _rnxSamplSpinBox = new QSpinBox();
193 _rnxSamplSpinBox->setWhatsThis(tr("<p>Select the RINEX sample interval in seconds. Zero '0' stands for converting all incoming epochs to RINEX.</p><p>Default for RINEX 'Sampling' is '0'.</p>"));
194 _rnxSamplSpinBox->setMinimum(0);
195 _rnxSamplSpinBox->setMaximum(60);
196 _rnxSamplSpinBox->setSingleStep(5);
197 _rnxSamplSpinBox->setMaximumWidth(9*ww);
198 _rnxSamplSpinBox->setValue(settings.value("rnxSampl").toInt());
199 _rnxSamplSpinBox->setSuffix(" sec");
200 _logFileLineEdit = new QLineEdit(settings.value("logFile").toString());
201 _logFileLineEdit->setWhatsThis(tr("<p>BNC's run-time comments as shown in the 'Log' section can be saved in a file through entering the full path for a 'Log' file.</p><p>Default value for 'Log' is an empty option field, meaning that BNC's run-time comments are not saved in a file.</p>"));
202 _mountPointsTable = new QTableWidget(0,7);
203 _mountPointsTable->setWhatsThis(tr("<p>Streams selected for retrieval are listed in the 'Mountpoints' section. Button 'Add Mountpoints' opens a window that allows to select data streams from an NTRIP broadcaster by their mountpoints. To delete a stream, select it by mouse click and hit 'Delete Mountpoints'. For adding or deleting several streams simultaneously, highlight them using +Shift and +Ctrl.</p><p>BNC automatically selects one out of several internal decoders for a stream based on its 'format' and 'format-details' as given in the source-table. It may happen that you need to overrule the automated decoder selection. Therefore BNC allows to edit the decoder string (first double-click, then edit field 'decoder', then hit Enter). Decoder strings allowed to be introduced for stream decoding and conversion are 'RTCM_2.x', 'RTCM_3.x', and 'RTIGS'.</p><p> BNC allows to by-pass its stream decoding and conversion algorithms, leave whatever is received untouched and save it in daily named files. To activate this functionality you need to enter the decoder string 'ZERO'. <p>BNC allows to receive streams from virtual reference stations. For accessing these streams, an approximate rover position is required to be send in NMEA format to the NTRIP broadcaster. Whether or not a stream retrieval needs be initiated by BNC through sending an NMEA-GGA string is indicated in column 'nmea'. For those streams showing 'yes' in column 'nmea', an individual user-specific data stream is generated, usually by a network RTK software. This stream is tailored exactly to the latitude and longitude shown in the 'lat' and 'long' columns. You may change these values (first double-click, then edit fields 'lat' and/or 'long', then hit Enter) according to your needs. The position has to be introduced in northern latitude degrees (example for northern hemisphere: 52.436, example for southern hemisphere: -24.567) and eastern longitude degrees (example: 358.872 or -1.128). Editing the 'lat' and 'long' values is only possible for streams that show a 'yes' in column 'nmea'. The position must point to a location within the service area of the affected RTK network.</p>"));
204
205 _mountPointsTable->horizontalHeader()->resizeSection(1,25*ww);
206 _mountPointsTable->horizontalHeader()->resizeSection(2,9*ww);
207 _mountPointsTable->horizontalHeader()->resizeSection(3,7*ww);
208 _mountPointsTable->horizontalHeader()->resizeSection(4,7*ww);
209 _mountPointsTable->horizontalHeader()->resizeSection(5,5*ww);
210 _mountPointsTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
211 _mountPointsTable->horizontalHeader()->setStretchLastSection(true);
212 _mountPointsTable->setHorizontalHeaderLabels(labels);
213 _mountPointsTable->setGridStyle(Qt::NoPen);
214 _mountPointsTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
215 _mountPointsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
216 _mountPointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
217 QListIterator<QString> it(settings.value("mountPoints").toStringList());
218 if (!it.hasNext()) {
219 _actGetData->setEnabled(false);
220 }
221 int iRow = 0;
222 while (it.hasNext()) {
223 QStringList hlp = it.next().split(" ");
224 if (hlp.size() < 5) continue;
225 _mountPointsTable->insertRow(iRow);
226
227 QUrl url(hlp[0]);
228
229 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
230 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
231 QString nmea(hlp[4]);
232
233 QTableWidgetItem* it;
234 it = new QTableWidgetItem(url.userInfo());
235 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
236 _mountPointsTable->setItem(iRow, 0, it);
237
238 it = new QTableWidgetItem(fullPath);
239 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
240 _mountPointsTable->setItem(iRow, 1, it);
241
242 it = new QTableWidgetItem(format);
243 _mountPointsTable->setItem(iRow, 2, it);
244
245 if (nmea == "yes") {
246 it = new QTableWidgetItem(latitude);
247 _mountPointsTable->setItem(iRow, 3, it);
248 it = new QTableWidgetItem(longitude);
249 _mountPointsTable->setItem(iRow, 4, it);
250 } else {
251 it = new QTableWidgetItem(latitude);
252 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
253 _mountPointsTable->setItem(iRow, 3, it);
254 it = new QTableWidgetItem(longitude);
255 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
256 _mountPointsTable->setItem(iRow, 4, it);
257 }
258
259 it = new QTableWidgetItem(nmea);
260 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
261 _mountPointsTable->setItem(iRow, 5, it);
262
263 bncTableItem* bncIt = new bncTableItem();
264 bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
265 _mountPointsTable->setItem(iRow, 6, bncIt);
266
267 iRow++;
268 }
269 _mountPointsTable->hideColumn(0);
270 _mountPointsTable->sortItems(1);
271
272 connect(_mountPointsTable, SIGNAL(itemSelectionChanged()),
273 SLOT(slotSelectionChanged()));
274
275 _log = new QTextBrowser();
276 _log->setReadOnly(true);
277
278 _log->setWhatsThis(tr("BNC comments its activities in the 'Log' section. Information is given concerning reconnections to the NTRIP broadcaster(s) following outages, stream delays, stream conversion etc."));
279
280 layout->addWidget(new QLabel("Proxy host"), 0, 0, 1, 2);
281 layout->addWidget(_proxyHostLineEdit, 0, 2);
282 layout->addWidget(new QLabel("Proxy port"), 0, 3);
283 layout->addWidget(_proxyPortLineEdit, 0, 4);
284
285 layout->addWidget(new QLabel("Wait for full epoch"), 1, 0, 1, 2);
286 layout->addWidget(_waitTimeSpinBox, 1, 2);
287
288 layout->addWidget(new QLabel("ASCII output file (full path)"), 2, 0, 1, 2);
289 layout->addWidget(_outFileLineEdit, 2, 2, 1, 3);
290
291 layout->addWidget(new QLabel("Port for output"), 3, 0, 1, 2);
292 QBoxLayout* bl1 = new QBoxLayout(QBoxLayout::LeftToRight);
293 bl1->addWidget(_outPortLineEdit);
294 bl1->addWidget(new QLabel("Observations (binary)"));
295 bl1->addStretch();
296 bl1->addWidget(_outEphPortLineEdit);
297 bl1->addWidget(new QLabel("Ephemeris (ascii)"));
298 layout->addLayout(bl1, 3, 2, 1, 2);
299
300 layout->addWidget(new QLabel("RINEX directory"), 4, 0, 1, 2);
301 layout->addWidget(_rnxPathLineEdit, 4, 2);
302
303 layout->addWidget(new QLabel("RINEX v3"), 4, 3, 1, 2);
304 layout->addWidget(_rnxV3CheckBox, 4, 4);
305 _rnxV3CheckBox->setWhatsThis(tr("<p>Select the RINEX Observation file output format.</p><p>Default is RINEX Version 2.11 format. Output in RINEX Version 3 (RINEX v3) format is optional.</p>"));
306
307 layout->addWidget(new QLabel("RINEX script (full path)"), 5, 0, 1, 2);
308 layout->addWidget(_rnxScrpLineEdit, 5, 2, 1, 3);
309
310 layout->addWidget(new QLabel("File interval"), 6, 0, 1, 2);
311
312 QBoxLayout* bl = new QBoxLayout(QBoxLayout::LeftToRight);
313 bl->addWidget(_rnxIntrComboBox);
314 bl->addWidget(new QLabel("RINEX"));
315 bl->addWidget(_ephIntrComboBox);
316 bl->addWidget(new QLabel("Ephemeris"));
317 layout->addLayout(bl, 6, 2, 1, 1);
318
319 layout->addWidget(new QLabel("Sampling"), 6, 3);
320 layout->addWidget(_rnxSamplSpinBox, 6, 4);
321
322 layout->addWidget(new QLabel("RINEX skeleton extension"), 7, 0, 1, 2);
323 layout->addWidget(_rnxSkelLineEdit, 7, 2);
324
325 layout->addWidget(new QLabel("Append files"), 7, 3);
326 layout->addWidget(_rnxAppendCheckBox, 7, 4);
327
328 layout->addWidget(new QLabel("Ephemeris directory"), 8, 0, 1, 2);
329 layout->addWidget(_ephPathLineEdit, 8, 2);
330
331 layout->addWidget(new QLabel("RINEX v3"), 8, 3, 1, 2);
332 layout->addWidget(_ephV3CheckBox, 8, 4);
333 _ephV3CheckBox->setWhatsThis(tr("<p>Select the RINEX Ephemeris file output format.</p><p>Default is RINEX Version 2.11 format. Output in RINEX Version 3 (RINEX v3) format is optional.</p>"));
334
335 layout->addWidget(new QLabel("Mountpoints"), 9, 0, 1, 2);
336
337 layout->addWidget(_mountPointsTable, 10, 0, 1, 5);
338
339 layout->addWidget(new QLabel("Log (full path)"), 11, 0, 1, 2);
340 layout->addWidget(_logFileLineEdit, 11, 2, 1, 3);
341 layout->addWidget(_log, 12, 0, 1, 5);
342}
343
344// Destructor
345////////////////////////////////////////////////////////////////////////////
346bncWindow::~bncWindow() {
347 delete _caster;
348}
349
350// Retrieve Table
351////////////////////////////////////////////////////////////////////////////
352void bncWindow::slotAddMountPoints() {
353
354 QSettings settings;
355 QString proxyHost = settings.value("proxyHost").toString();
356 int proxyPort = settings.value("proxyPort").toInt();
357 if (proxyHost != _proxyHostLineEdit->text() ||
358 proxyPort != _proxyPortLineEdit->text().toInt()) {
359 int iRet = QMessageBox::question(this, "Question", "Proxy options "
360 "changed. Use the new ones?",
361 QMessageBox::Yes, QMessageBox::No,
362 QMessageBox::NoButton);
363 if (iRet == QMessageBox::Yes) {
364 settings.setValue("proxyHost", _proxyHostLineEdit->text());
365 settings.setValue("proxyPort", _proxyPortLineEdit->text());
366 }
367 }
368
369 bncTableDlg* dlg = new bncTableDlg(this);
370 dlg->move(this->pos().x()+50, this->pos().y()+50);
371 connect(dlg, SIGNAL(newMountPoints(QStringList*)),
372 this, SLOT(slotNewMountPoints(QStringList*)));
373 dlg->exec();
374 delete dlg;
375
376}
377
378// Delete Selected Mount Points
379////////////////////////////////////////////////////////////////////////////
380void bncWindow::slotDeleteMountPoints() {
381
382 int nRows = _mountPointsTable->rowCount();
383 bool flg[nRows];
384 for (int iRow = 0; iRow < nRows; iRow++) {
385 if (_mountPointsTable->isItemSelected(_mountPointsTable->item(iRow,1))) {
386 flg[iRow] = true;
387 }
388 else {
389 flg[iRow] = false;
390 }
391 }
392 for (int iRow = nRows-1; iRow >= 0; iRow--) {
393 if (flg[iRow]) {
394 _mountPointsTable->removeRow(iRow);
395 }
396 }
397 _actDeleteMountPoints->setEnabled(false);
398
399 if (_mountPointsTable->rowCount() == 0) {
400 _actGetData->setEnabled(false);
401 }
402}
403
404// New Mount Points Selected
405////////////////////////////////////////////////////////////////////////////
406void bncWindow::slotNewMountPoints(QStringList* mountPoints) {
407 int iRow = 0;
408 QListIterator<QString> it(*mountPoints);
409 while (it.hasNext()) {
410 QStringList hlp = it.next().split(" ");
411 QUrl url(hlp[0]);
412 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
413 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
414 QString nmea(hlp[4]);
415
416 _mountPointsTable->insertRow(iRow);
417
418 QTableWidgetItem* it;
419 it = new QTableWidgetItem(url.userInfo());
420 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
421 _mountPointsTable->setItem(iRow, 0, it);
422
423 it = new QTableWidgetItem(fullPath);
424 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
425 _mountPointsTable->setItem(iRow, 1, it);
426
427 it = new QTableWidgetItem(format);
428 _mountPointsTable->setItem(iRow, 2, it);
429
430 if (nmea == "yes") {
431 it = new QTableWidgetItem(latitude);
432 _mountPointsTable->setItem(iRow, 3, it);
433 it = new QTableWidgetItem(longitude);
434 _mountPointsTable->setItem(iRow, 4, it);
435 } else {
436 it = new QTableWidgetItem(latitude);
437 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
438 _mountPointsTable->setItem(iRow, 3, it);
439 it = new QTableWidgetItem(longitude);
440 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
441 _mountPointsTable->setItem(iRow, 4, it);
442 }
443
444 it = new QTableWidgetItem(nmea);
445 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
446 _mountPointsTable->setItem(iRow, 5, it);
447
448 bncTableItem* bncIt = new bncTableItem();
449 _mountPointsTable->setItem(iRow, 6, bncIt);
450
451 iRow++;
452 }
453 _mountPointsTable->hideColumn(0);
454 _mountPointsTable->sortItems(1);
455 if (mountPoints->count() > 0) {
456 _actGetData->setEnabled(true);
457 }
458 delete mountPoints;
459}
460
461// Save Options
462////////////////////////////////////////////////////////////////////////////
463void bncWindow::slotSaveOptions() {
464 QSettings settings;
465 settings.setValue("proxyHost", _proxyHostLineEdit->text());
466 settings.setValue("proxyPort", _proxyPortLineEdit->text());
467 settings.setValue("waitTime", _waitTimeSpinBox->value());
468 settings.setValue("outFile", _outFileLineEdit->text());
469 settings.setValue("outPort", _outPortLineEdit->text());
470 settings.setValue("outEphPort", _outEphPortLineEdit->text());
471 settings.setValue("rnxPath", _rnxPathLineEdit->text());
472 settings.setValue("ephPath", _ephPathLineEdit->text());
473 settings.setValue("rnxScript", _rnxScrpLineEdit->text());
474 settings.setValue("rnxIntr", _rnxIntrComboBox->currentText());
475 settings.setValue("ephIntr", _ephIntrComboBox->currentText());
476 settings.setValue("rnxSampl", _rnxSamplSpinBox->value());
477 settings.setValue("rnxSkel", _rnxSkelLineEdit->text());
478 settings.setValue("rnxAppend", _rnxAppendCheckBox->checkState());
479 settings.setValue("rnxV3", _rnxV3CheckBox->checkState());
480 settings.setValue("ephV3", _ephV3CheckBox->checkState());
481 settings.setValue("logFile", _logFileLineEdit->text());
482
483QStringList mountPoints;
484
485 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
486 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
487 "@" + _mountPointsTable->item(iRow, 1)->text() );
488
489 mountPoints.append(url.toString() + " " +
490 _mountPointsTable->item(iRow, 2)->text()
491 + " " + _mountPointsTable->item(iRow, 3)->text()
492 + " " + _mountPointsTable->item(iRow, 4)->text()
493 + " " + _mountPointsTable->item(iRow, 5)->text());
494 }
495 settings.setValue("mountPoints", mountPoints);
496}
497
498// All get slots terminated
499////////////////////////////////////////////////////////////////////////////
500void bncWindow::slotGetThreadErrors() {
501 slotMessage("All Get Threads Terminated");
502 ((bncApp*)qApp)->slotMessage("All Get Threads Terminated");
503 _actAddMountPoints->setEnabled(true);
504 _actGetData->setEnabled(true);
505}
506
507// Retrieve Data
508////////////////////////////////////////////////////////////////////////////
509void bncWindow::slotGetData() {
510 slotSaveOptions();
511
512 _actAddMountPoints->setEnabled(false);
513 _actDeleteMountPoints->setEnabled(false);
514 _actGetData->setEnabled(false);
515 _actStop->setEnabled(true);
516
517 _caster = new bncCaster(_outFileLineEdit->text(),
518 _outPortLineEdit->text().toInt());
519
520 ((bncApp*)qApp)->setPort(_outEphPortLineEdit->text().toInt());
521
522 connect(_caster, SIGNAL(getThreadErrors()),
523 this, SLOT(slotGetThreadErrors()));
524
525 connect(_caster, SIGNAL(newMessage(QByteArray)),
526 this, SLOT(slotMessage(QByteArray)));
527 connect(_caster, SIGNAL(newMessage(QByteArray)),
528 (bncApp*)qApp, SLOT(slotMessage(QByteArray)));
529
530 slotMessage("============ Start BNC ============");
531 ((bncApp*)qApp)->slotMessage("============ Start BNC ============");
532
533 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
534 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
535 "@" + _mountPointsTable->item(iRow, 1)->text() );
536
537 QByteArray format = _mountPointsTable->item(iRow, 2)->text().toAscii();
538
539 QByteArray latitude = _mountPointsTable->item(iRow, 3)->text().toAscii();
540 QByteArray longitude = _mountPointsTable->item(iRow, 4)->text().toAscii();
541 QByteArray nmea = _mountPointsTable->item(iRow, 5)->text().toAscii();
542
543 bncGetThread* getThread = new bncGetThread(url, format, latitude, longitude, nmea, iRow);
544
545 connect(getThread, SIGNAL(newMessage(QByteArray)),
546 this, SLOT(slotMessage(QByteArray)));
547 connect(getThread, SIGNAL(newMessage(QByteArray)),
548 (bncApp*)qApp, SLOT(slotMessage(QByteArray)));
549
550 connect(getThread, SIGNAL(newBytes(QByteArray, double)),
551 (bncTableItem*) _mountPointsTable->item(iRow, 6),
552 SLOT(slotNewBytes(QByteArray, double)));
553
554 _caster->addGetThread(getThread);
555
556 getThread->start();
557 }
558}
559
560// Retrieve Data
561////////////////////////////////////////////////////////////////////////////
562void bncWindow::slotStop() {
563 int iRet = QMessageBox::question(this, "Stop", "Stop retrieving data?",
564 QMessageBox::Yes, QMessageBox::No,
565 QMessageBox::NoButton);
566 if (iRet == QMessageBox::Yes) {
567 delete _caster; _caster = 0;
568 _actGetData->setEnabled(true);
569 _actStop->setEnabled(false);
570 _actAddMountPoints->setEnabled(true);
571 }
572}
573
574// Close Application gracefully
575////////////////////////////////////////////////////////////////////////////
576void bncWindow::closeEvent(QCloseEvent* event) {
577
578 int iRet = QMessageBox::question(this, "Close", "Save Options?",
579 QMessageBox::Yes, QMessageBox::No,
580 QMessageBox::Cancel);
581
582 if (iRet == QMessageBox::Cancel) {
583 event->ignore();
584 return;
585 }
586 else if (iRet == QMessageBox::Yes) {
587 slotSaveOptions();
588 }
589
590 QMainWindow::closeEvent(event);
591 delete this;
592}
593
594// User changed the selection of mountPoints
595////////////////////////////////////////////////////////////////////////////
596void bncWindow::slotSelectionChanged() {
597 if (_mountPointsTable->selectedItems().isEmpty()) {
598 _actDeleteMountPoints->setEnabled(false);
599 }
600 else {
601 _actDeleteMountPoints->setEnabled(true);
602 }
603}
604
605// Display Program Messages
606////////////////////////////////////////////////////////////////////////////
607void bncWindow::slotMessage(const QByteArray msg) {
608
609 const int maxBufferSize = 10000;
610
611 QString txt = _log->toPlainText() + "\n" +
612 QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ") + msg;
613 _log->clear();
614 _log->append(txt.right(maxBufferSize));
615}
616
617// About Message
618////////////////////////////////////////////////////////////////////////////
619void bncWindow::slotAbout() {
620
621 QTextBrowser* tb = new QTextBrowser;
622 QUrl url; url.setPath(":bncabout.html");
623 tb->setSource(url);
624 tb->setReadOnly(true);
625
626 QDialog dlg(this);
627
628 QGridLayout* dlgLayout = new QGridLayout();
629 QLabel* img = new QLabel();
630 img->setPixmap(QPixmap(":ntrip-logo.png"));
631 dlgLayout->addWidget(img, 0,0);
632 dlgLayout->addWidget(new QLabel("BKG NTRIP Client (BNC) Version 1.5"), 0,1);
633 dlgLayout->addWidget(tb,1,0,1,2);
634
635 dlg.setLayout(dlgLayout);
636 int ww = QFontMetrics(font()).width('w');
637 dlg.resize(60*ww, 60*ww);
638 dlg.exec();
639}
640
641// Help Window
642////////////////////////////////////////////////////////////////////////////
643void bncWindow::slotHelp() {
644 QUrl url;
645 url.setPath(":bnchelp.html");
646 new bncHlpDlg(this, url);
647}
648
649// Select Fonts
650////////////////////////////////////////////////////////////////////////////
651void bncWindow::slotFontSel() {
652 bool ok;
653 QFont newFont = QFontDialog::getFont(&ok, this->font(), this);
654 if (ok) {
655 QSettings settings;
656 settings.setValue("font", newFont.toString());
657 QApplication::setFont(newFont);
658 int ww = QFontMetrics(newFont).width('w');
659 setMinimumSize(60*ww, 80*ww);
660 resize(60*ww, 80*ww);
661 }
662}
663
664// Whats This Help
665void bncWindow::slotWhatsThis() {
666QWhatsThis::enterWhatsThisMode();
667}
668
669
Note: See TracBrowser for help on using the repository browser.