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

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