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

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

* empty log message *

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