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

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

* empty log message *

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