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

Last change on this file since 665 was 660, checked in by weber, 17 years ago

* empty log message *

File size: 35.9 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>If you are running BNC within a protected Local Area Network (LAN), you might need to use a proxy server to access the Internet. Enter your proxy server IP 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 the proxy server settings in your Internet browser or ask your network administrator.</p><p>Note that IP streaming is often not allowed in a LAN. In this case you need to ask your network administrator for an appropriate modification of the local security policy or for the installation of a TCP relay to the NTRIP broadcasters. If these are not possible, you might need to run BNC outside your LAN on a host that has unobstructed connection to the Internet.</p>"));
137 _proxyPortLineEdit = new QLineEdit(settings.value("proxyPort").toString());
138 _proxyPortLineEdit->setMaximumWidth(9*ww);
139 _proxyPortLineEdit->setWhatsThis(tr("<p>If you are running BNC within a protected Local Area Network (LAN), you might need to use a proxy server to access the Internet. Enter your proxy server IP 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 the proxy server settings in your Internet browser or ask your network administrator.</p><p>Note that IP streaming is often not allowed in a LAN. In this case you need to ask your network administrator for an appropriate modification of the local security policy or for the installation of a TCP relay to the NTRIP broadcasters. If these are not possible, you might need to run BNC outside your LAN on a host that has unobstructed connection to the Internet.</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>When feeding a real-time GNSS engine waiting for input epoch by epoch, BNC drops 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 acceptable for your real-time GNSS product.</p><p>Note that 'Wait for full epoch' does not effect the RINEX Observation file content. Observations received later than 'Wait for full epoch' seconds will still be included in the RINEX Observation files.</p>"));
148 _outFileLineEdit = new QLineEdit(settings.value("outFile").toString());
149 _outFileLineEdit->setWhatsThis(tr("<p>Specify the full path to a file where synchrozined observations are saved in plain ASCII format. Beware that the size of this file can rapidly increase depending on the number of incoming streams.</p>"));
150 _outPortLineEdit = new QLineEdit(settings.value("outPort").toString());
151 _outPortLineEdit->setMaximumWidth(9*ww);
152 _outPortLineEdit->setWhatsThis(tr("<p>BNC can produce synchronized observations in binary format on your local host through an IP port. Specify an IP port number here to activate this function.</p>"));
153 _outEphPortLineEdit = new QLineEdit(settings.value("outEphPort").toString());
154 _outEphPortLineEdit->setMaximumWidth(9*ww);
155 _outEphPortLineEdit->setWhatsThis(tr("<p>BNC can produce ephemeris data in ASCII format on your local host through an IP port. Specify an IP port number here to activate this function.</p>"));
156 _rnxPathLineEdit = new QLineEdit(settings.value("rnxPath").toString());
157 _rnxPathLineEdit->setWhatsThis(tr("<p>Here you specify the path to where the RINEX Observation files will be stored. If the specified directory does not exist, BNC will not create RINEX Observation files.</p>"));
158 _ephPathLineEdit = new QLineEdit(settings.value("ephPath").toString());
159 _ephPathLineEdit->setWhatsThis(tr("<p>Specify the path for saving Broadcast Ephemeris data as RINEX Navigation files. If the specified directory does not exist, BNC will not create RINEX Navigation files.</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 Observation file is saved, you might want to compress, copy or upload it immediately via FTP. BNC allows you to execute a script/batch file to carry out these operations. To do that specify the full path of the script/batch file here. BNC will pass the RINEX Observation file path to the script as a command line parameter (%1 on Windows systems, $1 onUnix/Linux systems).</p><p>The triggering event for calling the script or batchfile is the end of a RINEX Observation 'File interval'. If that is overridden by a stream outage, the triggering event is the stream reconnection.</p>"));
167 _rnxSkelLineEdit = new QLineEdit(settings.value("rnxSkel").toString());
168 _rnxSkelLineEdit->setMaximumWidth(5*ww);
169 _rnxSkelLineEdit->setWhatsThis(tr("<p>Whenever BNC starts generating RINEX Observation 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, sometimes public RINEX header skeleton files are not available, its contents is not up to date, or you need to put additional/optional records in the RINEX header.</p><p>For that BNC allows using personal skeleton files that contain the header records you would like to include. You can 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 corresponding stream.</p>"));
170 _rnxAppendCheckBox = new QCheckBox();
171 _rnxAppendCheckBox->setCheckState(Qt::CheckState(
172 settings.value("rnxAppend").toInt()));
173 _rnxAppendCheckBox->setWhatsThis(tr("<p>When BNC is started, new RINEX Observation files are created by default and any existing files with the same name will be overwritten. However, users might want to append observations and ephemeris to existing RINEX files following a restart of BNC, a system crash or when BNC crashed. Tick 'Append files' to continue with existing files and keep what has been recorded so far.</p>"));
174 _rnxIntrComboBox = new QComboBox();
175 _rnxIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Observation file.</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 the length of the RINEX Navigation file.</p>"));
185 _ephIntrComboBox->setMaximumWidth(9*ww);
186 _ephIntrComboBox->setEditable(false);
187 _ephIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 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 Observation sampling interval in seconds. A value of zero '0' tells BNC to store all received epochs into RINEX.</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 _inspSegmSpinBox = new QSpinBox();
201 _inspSegmSpinBox->setWhatsThis(tr("<p>Select the RINEX Observation sampling interval in seconds. A value of zero '0' tells BNC to store all received epochs into RINEX.</p>"));
202 _inspSegmSpinBox->setMinimum(0);
203 _inspSegmSpinBox->setMaximum(60);
204 _inspSegmSpinBox->setSingleStep(1);
205 _inspSegmSpinBox->setMaximumWidth(9*ww);
206 _inspSegmSpinBox->setValue(settings.value("inspSegm").toInt());
207 _inspSegmSpinBox->setSuffix(" sec");
208 _inspSegmSpinBox->setWhatsThis(tr("<p>BNC can collect all returns (success or failure) coming from a decoder within a certain short time span (Inspect segment) to then decide whether a stream content is corrupted or not. When a continuous problem is detected, BNC can inform its operator about this event through a Notice advisory. A value of about 15 sec (default) as 'Inspect segment' is recommended when handling 1Hz data.</p><p>A value of zero '0' means that you don't want BNC to inform you about incoming data that can not be decoded.</p>"));
209 _noticeRecoSpinBox = new QSpinBox();
210 _noticeRecoSpinBox->setMinimum(0);
211 _noticeRecoSpinBox->setMaximum(60);
212 _noticeRecoSpinBox->setSingleStep(1);
213 _noticeRecoSpinBox->setSuffix(" min");
214 _noticeRecoSpinBox->setMaximumWidth(9*ww);
215 _noticeRecoSpinBox->setValue(settings.value("noticeReco").toInt());
216 _noticeRecoSpinBox->setWhatsThis(tr("<p>Following a stream outage or a longer series of corrupted observations, a Notice advisory is generated when at least one valid observation is received again within the 'Recovery' threshold time span defined here. A value of about 5min (default) is recommendable.</p><p>A value of zero '0' means that for any stream recovery BNC immediately generates a Notice advisory!</p><p>Note that using this function for corrupted streams needs an 'Inspect segment' greater zero '0'.</p>"));
217 _noticeFailSpinBox = new QSpinBox();
218 _noticeFailSpinBox->setMinimum(0);
219 _noticeFailSpinBox->setMaximum(60);
220 _noticeFailSpinBox->setSingleStep(1);
221 _noticeFailSpinBox->setSuffix(" min");
222 _noticeFailSpinBox->setMaximumWidth(9*ww);
223 _noticeFailSpinBox->setValue(settings.value("noticeFail").toInt());
224 _noticeFailSpinBox->setWhatsThis(tr("<p>A Notice advisory is generated when no (or corrupted) observations are received throughout the 'Failure' threshold time span defined here. A value of about 15 min (default) is recommendable.</p><p>A value of zero '0' means that for any stream failure BNC immediately generates a Notice advisory!</p><p>Note that using this function for corrupted streams needs an 'Inspect segment' greater zero '0'.</p>"));
225 _logFileLineEdit = new QLineEdit(settings.value("logFile").toString());
226 _logFileLineEdit->setWhatsThis(tr("<p>Records of BNC's activities are shown in the 'Log' section below. They can be saved into a file when a valid path is specified in the 'Log (full path)' field.</p>"));
227 _noticeScriptLineEdit = new QLineEdit(settings.value("noticeScript").toString());
228 _noticeScriptLineEdit->setWhatsThis(tr("<p>Specify the full path to a script or batch file to handle Notice advisories generated in case of corrupted streams of stream outages. The affected mountpoint and one of the comments 'Begin_Outage', 'End_Outage', 'Begin_Currupted', or 'End_Corrupted' are passed on to the script as two command line parameters.</p><p>The script may be used to send an email to BNC's operator and/or to the affected streamprovider. An empty option field or invalid path means that you don't want to use this option.</p>"));
229 _mountPointsTable = new QTableWidget(0,7);
230 _mountPointsTable->setWhatsThis(tr("<p>Streams selected for retrieval are listed in the 'Mountpoints' section. Button 'Add Mountpoints' opens a window that allows the user to select data streams from an NTRIP broadcaster according to their mountpoints. To remove a stream from the 'Mountpoints' list, highlight it by clicking on it and hit the 'Delete Mountpoints' button. You can also remove multiple mountpoints simultaneously by highlighting them using +Shift and +Ctrl.</p><p>BNC automatically allocates one of its internal decoders to a stream based on the stream's 'format' and 'format-details' as given in the source-table. However, there might be cases where you need to override the automatic selection due to incorrect source-table for example. BNC allows users to manually select the required decoder by editing the decoder string. Doubleclick on the 'decoder' field, enter your preferred decoder and then hit Enter. The accepted decoder strings are 'RTCM_2.x', 'RTCM_3.x', and 'RTIGS'.</p><p>In case you need to log the raw data as is, BNC allows users to by-pass its decoders and and directly save the input in daily log files. To do this specify the decoder string as 'ZERO'.</p><p>BNC can also retrieve streams from virtual reference stations (VRS). To initiate these streams, an approximate rover position needs to be sent in NMEA format to the NTRIP broadcaster. In return, a user-specific data stream is generated, typically by a Network-RTK software. This stream is customized to the exact latitude and longitude as shown in the 'lat' and 'long' columns under 'Mountpoints'. These VRS streams are indicated by a 'yes' in the 'nmea' column under 'Mountpoints' as well as in the source-table. The default 'lat' and 'long' values are taken from the source-table. However, in most cases you would probably want to change this according to your requirement. Double-click on 'lat' and 'long' fields, enter the values you wish to send and then hit Enter. The format is in positive north latitude degrees (e.g. for northern hemisphere: 52.436, for southern hemisphere: -24.567) and eastern longitude degrees (example: 358.872 or -1.128). Only mountpoints with a 'yes' in its 'nmea' column can be edited. The position must preferably be a point within the service area of the network.</p>"));
231
232 _mountPointsTable->horizontalHeader()->resizeSection(1,25*ww);
233 _mountPointsTable->horizontalHeader()->resizeSection(2,9*ww);
234 _mountPointsTable->horizontalHeader()->resizeSection(3,7*ww);
235 _mountPointsTable->horizontalHeader()->resizeSection(4,7*ww);
236 _mountPointsTable->horizontalHeader()->resizeSection(5,5*ww);
237 _mountPointsTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
238 _mountPointsTable->horizontalHeader()->setStretchLastSection(true);
239 _mountPointsTable->setHorizontalHeaderLabels(labels);
240 _mountPointsTable->setGridStyle(Qt::NoPen);
241 _mountPointsTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
242 _mountPointsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
243 _mountPointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
244 QListIterator<QString> it(settings.value("mountPoints").toStringList());
245 if (!it.hasNext()) {
246 _actGetData->setEnabled(false);
247 }
248 int iRow = 0;
249 while (it.hasNext()) {
250 QStringList hlp = it.next().split(" ");
251 if (hlp.size() < 5) continue;
252 _mountPointsTable->insertRow(iRow);
253
254 QUrl url(hlp[0]);
255
256 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
257 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
258 QString nmea(hlp[4]);
259
260 QTableWidgetItem* it;
261 it = new QTableWidgetItem(url.userInfo());
262 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
263 _mountPointsTable->setItem(iRow, 0, it);
264
265 it = new QTableWidgetItem(fullPath);
266 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
267 _mountPointsTable->setItem(iRow, 1, it);
268
269 it = new QTableWidgetItem(format);
270 _mountPointsTable->setItem(iRow, 2, it);
271
272 if (nmea == "yes") {
273 it = new QTableWidgetItem(latitude);
274 _mountPointsTable->setItem(iRow, 3, it);
275 it = new QTableWidgetItem(longitude);
276 _mountPointsTable->setItem(iRow, 4, it);
277 } else {
278 it = new QTableWidgetItem(latitude);
279 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
280 _mountPointsTable->setItem(iRow, 3, it);
281 it = new QTableWidgetItem(longitude);
282 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
283 _mountPointsTable->setItem(iRow, 4, it);
284 }
285
286 it = new QTableWidgetItem(nmea);
287 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
288 _mountPointsTable->setItem(iRow, 5, it);
289
290 bncTableItem* bncIt = new bncTableItem();
291 bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
292 _mountPointsTable->setItem(iRow, 6, bncIt);
293
294 iRow++;
295 }
296 _mountPointsTable->hideColumn(0);
297 _mountPointsTable->sortItems(1);
298
299 connect(_mountPointsTable, SIGNAL(itemSelectionChanged()),
300 SLOT(slotSelectionChanged()));
301
302 _log = new QTextBrowser();
303 _log->setReadOnly(true);
304
305 _log->setWhatsThis(tr("Records of BNC's activities are shown in the 'Log' section. The message log covers the communication status between BNC and the NTRIP broadcaster as well as problems that may occur in the communication link, stream availability, stream delay, stream conversion etc."));
306
307 layout->addWidget(new QLabel("Proxy host"), 0, 0, 1, 2);
308 layout->addWidget(_proxyHostLineEdit, 0, 2);
309 layout->addWidget(new QLabel("Proxy port"), 0, 3);
310 layout->addWidget(_proxyPortLineEdit, 0, 4);
311
312 layout->addWidget(new QLabel("Wait for full epoch"), 1, 0, 1, 2);
313 layout->addWidget(_waitTimeSpinBox, 1, 2);
314
315 layout->addWidget(new QLabel("ASCII output file (full path)"), 2, 0, 1, 2);
316 layout->addWidget(_outFileLineEdit, 2, 2, 1, 3);
317
318 layout->addWidget(new QLabel("Ports for output"), 3, 0, 1, 2);
319 QBoxLayout* bl1 = new QBoxLayout(QBoxLayout::LeftToRight);
320 bl1->addWidget(_outPortLineEdit);
321 bl1->addWidget(new QLabel("Observations (binary)"));
322 bl1->addStretch();
323 bl1->addWidget(_outEphPortLineEdit);
324 bl1->addWidget(new QLabel("Ephemeris (ascii)"));
325 layout->addLayout(bl1, 3, 2, 1, 2);
326
327 layout->addWidget(new QLabel("RINEX directory"), 4, 0, 1, 2);
328 layout->addWidget(_rnxPathLineEdit, 4, 2);
329
330 layout->addWidget(new QLabel("RINEX v3"), 4, 3, 1, 2);
331 layout->addWidget(_rnxV3CheckBox, 4, 4);
332 _rnxV3CheckBox->setWhatsThis(tr("<p>Default format for RINEX Observation files is RINEX Version 2.11. Select 'RINEX v3' if you want to save the observations in RINEX Version 3 format.</p>"));
333
334 layout->addWidget(new QLabel("RINEX script (full path)"), 5, 0, 1, 2);
335 layout->addWidget(_rnxScrpLineEdit, 5, 2, 1, 3);
336
337 layout->addWidget(new QLabel("File intervals"), 6, 0, 1, 2);
338
339 QBoxLayout* bl = new QBoxLayout(QBoxLayout::LeftToRight);
340 bl->addWidget(_rnxIntrComboBox);
341 bl->addWidget(new QLabel("RINEX"));
342 bl->addWidget(_ephIntrComboBox);
343 bl->addWidget(new QLabel("Ephemeris"));
344 layout->addLayout(bl, 6, 2, 1, 1);
345
346 layout->addWidget(new QLabel("Sampling"), 6, 3);
347 layout->addWidget(_rnxSamplSpinBox, 6, 4);
348
349 layout->addWidget(new QLabel("RINEX skeleton extension"), 7, 0, 1, 2);
350 layout->addWidget(_rnxSkelLineEdit, 7, 2);
351
352 layout->addWidget(new QLabel("Append files"), 7, 3);
353 layout->addWidget(_rnxAppendCheckBox, 7, 4);
354
355 layout->addWidget(new QLabel("Ephemeris directory"), 8, 0, 1, 2);
356 layout->addWidget(_ephPathLineEdit, 8, 2);
357
358 layout->addWidget(new QLabel("RINEX v3"), 8, 3, 1, 2);
359 layout->addWidget(_ephV3CheckBox, 8, 4);
360 _ephV3CheckBox->setWhatsThis(tr("<p>Default format for RINEX Navigation files containing Broadcast Ephemeris is RINEX Version 2.11. Select 'RINEX v3' if you want to save the ephemeris in RINEX Version 3 format.</p>"));
361
362 layout->addWidget(new QLabel("Notice thresholds"), 9, 0, 1, 2);
363 QBoxLayout* bl2 = new QBoxLayout(QBoxLayout::LeftToRight);
364 bl2->addWidget(_noticeFailSpinBox);
365 bl2->addWidget(new QLabel("Failure"));
366 bl2->addWidget(_noticeRecoSpinBox);
367 bl2->addWidget(new QLabel("Recovery"));
368 bl2->addWidget(new QLabel("Inspect segment"));
369 bl2->addWidget(_inspSegmSpinBox);
370 layout->addLayout(bl2, 9, 2, 1, 3);
371
372 layout->addWidget(new QLabel("Notice script (full path)"), 10, 0, 1, 2);
373 layout->addWidget(_noticeScriptLineEdit, 10, 2, 1, 3);
374
375 layout->addWidget(new QLabel("Mountpoints"), 11, 0, 1, 2);
376
377 layout->addWidget(_mountPointsTable, 12, 0, 1, 5);
378
379 layout->addWidget(new QLabel("Log (full path)"), 13, 0, 1, 2);
380 layout->addWidget(_logFileLineEdit, 13, 2, 1, 3);
381 layout->addWidget(_log, 14, 0, 1, 5);
382}
383
384// Destructor
385////////////////////////////////////////////////////////////////////////////
386bncWindow::~bncWindow() {
387 delete _caster;
388}
389
390// Retrieve Table
391////////////////////////////////////////////////////////////////////////////
392void bncWindow::slotAddMountPoints() {
393
394 QSettings settings;
395 QString proxyHost = settings.value("proxyHost").toString();
396 int proxyPort = settings.value("proxyPort").toInt();
397 if (proxyHost != _proxyHostLineEdit->text() ||
398 proxyPort != _proxyPortLineEdit->text().toInt()) {
399 int iRet = QMessageBox::question(this, "Question", "Proxy options "
400 "changed. Use the new ones?",
401 QMessageBox::Yes, QMessageBox::No,
402 QMessageBox::NoButton);
403 if (iRet == QMessageBox::Yes) {
404 settings.setValue("proxyHost", _proxyHostLineEdit->text());
405 settings.setValue("proxyPort", _proxyPortLineEdit->text());
406 }
407 }
408
409 bncTableDlg* dlg = new bncTableDlg(this);
410 dlg->move(this->pos().x()+50, this->pos().y()+50);
411 connect(dlg, SIGNAL(newMountPoints(QStringList*)),
412 this, SLOT(slotNewMountPoints(QStringList*)));
413 dlg->exec();
414 delete dlg;
415
416}
417
418// Delete Selected Mount Points
419////////////////////////////////////////////////////////////////////////////
420void bncWindow::slotDeleteMountPoints() {
421
422 int nRows = _mountPointsTable->rowCount();
423 bool flg[nRows];
424 for (int iRow = 0; iRow < nRows; iRow++) {
425 if (_mountPointsTable->isItemSelected(_mountPointsTable->item(iRow,1))) {
426 flg[iRow] = true;
427 }
428 else {
429 flg[iRow] = false;
430 }
431 }
432 for (int iRow = nRows-1; iRow >= 0; iRow--) {
433 if (flg[iRow]) {
434 _mountPointsTable->removeRow(iRow);
435 }
436 }
437 _actDeleteMountPoints->setEnabled(false);
438
439 if (_mountPointsTable->rowCount() == 0) {
440 _actGetData->setEnabled(false);
441 }
442}
443
444// New Mount Points Selected
445////////////////////////////////////////////////////////////////////////////
446void bncWindow::slotNewMountPoints(QStringList* mountPoints) {
447 int iRow = 0;
448 QListIterator<QString> it(*mountPoints);
449 while (it.hasNext()) {
450 QStringList hlp = it.next().split(" ");
451 QUrl url(hlp[0]);
452 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
453 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
454 QString nmea(hlp[4]);
455
456 _mountPointsTable->insertRow(iRow);
457
458 QTableWidgetItem* it;
459 it = new QTableWidgetItem(url.userInfo());
460 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
461 _mountPointsTable->setItem(iRow, 0, it);
462
463 it = new QTableWidgetItem(fullPath);
464 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
465 _mountPointsTable->setItem(iRow, 1, it);
466
467 it = new QTableWidgetItem(format);
468 _mountPointsTable->setItem(iRow, 2, it);
469
470 if (nmea == "yes") {
471 it = new QTableWidgetItem(latitude);
472 _mountPointsTable->setItem(iRow, 3, it);
473 it = new QTableWidgetItem(longitude);
474 _mountPointsTable->setItem(iRow, 4, it);
475 } else {
476 it = new QTableWidgetItem(latitude);
477 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
478 _mountPointsTable->setItem(iRow, 3, it);
479 it = new QTableWidgetItem(longitude);
480 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
481 _mountPointsTable->setItem(iRow, 4, it);
482 }
483
484 it = new QTableWidgetItem(nmea);
485 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
486 _mountPointsTable->setItem(iRow, 5, it);
487
488 bncTableItem* bncIt = new bncTableItem();
489 _mountPointsTable->setItem(iRow, 6, bncIt);
490
491 iRow++;
492 }
493 _mountPointsTable->hideColumn(0);
494 _mountPointsTable->sortItems(1);
495 if (mountPoints->count() > 0) {
496 _actGetData->setEnabled(true);
497 }
498 delete mountPoints;
499}
500
501// Save Options
502////////////////////////////////////////////////////////////////////////////
503void bncWindow::slotSaveOptions() {
504 QSettings settings;
505 settings.setValue("proxyHost", _proxyHostLineEdit->text());
506 settings.setValue("proxyPort", _proxyPortLineEdit->text());
507 settings.setValue("waitTime", _waitTimeSpinBox->value());
508 settings.setValue("inspSegm", _inspSegmSpinBox->value());
509 settings.setValue("noticeFail", _noticeFailSpinBox->value());
510 settings.setValue("noticeReco", _noticeRecoSpinBox->value());
511 settings.setValue("outFile", _outFileLineEdit->text());
512 settings.setValue("outPort", _outPortLineEdit->text());
513 settings.setValue("outEphPort", _outEphPortLineEdit->text());
514 settings.setValue("rnxPath", _rnxPathLineEdit->text());
515 settings.setValue("ephPath", _ephPathLineEdit->text());
516 settings.setValue("rnxScript", _rnxScrpLineEdit->text());
517 settings.setValue("rnxIntr", _rnxIntrComboBox->currentText());
518 settings.setValue("ephIntr", _ephIntrComboBox->currentText());
519 settings.setValue("rnxSampl", _rnxSamplSpinBox->value());
520 settings.setValue("rnxSkel", _rnxSkelLineEdit->text());
521 settings.setValue("rnxAppend", _rnxAppendCheckBox->checkState());
522 settings.setValue("rnxV3", _rnxV3CheckBox->checkState());
523 settings.setValue("ephV3", _ephV3CheckBox->checkState());
524 settings.setValue("logFile", _logFileLineEdit->text());
525 settings.setValue("noticeScript",_noticeScriptLineEdit->text());
526
527QStringList mountPoints;
528
529 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
530 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
531 "@" + _mountPointsTable->item(iRow, 1)->text() );
532
533 mountPoints.append(url.toString() + " " +
534 _mountPointsTable->item(iRow, 2)->text()
535 + " " + _mountPointsTable->item(iRow, 3)->text()
536 + " " + _mountPointsTable->item(iRow, 4)->text()
537 + " " + _mountPointsTable->item(iRow, 5)->text());
538 }
539 settings.setValue("mountPoints", mountPoints);
540}
541
542// All get slots terminated
543////////////////////////////////////////////////////////////////////////////
544void bncWindow::slotGetThreadErrors() {
545 slotMessage("All Get Threads Terminated");
546 ((bncApp*)qApp)->slotMessage("All Get Threads Terminated");
547 _actAddMountPoints->setEnabled(true);
548 _actGetData->setEnabled(true);
549}
550
551// Retrieve Data
552////////////////////////////////////////////////////////////////////////////
553void bncWindow::slotGetData() {
554 slotSaveOptions();
555
556 _actAddMountPoints->setEnabled(false);
557 _actDeleteMountPoints->setEnabled(false);
558 _actGetData->setEnabled(false);
559 _actStop->setEnabled(true);
560
561 _caster = new bncCaster(_outFileLineEdit->text(),
562 _outPortLineEdit->text().toInt());
563
564 ((bncApp*)qApp)->setPort(_outEphPortLineEdit->text().toInt());
565
566 connect(_caster, SIGNAL(getThreadErrors()),
567 this, SLOT(slotGetThreadErrors()));
568
569 connect(_caster, SIGNAL(newMessage(QByteArray)),
570 this, SLOT(slotMessage(QByteArray)));
571 connect(_caster, SIGNAL(newMessage(QByteArray)),
572 (bncApp*)qApp, SLOT(slotMessage(QByteArray)));
573
574 slotMessage("============ Start BNC ============");
575 ((bncApp*)qApp)->slotMessage("============ Start BNC ============");
576
577 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
578 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
579 "@" + _mountPointsTable->item(iRow, 1)->text() );
580
581 QByteArray format = _mountPointsTable->item(iRow, 2)->text().toAscii();
582
583 QByteArray latitude = _mountPointsTable->item(iRow, 3)->text().toAscii();
584 QByteArray longitude = _mountPointsTable->item(iRow, 4)->text().toAscii();
585 QByteArray nmea = _mountPointsTable->item(iRow, 5)->text().toAscii();
586
587 bncGetThread* getThread = new bncGetThread(url, format, latitude, longitude, nmea, iRow);
588
589 connect(getThread, SIGNAL(newMessage(QByteArray)),
590 this, SLOT(slotMessage(QByteArray)));
591 connect(getThread, SIGNAL(newMessage(QByteArray)),
592 (bncApp*)qApp, SLOT(slotMessage(QByteArray)));
593
594 connect(getThread, SIGNAL(newBytes(QByteArray, double)),
595 (bncTableItem*) _mountPointsTable->item(iRow, 6),
596 SLOT(slotNewBytes(QByteArray, double)));
597
598 _caster->addGetThread(getThread);
599
600 getThread->start();
601 }
602}
603
604// Retrieve Data
605////////////////////////////////////////////////////////////////////////////
606void bncWindow::slotStop() {
607 int iRet = QMessageBox::question(this, "Stop", "Stop retrieving data?",
608 QMessageBox::Yes, QMessageBox::No,
609 QMessageBox::NoButton);
610 if (iRet == QMessageBox::Yes) {
611 delete _caster; _caster = 0;
612 _actGetData->setEnabled(true);
613 _actStop->setEnabled(false);
614 _actAddMountPoints->setEnabled(true);
615 }
616}
617
618// Close Application gracefully
619////////////////////////////////////////////////////////////////////////////
620void bncWindow::closeEvent(QCloseEvent* event) {
621
622 int iRet = QMessageBox::question(this, "Close", "Save Options?",
623 QMessageBox::Yes, QMessageBox::No,
624 QMessageBox::Cancel);
625
626 if (iRet == QMessageBox::Cancel) {
627 event->ignore();
628 return;
629 }
630 else if (iRet == QMessageBox::Yes) {
631 slotSaveOptions();
632 }
633
634 QMainWindow::closeEvent(event);
635 delete this;
636}
637
638// User changed the selection of mountPoints
639////////////////////////////////////////////////////////////////////////////
640void bncWindow::slotSelectionChanged() {
641 if (_mountPointsTable->selectedItems().isEmpty()) {
642 _actDeleteMountPoints->setEnabled(false);
643 }
644 else {
645 _actDeleteMountPoints->setEnabled(true);
646 }
647}
648
649// Display Program Messages
650////////////////////////////////////////////////////////////////////////////
651void bncWindow::slotMessage(const QByteArray msg) {
652
653 const int maxBufferSize = 10000;
654
655 QString txt = _log->toPlainText() + "\n" +
656 QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ") + msg;
657 _log->clear();
658 _log->append(txt.right(maxBufferSize));
659}
660
661// About Message
662////////////////////////////////////////////////////////////////////////////
663void bncWindow::slotAbout() {
664
665 QTextBrowser* tb = new QTextBrowser;
666 QUrl url; url.setPath(":bncabout.html");
667 tb->setSource(url);
668 tb->setReadOnly(true);
669
670 QDialog dlg(this);
671
672 QGridLayout* dlgLayout = new QGridLayout();
673 QLabel* img = new QLabel();
674 img->setPixmap(QPixmap(":ntrip-logo.png"));
675 dlgLayout->addWidget(img, 0,0);
676 dlgLayout->addWidget(new QLabel("BKG NTRIP Client (BNC) Version 1.5"), 0,1);
677 dlgLayout->addWidget(tb,1,0,1,2);
678
679 dlg.setLayout(dlgLayout);
680 int ww = QFontMetrics(font()).width('w');
681 dlg.resize(60*ww, 60*ww);
682 dlg.exec();
683}
684
685// Help Window
686////////////////////////////////////////////////////////////////////////////
687void bncWindow::slotHelp() {
688 QUrl url;
689 url.setPath(":bnchelp.html");
690 new bncHlpDlg(this, url);
691}
692
693// Select Fonts
694////////////////////////////////////////////////////////////////////////////
695void bncWindow::slotFontSel() {
696 bool ok;
697 QFont newFont = QFontDialog::getFont(&ok, this->font(), this);
698 if (ok) {
699 QSettings settings;
700 settings.setValue("font", newFont.toString());
701 QApplication::setFont(newFont);
702 int ww = QFontMetrics(newFont).width('w');
703 setMinimumSize(60*ww, 80*ww);
704 resize(60*ww, 80*ww);
705 }
706}
707
708// Whats This Help
709void bncWindow::slotWhatsThis() {
710QWhatsThis::enterWhatsThisMode();
711}
712
713
Note: See TracBrowser for help on using the repository browser.