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

Last change on this file since 608 was 608, 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 int ww = QFontMetrics(this->font()).width('w');
57
58 static const QStringList labels = QString("account,mountpoint,decoder,lat,long,nmea,bytes").split(",");
59
60 setMinimumSize(77*ww, 65*ww);
61
62 setWindowTitle(tr("BKG Ntrip Client (BNC) Version 1.5"));
63
64 // Create Actions
65 // --------------
66 _actHelp = new QAction(tr("&Help Contents"),this);
67 connect(_actHelp, SIGNAL(triggered()), SLOT(slotHelp()));
68
69 _actAbout = new QAction(tr("&About BNC"),this);
70 connect(_actAbout, SIGNAL(triggered()), SLOT(slotAbout()));
71
72 _actFontSel = new QAction(tr("Select &Font"),this);
73 connect(_actFontSel, SIGNAL(triggered()), SLOT(slotFontSel()));
74
75 _actSaveOpt = new QAction(tr("&Save Options"),this);
76 connect(_actSaveOpt, SIGNAL(triggered()), SLOT(slotSaveOptions()));
77
78 _actQuit = new QAction(tr("&Quit"),this);
79 connect(_actQuit, SIGNAL(triggered()), SLOT(close()));
80
81 _actAddMountPoints = new QAction(tr("Add &Mountpoints"),this);
82 connect(_actAddMountPoints, SIGNAL(triggered()), SLOT(slotAddMountPoints()));
83
84 _actDeleteMountPoints = new QAction(tr("&Delete Mountpoints"),this);
85 connect(_actDeleteMountPoints, SIGNAL(triggered()), SLOT(slotDeleteMountPoints()));
86 _actDeleteMountPoints->setEnabled(false);
87
88 _actGetData = new QAction(tr("Sta&rt"),this);
89 connect(_actGetData, SIGNAL(triggered()), SLOT(slotGetData()));
90
91 _actStop = new QAction(tr("Sto&p"),this);
92 connect(_actStop, SIGNAL(triggered()), SLOT(slotStop()));
93 _actStop->setEnabled(false);
94
95 _actwhatsthis= new QAction(tr("Help=Shift+F1"),this);
96 connect(_actwhatsthis, SIGNAL(triggered()), SLOT(slotWhatsThis()));
97
98 // Create Menus
99 // ------------
100 _menuFile = menuBar()->addMenu(tr("&File"));
101 _menuFile->addAction(_actFontSel);
102 _menuFile->addSeparator();
103 _menuFile->addAction(_actSaveOpt);
104 _menuFile->addSeparator();
105 _menuFile->addAction(_actQuit);
106
107 _menuHlp = menuBar()->addMenu(tr("&Help"));
108 _menuHlp->addAction(_actHelp);
109 _menuHlp->addAction(_actAbout);
110
111 // Tool (Command) Bar
112 // ------------------
113 QToolBar* toolBar = new QToolBar;
114 addToolBar(Qt::BottomToolBarArea, toolBar);
115 toolBar->setMovable(false);
116 toolBar->addAction(_actAddMountPoints);
117 toolBar->addAction(_actDeleteMountPoints);
118 toolBar->addAction(_actGetData);
119 toolBar->addAction(_actStop);
120 toolBar->addWidget(new QLabel(" "));
121 toolBar->addAction(_actwhatsthis);
122
123 // Canvas with Editable Fields
124 // ---------------------------
125 _canvas = new QWidget;
126 setCentralWidget(_canvas);
127
128 QGridLayout* layout = new QGridLayout;
129 _canvas->setLayout(layout);
130
131 QSettings settings;
132 _proxyHostLineEdit = new QLineEdit(settings.value("proxyHost").toString());
133 _proxyHostLineEdit->setMaximumWidth(12*ww);
134 _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>"));
135 _proxyPortLineEdit = new QLineEdit(settings.value("proxyPort").toString());
136 _proxyPortLineEdit->setMaximumWidth(9*ww);
137 _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>"));
138 _waitTimeSpinBox = new QSpinBox();
139 _waitTimeSpinBox->setMinimum(1);
140 _waitTimeSpinBox->setMaximum(30);
141 _waitTimeSpinBox->setSingleStep(1);
142 _waitTimeSpinBox->setSuffix(" sec");
143 _waitTimeSpinBox->setMaximumWidth(9*ww);
144 _waitTimeSpinBox->setValue(settings.value("waitTime").toInt());
145 _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>"));
146 _outFileLineEdit = new QLineEdit(settings.value("outFile").toString());
147 _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>"));
148 _outPortLineEdit = new QLineEdit(settings.value("outPort").toString());
149 _outPortLineEdit->setMaximumWidth(9*ww);
150 _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>"));
151 _outEphPortLineEdit = new QLineEdit(settings.value("outEphPort").toString());
152 _outEphPortLineEdit->setMaximumWidth(9*ww);
153 _outEphPortLineEdit->setWhatsThis(tr("<p>BNC makes broadcast ephemeris available in ASCII format on your local host through an IP port</p>"));
154 _rnxPathLineEdit = new QLineEdit(settings.value("rnxPath").toString());
155 _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>"));
156 _ephPathLineEdit = new QLineEdit(settings.value("ephPath").toString());
157 _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>"));
158
159 _rnxV3CheckBox = new QCheckBox();
160 _rnxV3CheckBox->setCheckState(Qt::CheckState(settings.value("rnxV3").toInt()));
161 _ephV3CheckBox = new QCheckBox();
162 _ephV3CheckBox->setCheckState(Qt::CheckState(settings.value("ephV3").toInt()));
163 _rnxScrpLineEdit = new QLineEdit(settings.value("rnxScript").toString());
164 _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."));
165 _rnxSkelLineEdit = new QLineEdit(settings.value("rnxSkel").toString());
166 _rnxSkelLineEdit->setMaximumWidth(5*ww);
167 _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>"));
168 _rnxAppendCheckBox = new QCheckBox();
169 _rnxAppendCheckBox->setCheckState(Qt::CheckState(
170 settings.value("rnxAppend").toInt()));
171 _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>"));
172 _rnxIntrComboBox = new QComboBox();
173 _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>"));
174 _rnxIntrComboBox->setMaximumWidth(9*ww);
175 _rnxIntrComboBox->setEditable(false);
176 _rnxIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
177 int ii = _rnxIntrComboBox->findText(settings.value("rnxIntr").toString());
178 if (ii != -1) {
179 _rnxIntrComboBox->setCurrentIndex(ii);
180 }
181 _ephIntrComboBox = new QComboBox();
182 _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>"));
183 _ephIntrComboBox->setMaximumWidth(9*ww);
184 _ephIntrComboBox->setEditable(false);
185 _ephIntrComboBox->addItems(QString("5 min,15 min,1 hour,1 day").split(","));
186 int jj = _ephIntrComboBox->findText(settings.value("ephIntr").toString());
187 if (jj != -1) {
188 _ephIntrComboBox->setCurrentIndex(jj);
189 }
190 _rnxSamplSpinBox = new QSpinBox();
191 _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>"));
192 _rnxSamplSpinBox->setMinimum(0);
193 _rnxSamplSpinBox->setMaximum(60);
194 _rnxSamplSpinBox->setSingleStep(5);
195 _rnxSamplSpinBox->setMaximumWidth(9*ww);
196 _rnxSamplSpinBox->setValue(settings.value("rnxSampl").toInt());
197 _rnxSamplSpinBox->setSuffix(" sec");
198 _logFileLineEdit = new QLineEdit(settings.value("logFile").toString());
199 _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>"));
200 _mountPointsTable = new QTableWidget(0,7);
201 _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>"));
202
203 _mountPointsTable->horizontalHeader()->resizeSection(1,25*ww);
204 _mountPointsTable->horizontalHeader()->resizeSection(2,9*ww);
205 _mountPointsTable->horizontalHeader()->resizeSection(3,7*ww);
206 _mountPointsTable->horizontalHeader()->resizeSection(4,7*ww);
207 _mountPointsTable->horizontalHeader()->resizeSection(5,5*ww);
208 _mountPointsTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
209 _mountPointsTable->horizontalHeader()->setStretchLastSection(true);
210 _mountPointsTable->setHorizontalHeaderLabels(labels);
211 _mountPointsTable->setGridStyle(Qt::NoPen);
212 _mountPointsTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
213 _mountPointsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
214 _mountPointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
215 QListIterator<QString> it(settings.value("mountPoints").toStringList());
216 if (!it.hasNext()) {
217 _actGetData->setEnabled(false);
218 }
219 int iRow = 0;
220 while (it.hasNext()) {
221 QStringList hlp = it.next().split(" ");
222 if (hlp.size() < 5) continue;
223 _mountPointsTable->insertRow(iRow);
224
225 QUrl url(hlp[0]);
226
227 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
228 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
229 QString nmea(hlp[4]);
230
231 QTableWidgetItem* it;
232 it = new QTableWidgetItem(url.userInfo());
233 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
234 _mountPointsTable->setItem(iRow, 0, it);
235
236 it = new QTableWidgetItem(fullPath);
237 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
238 _mountPointsTable->setItem(iRow, 1, it);
239
240 it = new QTableWidgetItem(format);
241 _mountPointsTable->setItem(iRow, 2, it);
242
243 if (nmea == "yes") {
244 it = new QTableWidgetItem(latitude);
245 _mountPointsTable->setItem(iRow, 3, it);
246 it = new QTableWidgetItem(longitude);
247 _mountPointsTable->setItem(iRow, 4, it);
248 } else {
249 it = new QTableWidgetItem(latitude);
250 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
251 _mountPointsTable->setItem(iRow, 3, it);
252 it = new QTableWidgetItem(longitude);
253 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
254 _mountPointsTable->setItem(iRow, 4, it);
255 }
256
257 it = new QTableWidgetItem(nmea);
258 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
259 _mountPointsTable->setItem(iRow, 5, it);
260
261 bncTableItem* bncIt = new bncTableItem();
262 bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
263 _mountPointsTable->setItem(iRow, 6, bncIt);
264
265 iRow++;
266 }
267 _mountPointsTable->hideColumn(0);
268 _mountPointsTable->sortItems(1);
269
270 connect(_mountPointsTable, SIGNAL(itemSelectionChanged()),
271 SLOT(slotSelectionChanged()));
272
273 _log = new QTextBrowser();
274 _log->setReadOnly(true);
275
276 _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."));
277
278 layout->addWidget(new QLabel("Proxy host"), 0, 0, 1, 2);
279 layout->addWidget(_proxyHostLineEdit, 0, 2);
280 layout->addWidget(new QLabel("Proxy port"), 0, 3);
281 layout->addWidget(_proxyPortLineEdit, 0, 4);
282
283 layout->addWidget(new QLabel("Wait for full epoch"), 1, 0, 1, 2);
284 layout->addWidget(_waitTimeSpinBox, 1, 2);
285
286 layout->addWidget(new QLabel("ASCII output file (full path)"), 2, 0, 1, 2);
287 layout->addWidget(_outFileLineEdit, 2, 2, 1, 3);
288
289 layout->addWidget(new QLabel("Port for output"), 3, 0, 1, 2);
290 QBoxLayout* bl1 = new QBoxLayout(QBoxLayout::LeftToRight);
291 bl1->addWidget(_outPortLineEdit);
292 bl1->addWidget(new QLabel("Observations (binary)"));
293 bl1->addStretch();
294 bl1->addWidget(_outEphPortLineEdit);
295 bl1->addWidget(new QLabel("Ephemeris (ascii)"));
296 layout->addLayout(bl1, 3, 2, 1, 2);
297
298 layout->addWidget(new QLabel("RINEX directory"), 4, 0, 1, 2);
299 layout->addWidget(_rnxPathLineEdit, 4, 2);
300
301 layout->addWidget(new QLabel("RINEX v3"), 4, 3, 1, 2);
302 layout->addWidget(_rnxV3CheckBox, 4, 4);
303 _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>"));
304
305 layout->addWidget(new QLabel("RINEX script (full path)"), 5, 0, 1, 2);
306 layout->addWidget(_rnxScrpLineEdit, 5, 2, 1, 3);
307
308 layout->addWidget(new QLabel("File interval"), 6, 0, 1, 2);
309
310 QBoxLayout* bl = new QBoxLayout(QBoxLayout::LeftToRight);
311 bl->addWidget(_rnxIntrComboBox);
312 bl->addWidget(new QLabel("RINEX"));
313 bl->addWidget(_ephIntrComboBox);
314 bl->addWidget(new QLabel("Ephemeris"));
315 layout->addLayout(bl, 6, 2, 1, 1);
316
317 layout->addWidget(new QLabel("Sampling"), 6, 3);
318 layout->addWidget(_rnxSamplSpinBox, 6, 4);
319
320 layout->addWidget(new QLabel("RINEX skeleton extension"), 7, 0, 1, 2);
321 layout->addWidget(_rnxSkelLineEdit, 7, 2);
322
323 layout->addWidget(new QLabel("Append files"), 7, 3);
324 layout->addWidget(_rnxAppendCheckBox, 7, 4);
325
326 layout->addWidget(new QLabel("Ephemeris directory"), 8, 0, 1, 2);
327 layout->addWidget(_ephPathLineEdit, 8, 2);
328
329 layout->addWidget(new QLabel("RINEX v3"), 8, 3, 1, 2);
330 layout->addWidget(_ephV3CheckBox, 8, 4);
331 _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>"));
332
333 layout->addWidget(new QLabel("Mountpoints"), 9, 0, 1, 2);
334
335 layout->addWidget(_mountPointsTable, 10, 0, 1, 5);
336
337 layout->addWidget(new QLabel("Log (full path)"), 11, 0, 1, 2);
338 layout->addWidget(_logFileLineEdit, 11, 2, 1, 3);
339 layout->addWidget(_log, 12, 0, 1, 5);
340}
341
342// Destructor
343////////////////////////////////////////////////////////////////////////////
344bncWindow::~bncWindow() {
345}
346
347// Retrieve Table
348////////////////////////////////////////////////////////////////////////////
349void bncWindow::slotAddMountPoints() {
350
351 QSettings settings;
352 QString proxyHost = settings.value("proxyHost").toString();
353 int proxyPort = settings.value("proxyPort").toInt();
354 if (proxyHost != _proxyHostLineEdit->text() ||
355 proxyPort != _proxyPortLineEdit->text().toInt()) {
356 int iRet = QMessageBox::question(this, "Question", "Proxy options "
357 "changed. Use the new ones?",
358 QMessageBox::Yes, QMessageBox::No,
359 QMessageBox::NoButton);
360 if (iRet == QMessageBox::Yes) {
361 settings.setValue("proxyHost", _proxyHostLineEdit->text());
362 settings.setValue("proxyPort", _proxyPortLineEdit->text());
363 }
364 }
365
366 bncTableDlg* dlg = new bncTableDlg(this);
367 dlg->move(this->pos().x()+50, this->pos().y()+50);
368 connect(dlg, SIGNAL(newMountPoints(QStringList*)),
369 this, SLOT(slotNewMountPoints(QStringList*)));
370 dlg->exec();
371 delete dlg;
372
373}
374
375// Delete Selected Mount Points
376////////////////////////////////////////////////////////////////////////////
377void bncWindow::slotDeleteMountPoints() {
378
379 int nRows = _mountPointsTable->rowCount();
380 bool flg[nRows];
381 for (int iRow = 0; iRow < nRows; iRow++) {
382 if (_mountPointsTable->isItemSelected(_mountPointsTable->item(iRow,1))) {
383 flg[iRow] = true;
384 }
385 else {
386 flg[iRow] = false;
387 }
388 }
389 for (int iRow = nRows-1; iRow >= 0; iRow--) {
390 if (flg[iRow]) {
391 _mountPointsTable->removeRow(iRow);
392 }
393 }
394 _actDeleteMountPoints->setEnabled(false);
395
396 if (_mountPointsTable->rowCount() == 0) {
397 _actGetData->setEnabled(false);
398 }
399}
400
401// New Mount Points Selected
402////////////////////////////////////////////////////////////////////////////
403void bncWindow::slotNewMountPoints(QStringList* mountPoints) {
404 int iRow = 0;
405 QListIterator<QString> it(*mountPoints);
406 while (it.hasNext()) {
407 QStringList hlp = it.next().split(" ");
408 QUrl url(hlp[0]);
409 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
410 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
411 QString nmea(hlp[4]);
412
413 _mountPointsTable->insertRow(iRow);
414
415 QTableWidgetItem* it;
416 it = new QTableWidgetItem(url.userInfo());
417 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
418 _mountPointsTable->setItem(iRow, 0, it);
419
420 it = new QTableWidgetItem(fullPath);
421 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
422 _mountPointsTable->setItem(iRow, 1, it);
423
424 it = new QTableWidgetItem(format);
425 _mountPointsTable->setItem(iRow, 2, it);
426
427 if (nmea == "yes") {
428 it = new QTableWidgetItem(latitude);
429 _mountPointsTable->setItem(iRow, 3, it);
430 it = new QTableWidgetItem(longitude);
431 _mountPointsTable->setItem(iRow, 4, it);
432 } else {
433 it = new QTableWidgetItem(latitude);
434 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
435 _mountPointsTable->setItem(iRow, 3, it);
436 it = new QTableWidgetItem(longitude);
437 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
438 _mountPointsTable->setItem(iRow, 4, it);
439 }
440
441 it = new QTableWidgetItem(nmea);
442 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
443 _mountPointsTable->setItem(iRow, 5, it);
444
445 bncTableItem* bncIt = new bncTableItem();
446 _mountPointsTable->setItem(iRow, 6, bncIt);
447
448 iRow++;
449 }
450 _mountPointsTable->hideColumn(0);
451 _mountPointsTable->sortItems(1);
452 if (mountPoints->count() > 0) {
453 _actGetData->setEnabled(true);
454 }
455 delete mountPoints;
456}
457
458// Save Options
459////////////////////////////////////////////////////////////////////////////
460void bncWindow::slotSaveOptions() {
461 QSettings settings;
462 settings.setValue("proxyHost", _proxyHostLineEdit->text());
463 settings.setValue("proxyPort", _proxyPortLineEdit->text());
464 settings.setValue("waitTime", _waitTimeSpinBox->value());
465 settings.setValue("outFile", _outFileLineEdit->text());
466 settings.setValue("outPort", _outPortLineEdit->text());
467 settings.setValue("outEphPort", _outEphPortLineEdit->text());
468 settings.setValue("rnxPath", _rnxPathLineEdit->text());
469 settings.setValue("ephPath", _ephPathLineEdit->text());
470 settings.setValue("rnxScript", _rnxScrpLineEdit->text());
471 settings.setValue("rnxIntr", _rnxIntrComboBox->currentText());
472 settings.setValue("ephIntr", _ephIntrComboBox->currentText());
473 settings.setValue("rnxSampl", _rnxSamplSpinBox->value());
474 settings.setValue("rnxSkel", _rnxSkelLineEdit->text());
475 settings.setValue("rnxAppend", _rnxAppendCheckBox->checkState());
476 settings.setValue("rnxV3", _rnxV3CheckBox->checkState());
477 settings.setValue("ephV3", _ephV3CheckBox->checkState());
478 settings.setValue("logFile", _logFileLineEdit->text());
479
480QStringList mountPoints;
481
482 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
483 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
484 "@" + _mountPointsTable->item(iRow, 1)->text() );
485
486 mountPoints.append(url.toString() + " " +
487 _mountPointsTable->item(iRow, 2)->text()
488 + " " + _mountPointsTable->item(iRow, 3)->text()
489 + " " + _mountPointsTable->item(iRow, 4)->text()
490 + " " + _mountPointsTable->item(iRow, 5)->text());
491 }
492 settings.setValue("mountPoints", mountPoints);
493}
494
495// All get slots terminated
496////////////////////////////////////////////////////////////////////////////
497void bncWindow::slotGetThreadErrors() {
498 slotMessage("All Get Threads Terminated");
499 ((bncApp*)qApp)->slotMessage("All Get Threads Terminated");
500 _actAddMountPoints->setEnabled(true);
501 _actGetData->setEnabled(true);
502}
503
504// Retrieve Data
505////////////////////////////////////////////////////////////////////////////
506void bncWindow::slotGetData() {
507 slotSaveOptions();
508
509 _actAddMountPoints->setEnabled(false);
510 _actDeleteMountPoints->setEnabled(false);
511 _actGetData->setEnabled(false);
512 _actStop->setEnabled(true);
513
514 _caster = new bncCaster(_outFileLineEdit->text(),
515 _outPortLineEdit->text().toInt());
516
517 ((bncApp*)qApp)->setPort(_outEphPortLineEdit->text().toInt());
518
519 connect(_caster, SIGNAL(getThreadErrors()),
520 this, SLOT(slotGetThreadErrors()));
521
522 connect(_caster, SIGNAL(newMessage(const QByteArray&)),
523 this, SLOT(slotMessage(const QByteArray&)));
524 connect(_caster, SIGNAL(newMessage(const QByteArray&)),
525 (bncApp*)qApp, SLOT(slotMessage(const QByteArray&)));
526
527 slotMessage("============ Start BNC ============");
528 ((bncApp*)qApp)->slotMessage("============ Start BNC ============");
529
530 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
531 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
532 "@" + _mountPointsTable->item(iRow, 1)->text() );
533
534 QByteArray format = _mountPointsTable->item(iRow, 2)->text().toAscii();
535
536 QByteArray latitude = _mountPointsTable->item(iRow, 3)->text().toAscii();
537 QByteArray longitude = _mountPointsTable->item(iRow, 4)->text().toAscii();
538 QByteArray nmea = _mountPointsTable->item(iRow, 5)->text().toAscii();
539
540 bncGetThread* getThread = new bncGetThread(url, format, latitude, longitude, nmea, iRow);
541
542 connect(getThread, SIGNAL(newMessage(const QByteArray&)),
543 this, SLOT(slotMessage(const QByteArray&)));
544 connect(getThread, SIGNAL(newMessage(const QByteArray&)),
545 (bncApp*)qApp, SLOT(slotMessage(const QByteArray&)));
546
547 connect(getThread, SIGNAL(newBytes(const QByteArray, double)),
548 (bncTableItem*) _mountPointsTable->item(iRow, 6),
549 SLOT(slotNewBytes(const QByteArray, double)));
550
551 _caster->addGetThread(getThread);
552
553 getThread->start();
554 }
555}
556
557// Retrieve Data
558////////////////////////////////////////////////////////////////////////////
559void bncWindow::slotStop() {
560 int iRet = QMessageBox::question(this, "Stop", "Stop retrieving data?",
561 QMessageBox::Yes, QMessageBox::No,
562 QMessageBox::NoButton);
563 if (iRet == QMessageBox::Yes) {
564 delete _caster; _caster = 0;
565 _actGetData->setEnabled(true);
566 _actStop->setEnabled(false);
567 _actAddMountPoints->setEnabled(true);
568 }
569}
570
571// Close Application gracefully
572////////////////////////////////////////////////////////////////////////////
573void bncWindow::closeEvent(QCloseEvent* event) {
574
575 int iRet = QMessageBox::question(this, "Close", "Save Options?",
576 QMessageBox::Yes, QMessageBox::No,
577 QMessageBox::Cancel);
578
579 if (iRet == QMessageBox::Cancel) {
580 event->ignore();
581 return;
582 }
583 else if (iRet == QMessageBox::Yes) {
584 slotSaveOptions();
585 }
586
587 QMainWindow::closeEvent(event);
588 delete this;
589}
590
591// User changed the selection of mountPoints
592////////////////////////////////////////////////////////////////////////////
593void bncWindow::slotSelectionChanged() {
594 if (_mountPointsTable->selectedItems().isEmpty()) {
595 _actDeleteMountPoints->setEnabled(false);
596 }
597 else {
598 _actDeleteMountPoints->setEnabled(true);
599 }
600}
601
602// Display Program Messages
603////////////////////////////////////////////////////////////////////////////
604void bncWindow::slotMessage(const QByteArray msg) {
605
606 const int maxBufferSize = 10000;
607
608 QString txt = _log->toPlainText() + "\n" +
609 QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ") + msg;
610 _log->clear();
611 _log->append(txt.right(maxBufferSize));
612}
613
614// About Message
615////////////////////////////////////////////////////////////////////////////
616void bncWindow::slotAbout() {
617
618 QTextBrowser* tb = new QTextBrowser;
619 QUrl url; url.setPath(":bncabout.html");
620 tb->setSource(url);
621 tb->setReadOnly(true);
622
623 QDialog dlg(this);
624
625 QGridLayout* dlgLayout = new QGridLayout();
626 QLabel* img = new QLabel();
627 img->setPixmap(QPixmap(":ntrip-logo.png"));
628 dlgLayout->addWidget(img, 0,0);
629 dlgLayout->addWidget(new QLabel("BKG NTRIP Client (BNC) Version 1.5"), 0,1);
630 dlgLayout->addWidget(tb,1,0,1,2);
631
632 dlg.setLayout(dlgLayout);
633 int ww = QFontMetrics(font()).width('w');
634 dlg.resize(60*ww, 60*ww);
635 dlg.exec();
636}
637
638// Help Window
639////////////////////////////////////////////////////////////////////////////
640void bncWindow::slotHelp() {
641 QUrl url;
642 url.setPath(":bnchelp.html");
643 new bncHlpDlg(this, url);
644}
645
646// Select Fonts
647////////////////////////////////////////////////////////////////////////////
648void bncWindow::slotFontSel() {
649 bool ok;
650 QFont newFont = QFontDialog::getFont(&ok, this->font(), this);
651 if (ok) {
652 QSettings settings;
653 settings.setValue("font", newFont.toString());
654 QApplication::setFont(newFont);
655 int ww = QFontMetrics(newFont).width('w');
656 setMinimumSize(60*ww, 80*ww);
657 resize(60*ww, 80*ww);
658 }
659}
660
661// Whats This Help
662void bncWindow::slotWhatsThis() {
663QWhatsThis::enterWhatsThisMode();
664}
665
666
Note: See TracBrowser for help on using the repository browser.