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

Last change on this file since 679 was 679, checked in by weber, 16 years ago

* empty log message *

File size: 38.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 CreateMenu();
101 AddToolbar();
102
103 QSettings settings;
104 _proxyHostLineEdit = new QLineEdit(settings.value("proxyHost").toString());
105// _proxyHostLineEdit->setMaximumWidth(12*ww);
106 _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>"));
107 _proxyPortLineEdit = new QLineEdit(settings.value("proxyPort").toString());
108 _proxyPortLineEdit->setMaximumWidth(9*ww);
109 _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>"));
110 _waitTimeSpinBox = new QSpinBox();
111 _waitTimeSpinBox->setMinimum(1);
112 _waitTimeSpinBox->setMaximum(30);
113 _waitTimeSpinBox->setSingleStep(1);
114 _waitTimeSpinBox->setSuffix(" sec");
115 _waitTimeSpinBox->setMaximumWidth(9*ww);
116 _waitTimeSpinBox->setValue(settings.value("waitTime").toInt());
117 _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>"));
118 _outFileLineEdit = new QLineEdit(settings.value("outFile").toString());
119 _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>"));
120 _outPortLineEdit = new QLineEdit(settings.value("outPort").toString());
121 _outPortLineEdit->setMaximumWidth(9*ww);
122 _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>"));
123 _outEphPortLineEdit = new QLineEdit(settings.value("outEphPort").toString());
124 _outEphPortLineEdit->setMaximumWidth(9*ww);
125 _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>"));
126 _rnxPathLineEdit = new QLineEdit(settings.value("rnxPath").toString());
127 _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>"));
128 _ephPathLineEdit = new QLineEdit(settings.value("ephPath").toString());
129 _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>"));
130
131 _rnxV3CheckBox = new QCheckBox();
132 _rnxV3CheckBox->setCheckState(Qt::CheckState(settings.value("rnxV3").toInt()));
133 _ephV3CheckBox = new QCheckBox();
134 _ephV3CheckBox->setCheckState(Qt::CheckState(settings.value("ephV3").toInt()));
135 _rnxScrpLineEdit = new QLineEdit(settings.value("rnxScript").toString());
136 _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>"));
137 _rnxSkelLineEdit = new QLineEdit(settings.value("rnxSkel").toString());
138 _rnxSkelLineEdit->setMaximumWidth(5*ww);
139 _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>"));
140 _rnxAppendCheckBox = new QCheckBox();
141 _rnxAppendCheckBox->setCheckState(Qt::CheckState(
142 settings.value("rnxAppend").toInt()));
143 _rnxAppendCheckBox->setWhatsThis(tr("<p>When BNC is started, new files are created by default and any existing files with the same name will be overwritten. However, users might want to append already existing 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>"));
144 _rnxIntrComboBox = new QComboBox();
145 _rnxIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Observation file.</p>"));
146 _rnxIntrComboBox->setMaximumWidth(9*ww);
147 _rnxIntrComboBox->setEditable(false);
148 _rnxIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
149 int ii = _rnxIntrComboBox->findText(settings.value("rnxIntr").toString());
150 if (ii != -1) {
151 _rnxIntrComboBox->setCurrentIndex(ii);
152 }
153 _ephIntrComboBox = new QComboBox();
154 _ephIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Navigation file.</p>"));
155 _ephIntrComboBox->setMaximumWidth(9*ww);
156 _ephIntrComboBox->setEditable(false);
157 _ephIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
158 int jj = _ephIntrComboBox->findText(settings.value("ephIntr").toString());
159 if (jj != -1) {
160 _ephIntrComboBox->setCurrentIndex(jj);
161 }
162 _rnxSamplSpinBox = new QSpinBox();
163 _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>"));
164 _rnxSamplSpinBox->setMinimum(0);
165 _rnxSamplSpinBox->setMaximum(60);
166 _rnxSamplSpinBox->setSingleStep(5);
167 _rnxSamplSpinBox->setMaximumWidth(9*ww);
168 _rnxSamplSpinBox->setValue(settings.value("rnxSampl").toInt());
169 _rnxSamplSpinBox->setSuffix(" sec");
170 _inspSegmSpinBox = new QSpinBox();
171 _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>"));
172 _inspSegmSpinBox->setMinimum(0);
173 _inspSegmSpinBox->setMaximum(60);
174 _inspSegmSpinBox->setSingleStep(1);
175 _inspSegmSpinBox->setMaximumWidth(9*ww);
176 _inspSegmSpinBox->setValue(settings.value("inspSegm").toInt());
177 _inspSegmSpinBox->setSuffix(" sec");
178 _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 an Advisory note. 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>"));
179 _adviseRecoSpinBox = new QSpinBox();
180 _adviseRecoSpinBox->setMinimum(0);
181 _adviseRecoSpinBox->setMaximum(60);
182 _adviseRecoSpinBox->setSingleStep(1);
183 _adviseRecoSpinBox->setSuffix(" min");
184 _adviseRecoSpinBox->setMaximumWidth(9*ww);
185 _adviseRecoSpinBox->setValue(settings.value("adviseReco").toInt());
186 _adviseRecoSpinBox->setWhatsThis(tr("<p>Following a stream outage or a longer series of corrupted observations, an Advisory note 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 an Advisory note!</p><p>Note that using this function for corrupted streams needs an 'Inspect segment' greater zero '0'.</p>"));
187 _adviseFailSpinBox = new QSpinBox();
188 _adviseFailSpinBox->setMinimum(0);
189 _adviseFailSpinBox->setMaximum(60);
190 _adviseFailSpinBox->setSingleStep(1);
191 _adviseFailSpinBox->setSuffix(" min");
192 _adviseFailSpinBox->setMaximumWidth(9*ww);
193 _adviseFailSpinBox->setValue(settings.value("adviseFail").toInt());
194 _adviseFailSpinBox->setWhatsThis(tr("<p>An Advisory note 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 an Advisory note!</p><p>Note that using this function for corrupted streams needs an 'Inspect segment' greater zero '0'.</p>"));
195 _logFileLineEdit = new QLineEdit(settings.value("logFile").toString());
196 _logFileLineEdit->setWhatsThis(tr("<p>Records of BNC's activities can be saved into a file when a valid path is specified in the 'Log (full path)' field.</p>"));
197 _adviseScriptLineEdit = new QLineEdit(settings.value("adviseScript").toString());
198 _adviseScriptLineEdit->setWhatsThis(tr("<p>Specify the full path to a script or batch file to handle Advisory notes 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>"));
199 _mountPointsTable = new QTableWidget(0,7);
200 _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>"));
201
202 _mountPointsTable->horizontalHeader()->resizeSection(1,34*ww);
203 _mountPointsTable->horizontalHeader()->resizeSection(2,9*ww);
204 _mountPointsTable->horizontalHeader()->resizeSection(3,7*ww);
205 _mountPointsTable->horizontalHeader()->resizeSection(4,7*ww);
206 _mountPointsTable->horizontalHeader()->resizeSection(5,5*ww);
207 _mountPointsTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
208 _mountPointsTable->horizontalHeader()->setStretchLastSection(true);
209 _mountPointsTable->setHorizontalHeaderLabels(labels);
210 _mountPointsTable->setGridStyle(Qt::NoPen);
211 _mountPointsTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
212 _mountPointsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
213 _mountPointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
214 QListIterator<QString> it(settings.value("mountPoints").toStringList());
215 if (!it.hasNext()) {
216 _actGetData->setEnabled(false);
217 }
218 int iRow = 0;
219 while (it.hasNext()) {
220 QStringList hlp = it.next().split(" ");
221 if (hlp.size() < 5) continue;
222 _mountPointsTable->insertRow(iRow);
223
224 QUrl url(hlp[0]);
225
226 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
227 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
228 QString nmea(hlp[4]);
229
230 QTableWidgetItem* it;
231 it = new QTableWidgetItem(url.userInfo());
232 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
233 _mountPointsTable->setItem(iRow, 0, it);
234
235 it = new QTableWidgetItem(fullPath);
236 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
237 _mountPointsTable->setItem(iRow, 1, it);
238
239 it = new QTableWidgetItem(format);
240 _mountPointsTable->setItem(iRow, 2, it);
241
242 if (nmea == "yes") {
243 it = new QTableWidgetItem(latitude);
244 _mountPointsTable->setItem(iRow, 3, it);
245 it = new QTableWidgetItem(longitude);
246 _mountPointsTable->setItem(iRow, 4, it);
247 } else {
248 it = new QTableWidgetItem(latitude);
249 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
250 _mountPointsTable->setItem(iRow, 3, it);
251 it = new QTableWidgetItem(longitude);
252 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
253 _mountPointsTable->setItem(iRow, 4, it);
254 }
255
256 it = new QTableWidgetItem(nmea);
257 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
258 _mountPointsTable->setItem(iRow, 5, it);
259
260 bncTableItem* bncIt = new bncTableItem();
261 bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
262 _mountPointsTable->setItem(iRow, 6, bncIt);
263
264 iRow++;
265 }
266 _mountPointsTable->hideColumn(0);
267 _mountPointsTable->sortItems(1);
268
269 connect(_mountPointsTable, SIGNAL(itemSelectionChanged()),
270 SLOT(slotSelectionChanged()));
271
272 _log = new QTextBrowser();
273 _log->setReadOnly(true);
274
275 _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."));
276
277
278
279 // Canvas with Editable Fields
280 // ---------------------------
281 _canvas = new QWidget;
282 setCentralWidget(_canvas);
283
284 QTabWidget* aogroup = new QTabWidget();
285 QWidget* pgroup = new QWidget();
286 QWidget* ggroup = new QWidget();
287 QWidget* sgroup = new QWidget();
288 QWidget* egroup = new QWidget();
289 QWidget* agroup = new QWidget();
290 QWidget* ogroup = new QWidget();
291 aogroup->addTab(pgroup,tr("Proxy"));
292 aogroup->addTab(ggroup,tr("General"));
293 aogroup->addTab(ogroup,tr("RINEX - Observations"));
294 aogroup->addTab(egroup,tr("RINEX - Ephemeris"));
295 aogroup->addTab(sgroup,tr("Synchronized Observations"));
296 aogroup->addTab(agroup,tr("Advisory"));
297
298
299 QGridLayout* pLayout = new QGridLayout;
300 pLayout->setColumnMinimumWidth(0,12*ww);
301 pLayout->addWidget(new QLabel("Proxy host"),0,0, Qt::AlignLeft);
302 pLayout->addWidget(_proxyHostLineEdit,0, 1);
303 pLayout->addWidget(new QLabel("Proxy port"),1,0, Qt::AlignLeft);
304 pLayout->addWidget(_proxyPortLineEdit,1,1);
305 pLayout->addWidget(new QLabel("Settings for the Proxy, leave the boxes blank if none."),2, 0, 1, 2, Qt::AlignLeft);
306 pLayout->addWidget(new QLabel(" "),3,0);
307 pLayout->addWidget(new QLabel(" "),4,0);
308 pLayout->addWidget(new QLabel(" "),5,0);
309 pgroup->setLayout(pLayout);
310
311 QGridLayout* gLayout = new QGridLayout;
312 gLayout->setColumnMinimumWidth(0,12*ww);
313 gLayout->addWidget(new QLabel("Logfile (full path)"), 0,0);
314 gLayout->addWidget(_logFileLineEdit, 0,1);
315 gLayout->addWidget(new QLabel("Append files") ,1,0 );
316 gLayout->addWidget(_rnxAppendCheckBox, 1,1 );
317 gLayout->addWidget(new QLabel("General settings for logfile and file handling."),2, 0, 1, 2, Qt::AlignLeft);
318 gLayout->addWidget(new QLabel(" "),3,0);
319 gLayout->addWidget(new QLabel(" "),4,0);
320 gLayout->addWidget(new QLabel(" "),5,0);
321 ggroup->setLayout(gLayout);
322
323 QGridLayout* sLayout = new QGridLayout;
324 sLayout->setColumnMinimumWidth(0,12*ww);
325 sLayout->addWidget(new QLabel("Port"), 0, 0);
326 sLayout->addWidget(_outPortLineEdit, 0, 1);
327 sLayout->addWidget(new QLabel("Wait for full epoch"), 1, 0);
328 sLayout->addWidget(_waitTimeSpinBox, 1, 1);
329 sLayout->addWidget(new QLabel("File (full path)"), 2, 0);
330 sLayout->addWidget(_outFileLineEdit, 2, 1);
331 sLayout->addWidget(new QLabel("Output synchronized observations epoch by epoch."),3,0,1,2,Qt::AlignLeft);
332 sLayout->addWidget(new QLabel(" "),4,0);
333 sLayout->addWidget(new QLabel(" "),5,0);
334 sgroup->setLayout(sLayout);
335
336 QGridLayout* eLayout = new QGridLayout;
337 eLayout->setColumnMinimumWidth(0,12*ww);
338 eLayout->addWidget(new QLabel("Interval"), 0, 0);
339 eLayout->addWidget(_ephIntrComboBox, 0, 1);
340 eLayout->addWidget(new QLabel("Port"), 1, 0);
341 eLayout->addWidget(_outEphPortLineEdit, 1, 1);
342 eLayout->addWidget(new QLabel("Directory"), 2, 0);
343 eLayout->addWidget(_ephPathLineEdit, 2, 1);
344 eLayout->addWidget(new QLabel("Version 3"), 3, 0);
345 eLayout->addWidget(_ephV3CheckBox, 3, 1);
346 _ephV3CheckBox->setWhatsThis(tr("<p>Default format for RINEX Navigation files containing Broadcast Ephemeris is RINEX Version 2.11. Select 'Version 3' if you want to save the ephemeris in RINEX Version 3 format.</p>"));
347 eLayout->addWidget(new QLabel("Saving RINEX ephemeris files."),4,0,1,2,Qt::AlignLeft);
348 eLayout->addWidget(new QLabel(" "),5,0);
349 egroup->setLayout(eLayout);
350
351 QGridLayout* aLayout = new QGridLayout;
352 aLayout->setColumnMinimumWidth(0,12*ww);
353 aLayout->addWidget(new QLabel("Failure"), 0, 0);
354 aLayout->addWidget(_adviseFailSpinBox, 0, 1);
355 aLayout->addWidget(new QLabel("Recovery"), 1, 0);
356 aLayout->addWidget(_adviseRecoSpinBox, 1, 1);
357 aLayout->addWidget(new QLabel("Script (full path)"), 2, 0);
358 aLayout->addWidget(_adviseScriptLineEdit, 2, 1);
359 aLayout->addWidget(new QLabel("Inspect segment"), 3, 0);
360 aLayout->addWidget(_inspSegmSpinBox, 3, 1);
361 aLayout->addWidget(new QLabel("Advisory notes, handling of corrupted streams."),4,0,1,2,Qt::AlignLeft);
362 aLayout->addWidget(new QLabel(" "),5,0);
363 agroup->setLayout(aLayout);
364
365 QGridLayout* oLayout = new QGridLayout;
366 oLayout->setColumnMinimumWidth(0,12*ww);
367 oLayout->setColumnMinimumWidth(1,8*ww);
368 oLayout->setColumnMinimumWidth(2,12*ww);
369 oLayout->setColumnMinimumWidth(3,40*ww);
370 oLayout->addWidget(new QLabel("Interval"), 0, 0);
371 oLayout->addWidget(_rnxIntrComboBox, 0, 1);
372 oLayout->addWidget(new QLabel("Sampling"), 0, 2, Qt::AlignRight);
373 oLayout->addWidget(_rnxSamplSpinBox, 0, 3, Qt::AlignLeft);
374 oLayout->addWidget(new QLabel("Directory"), 1, 0);
375 oLayout->addWidget(_rnxPathLineEdit, 1, 1,1,3);
376 oLayout->addWidget(new QLabel("Skeleton"), 2, 0);
377 oLayout->addWidget(_rnxSkelLineEdit, 2, 1);
378 oLayout->addWidget(new QLabel("Script (full path)"), 3, 0);
379 oLayout->addWidget(_rnxScrpLineEdit, 3, 1, 1, 3);
380 oLayout->addWidget(new QLabel("Version 3"), 4, 0);
381 oLayout->addWidget(_rnxV3CheckBox, 4, 1);
382 _rnxV3CheckBox->setWhatsThis(tr("<p>Default format for RINEX Observation files is RINEX Version 2.11. Select 'Version 3' if you want to save the observations in RINEX Version 3 format.</p>"));
383 oLayout->addWidget(new QLabel("Saving RINEX observation files."),5,0,1,4, Qt::AlignLeft);
384 ogroup->setLayout(oLayout);
385
386 QVBoxLayout* mLayout = new QVBoxLayout;
387 mLayout->addWidget(aogroup);
388 mLayout->addWidget(_mountPointsTable);
389 mLayout->addWidget(_log);
390
391 _canvas->setLayout(mLayout);
392}
393
394// Destructor
395////////////////////////////////////////////////////////////////////////////
396bncWindow::~bncWindow() {
397 delete _caster;
398}
399
400// Retrieve Table
401////////////////////////////////////////////////////////////////////////////
402void bncWindow::slotAddMountPoints() {
403
404 QSettings settings;
405 QString proxyHost = settings.value("proxyHost").toString();
406 int proxyPort = settings.value("proxyPort").toInt();
407 if (proxyHost != _proxyHostLineEdit->text() ||
408 proxyPort != _proxyPortLineEdit->text().toInt()) {
409 int iRet = QMessageBox::question(this, "Question", "Proxy options "
410 "changed. Use the new ones?",
411 QMessageBox::Yes, QMessageBox::No,
412 QMessageBox::NoButton);
413 if (iRet == QMessageBox::Yes) {
414 settings.setValue("proxyHost", _proxyHostLineEdit->text());
415 settings.setValue("proxyPort", _proxyPortLineEdit->text());
416 }
417 }
418
419 bncTableDlg* dlg = new bncTableDlg(this);
420 dlg->move(this->pos().x()+50, this->pos().y()+50);
421 connect(dlg, SIGNAL(newMountPoints(QStringList*)),
422 this, SLOT(slotNewMountPoints(QStringList*)));
423 dlg->exec();
424 delete dlg;
425
426}
427
428// Delete Selected Mount Points
429////////////////////////////////////////////////////////////////////////////
430void bncWindow::slotDeleteMountPoints() {
431
432 int nRows = _mountPointsTable->rowCount();
433 bool flg[nRows];
434 for (int iRow = 0; iRow < nRows; iRow++) {
435 if (_mountPointsTable->isItemSelected(_mountPointsTable->item(iRow,1))) {
436 flg[iRow] = true;
437 }
438 else {
439 flg[iRow] = false;
440 }
441 }
442 for (int iRow = nRows-1; iRow >= 0; iRow--) {
443 if (flg[iRow]) {
444 _mountPointsTable->removeRow(iRow);
445 }
446 }
447 _actDeleteMountPoints->setEnabled(false);
448
449 if (_mountPointsTable->rowCount() == 0) {
450 _actGetData->setEnabled(false);
451 }
452}
453
454// New Mount Points Selected
455////////////////////////////////////////////////////////////////////////////
456void bncWindow::slotNewMountPoints(QStringList* mountPoints) {
457 int iRow = 0;
458 QListIterator<QString> it(*mountPoints);
459 while (it.hasNext()) {
460 QStringList hlp = it.next().split(" ");
461 QUrl url(hlp[0]);
462 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
463 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
464 QString nmea(hlp[4]);
465
466 _mountPointsTable->insertRow(iRow);
467
468 QTableWidgetItem* it;
469 it = new QTableWidgetItem(url.userInfo());
470 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
471 _mountPointsTable->setItem(iRow, 0, it);
472
473 it = new QTableWidgetItem(fullPath);
474 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
475 _mountPointsTable->setItem(iRow, 1, it);
476
477 it = new QTableWidgetItem(format);
478 _mountPointsTable->setItem(iRow, 2, it);
479
480 if (nmea == "yes") {
481 it = new QTableWidgetItem(latitude);
482 _mountPointsTable->setItem(iRow, 3, it);
483 it = new QTableWidgetItem(longitude);
484 _mountPointsTable->setItem(iRow, 4, it);
485 } else {
486 it = new QTableWidgetItem(latitude);
487 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
488 _mountPointsTable->setItem(iRow, 3, it);
489 it = new QTableWidgetItem(longitude);
490 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
491 _mountPointsTable->setItem(iRow, 4, it);
492 }
493
494 it = new QTableWidgetItem(nmea);
495 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
496 _mountPointsTable->setItem(iRow, 5, it);
497
498 bncTableItem* bncIt = new bncTableItem();
499 _mountPointsTable->setItem(iRow, 6, bncIt);
500
501 iRow++;
502 }
503 _mountPointsTable->hideColumn(0);
504 _mountPointsTable->sortItems(1);
505 if (mountPoints->count() > 0) {
506 _actGetData->setEnabled(true);
507 }
508 delete mountPoints;
509}
510
511// Save Options
512////////////////////////////////////////////////////////////////////////////
513void bncWindow::slotSaveOptions() {
514 QSettings settings;
515 settings.setValue("proxyHost", _proxyHostLineEdit->text());
516 settings.setValue("proxyPort", _proxyPortLineEdit->text());
517 settings.setValue("waitTime", _waitTimeSpinBox->value());
518 settings.setValue("inspSegm", _inspSegmSpinBox->value());
519 settings.setValue("adviseFail", _adviseFailSpinBox->value());
520 settings.setValue("adviseReco", _adviseRecoSpinBox->value());
521 settings.setValue("outFile", _outFileLineEdit->text());
522 settings.setValue("outPort", _outPortLineEdit->text());
523 settings.setValue("outEphPort", _outEphPortLineEdit->text());
524 settings.setValue("rnxPath", _rnxPathLineEdit->text());
525 settings.setValue("ephPath", _ephPathLineEdit->text());
526 settings.setValue("rnxScript", _rnxScrpLineEdit->text());
527 settings.setValue("rnxIntr", _rnxIntrComboBox->currentText());
528 settings.setValue("ephIntr", _ephIntrComboBox->currentText());
529 settings.setValue("rnxSampl", _rnxSamplSpinBox->value());
530 settings.setValue("rnxSkel", _rnxSkelLineEdit->text());
531 settings.setValue("rnxAppend", _rnxAppendCheckBox->checkState());
532 settings.setValue("rnxV3", _rnxV3CheckBox->checkState());
533 settings.setValue("ephV3", _ephV3CheckBox->checkState());
534 settings.setValue("logFile", _logFileLineEdit->text());
535 settings.setValue("adviseScript",_adviseScriptLineEdit->text());
536
537QStringList mountPoints;
538
539 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
540 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
541 "@" + _mountPointsTable->item(iRow, 1)->text() );
542
543 mountPoints.append(url.toString() + " " +
544 _mountPointsTable->item(iRow, 2)->text()
545 + " " + _mountPointsTable->item(iRow, 3)->text()
546 + " " + _mountPointsTable->item(iRow, 4)->text()
547 + " " + _mountPointsTable->item(iRow, 5)->text());
548 }
549 settings.setValue("mountPoints", mountPoints);
550}
551
552// All get slots terminated
553////////////////////////////////////////////////////////////////////////////
554void bncWindow::slotGetThreadErrors() {
555 slotMessage("All Get Threads Terminated");
556 ((bncApp*)qApp)->slotMessage("All Get Threads Terminated");
557 _actAddMountPoints->setEnabled(true);
558 _actGetData->setEnabled(true);
559}
560
561// Retrieve Data
562////////////////////////////////////////////////////////////////////////////
563void bncWindow::slotGetData() {
564 slotSaveOptions();
565
566 _actAddMountPoints->setEnabled(false);
567 _actDeleteMountPoints->setEnabled(false);
568 _actGetData->setEnabled(false);
569 _actStop->setEnabled(true);
570
571 _caster = new bncCaster(_outFileLineEdit->text(),
572 _outPortLineEdit->text().toInt());
573
574 ((bncApp*)qApp)->setPort(_outEphPortLineEdit->text().toInt());
575
576 connect(_caster, SIGNAL(getThreadErrors()),
577 this, SLOT(slotGetThreadErrors()));
578
579 connect(_caster, SIGNAL(newMessage(QByteArray)),
580 this, SLOT(slotMessage(QByteArray)));
581 connect(_caster, SIGNAL(newMessage(QByteArray)),
582 (bncApp*)qApp, SLOT(slotMessage(QByteArray)));
583
584 slotMessage("============ Start BNC ============");
585 ((bncApp*)qApp)->slotMessage("============ Start BNC ============");
586
587 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
588 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
589 "@" + _mountPointsTable->item(iRow, 1)->text() );
590
591 QByteArray format = _mountPointsTable->item(iRow, 2)->text().toAscii();
592
593 QByteArray latitude = _mountPointsTable->item(iRow, 3)->text().toAscii();
594 QByteArray longitude = _mountPointsTable->item(iRow, 4)->text().toAscii();
595 QByteArray nmea = _mountPointsTable->item(iRow, 5)->text().toAscii();
596
597 bncGetThread* getThread = new bncGetThread(url, format, latitude, longitude, nmea, iRow);
598
599 connect(getThread, SIGNAL(newMessage(QByteArray)),
600 this, SLOT(slotMessage(QByteArray)));
601 connect(getThread, SIGNAL(newMessage(QByteArray)),
602 (bncApp*)qApp, SLOT(slotMessage(QByteArray)));
603
604 connect(getThread, SIGNAL(newBytes(QByteArray, double)),
605 (bncTableItem*) _mountPointsTable->item(iRow, 6),
606 SLOT(slotNewBytes(QByteArray, double)));
607
608 _caster->addGetThread(getThread);
609
610 getThread->start();
611 }
612}
613
614// Retrieve Data
615////////////////////////////////////////////////////////////////////////////
616void bncWindow::slotStop() {
617 int iRet = QMessageBox::question(this, "Stop", "Stop retrieving data?",
618 QMessageBox::Yes, QMessageBox::No,
619 QMessageBox::NoButton);
620 if (iRet == QMessageBox::Yes) {
621 delete _caster; _caster = 0;
622 _actGetData->setEnabled(true);
623 _actStop->setEnabled(false);
624 _actAddMountPoints->setEnabled(true);
625 }
626}
627
628// Close Application gracefully
629////////////////////////////////////////////////////////////////////////////
630void bncWindow::closeEvent(QCloseEvent* event) {
631
632 int iRet = QMessageBox::question(this, "Close", "Save Options?",
633 QMessageBox::Yes, QMessageBox::No,
634 QMessageBox::Cancel);
635
636 if (iRet == QMessageBox::Cancel) {
637 event->ignore();
638 return;
639 }
640 else if (iRet == QMessageBox::Yes) {
641 slotSaveOptions();
642 }
643
644 QMainWindow::closeEvent(event);
645 delete this;
646}
647
648// User changed the selection of mountPoints
649////////////////////////////////////////////////////////////////////////////
650void bncWindow::slotSelectionChanged() {
651 if (_mountPointsTable->selectedItems().isEmpty()) {
652 _actDeleteMountPoints->setEnabled(false);
653 }
654 else {
655 _actDeleteMountPoints->setEnabled(true);
656 }
657}
658
659// Display Program Messages
660////////////////////////////////////////////////////////////////////////////
661void bncWindow::slotMessage(const QByteArray msg) {
662
663 const int maxBufferSize = 10000;
664
665 QString txt = _log->toPlainText() + "\n" +
666 QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ") + msg;
667 _log->clear();
668 _log->append(txt.right(maxBufferSize));
669}
670
671// About Message
672////////////////////////////////////////////////////////////////////////////
673void bncWindow::slotAbout() {
674 new bncAboutDlg(0);
675}
676
677// Help Window
678////////////////////////////////////////////////////////////////////////////
679void bncWindow::slotHelp() {
680 QUrl url;
681 url.setPath(":bnchelp.html");
682 new bncHlpDlg(0, url);
683}
684
685// Select Fonts
686////////////////////////////////////////////////////////////////////////////
687void bncWindow::slotFontSel() {
688 bool ok;
689 QFont newFont = QFontDialog::getFont(&ok, this->font(), this);
690 if (ok) {
691 QSettings settings;
692 settings.setValue("font", newFont.toString());
693 QApplication::setFont(newFont);
694 int ww = QFontMetrics(newFont).width('w');
695 setMinimumSize(60*ww, 80*ww);
696 resize(60*ww, 80*ww);
697 }
698}
699
700// Whats This Help
701void bncWindow::slotWhatsThis() {
702QWhatsThis::enterWhatsThisMode();
703}
704
705void bncWindow::CreateMenu() {
706 // Create Menus
707 // ------------
708 _menuFile = menuBar()->addMenu(tr("&File"));
709 _menuFile->addAction(_actFontSel);
710 _menuFile->addSeparator();
711 _menuFile->addAction(_actSaveOpt);
712 _menuFile->addSeparator();
713 _menuFile->addAction(_actQuit);
714
715 _menuHlp = menuBar()->addMenu(tr("&Help"));
716 _menuHlp->addAction(_actHelp);
717 _menuHlp->addAction(_actAbout);
718
719}
720
721void bncWindow::AddToolbar() {
722 // Tool (Command) Bar
723 // ------------------
724 QToolBar* toolBar = new QToolBar;
725 addToolBar(Qt::BottomToolBarArea, toolBar);
726 toolBar->setMovable(false);
727 toolBar->addAction(_actAddMountPoints);
728 toolBar->addAction(_actDeleteMountPoints);
729 toolBar->addAction(_actGetData);
730 toolBar->addAction(_actStop);
731 toolBar->addWidget(new QLabel(" "));
732 toolBar->addAction(_actwhatsthis);
733}
734
735bncAboutDlg::bncAboutDlg(QWidget* parent) :
736 QDialog(parent) {
737
738 QTextBrowser* tb = new QTextBrowser;
739 QUrl url; url.setPath(":bncabout.html");
740 tb->setSource(url);
741 tb->setReadOnly(true);
742
743 int ww = QFontMetrics(font()).width('w');
744 QPushButton* _closeButton = new QPushButton("Close");
745 _closeButton->setMaximumWidth(10*ww);
746 connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
747
748 QGridLayout* dlgLayout = new QGridLayout();
749 QLabel* img = new QLabel();
750 img->setPixmap(QPixmap(":ntrip-logo.png"));
751 dlgLayout->addWidget(img, 0,0);
752 dlgLayout->addWidget(new QLabel("BKG NTRIP Client (BNC) Version 1.5"), 0,1);
753 dlgLayout->addWidget(tb,1,0,1,2);
754 dlgLayout->addWidget(_closeButton,2,1,Qt::AlignRight);
755
756 setLayout(dlgLayout);
757 resize(60*ww, 60*ww);
758 show();
759}
760
761bncAboutDlg::~bncAboutDlg() {
762};
763
Note: See TracBrowser for help on using the repository browser.