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

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