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

Last change on this file since 1171 was 1171, checked in by mervart, 16 years ago

* empty log message *

File size: 45.0 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: bncWindow
30 *
31 * Purpose: This class implements the main application window.
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Dec-2005
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <unistd.h>
42#include "bncwindow.h"
43#include "bncapp.h"
44#include "bncgetthread.h"
45#include "bnctabledlg.h"
46#include "bnchlpdlg.h"
47#include "bnchtml.h"
48#include "bnctableitem.h"
49
50using namespace std;
51
52// Constructor
53////////////////////////////////////////////////////////////////////////////
54bncWindow::bncWindow() {
55
56 _caster = 0;
57
58 int ww = QFontMetrics(this->font()).width('w');
59
60 static const QStringList labels = QString("account,broadcaster:port / mountpoint,decoder,lat,long,nmea,bytes").split(",");
61
62 setMinimumSize(80*ww, 65*ww);
63
64 setWindowTitle(tr("BKG Ntrip Client (BNC) Version 1.6"));
65
66 connect((bncApp*)qApp, SIGNAL(newMessage(QByteArray)),
67 this, SLOT(slotMessage(QByteArray)));
68
69 // Create Actions
70 // --------------
71 _actHelp = new QAction(tr("&Help Contents"),this);
72 connect(_actHelp, SIGNAL(triggered()), SLOT(slotHelp()));
73
74 _actAbout = new QAction(tr("&About BNC"),this);
75 connect(_actAbout, SIGNAL(triggered()), SLOT(slotAbout()));
76
77 _actFlowchart = new QAction(tr("&Flow Chart"),this);
78 connect(_actFlowchart, SIGNAL(triggered()), SLOT(slotFlowchart()));
79
80 _actFontSel = new QAction(tr("Select &Font"),this);
81 connect(_actFontSel, SIGNAL(triggered()), SLOT(slotFontSel()));
82
83 _actSaveOpt = new QAction(tr("&Save Options"),this);
84 connect(_actSaveOpt, SIGNAL(triggered()), SLOT(slotSaveOptions()));
85
86 _actQuit = new QAction(tr("&Quit"),this);
87 connect(_actQuit, SIGNAL(triggered()), SLOT(close()));
88
89 _actAddMountPoints = new QAction(tr("Add &Mountpoints"),this);
90 connect(_actAddMountPoints, SIGNAL(triggered()), SLOT(slotAddMountPoints()));
91
92 _actDeleteMountPoints = new QAction(tr("&Delete Mountpoints"),this);
93 connect(_actDeleteMountPoints, SIGNAL(triggered()), SLOT(slotDeleteMountPoints()));
94 _actDeleteMountPoints->setEnabled(false);
95
96 _actGetData = new QAction(tr("Sta&rt"),this);
97 connect(_actGetData, SIGNAL(triggered()), SLOT(slotGetData()));
98
99 _actStop = new QAction(tr("Sto&p"),this);
100 connect(_actStop, SIGNAL(triggered()), SLOT(slotStop()));
101 _actStop->setEnabled(false);
102
103 _actwhatsthis= new QAction(tr("Help=Shift+F1"),this);
104 connect(_actwhatsthis, SIGNAL(triggered()), SLOT(slotWhatsThis()));
105
106 CreateMenu();
107 AddToolbar();
108
109 QSettings settings;
110 _proxyHostLineEdit = new QLineEdit(settings.value("proxyHost").toString());
111 _proxyPortLineEdit = new QLineEdit(settings.value("proxyPort").toString());
112 _proxyPortLineEdit->setMaximumWidth(9*ww);
113 _messTypesLineEdit = new QLineEdit(settings.value("messTypes").toString());
114 _messTypesLineEdit->setMaximumWidth(20*ww);
115 _waitTimeSpinBox = new QSpinBox();
116 _waitTimeSpinBox->setMinimum(1);
117 _waitTimeSpinBox->setMaximum(30);
118 _waitTimeSpinBox->setSingleStep(1);
119 _waitTimeSpinBox->setSuffix(" sec");
120 _waitTimeSpinBox->setMaximumWidth(9*ww);
121 _waitTimeSpinBox->setValue(settings.value("waitTime").toInt());
122 _outFileLineEdit = new QLineEdit(settings.value("outFile").toString());
123 _outPortLineEdit = new QLineEdit(settings.value("outPort").toString());
124 _outPortLineEdit->setMaximumWidth(9*ww);
125 _outEphPortLineEdit = new QLineEdit(settings.value("outEphPort").toString());
126 _outEphPortLineEdit->setMaximumWidth(9*ww);
127 _corrPortLineEdit = new QLineEdit(settings.value("corrPort").toString());
128 _corrPortLineEdit->setMaximumWidth(9*ww);
129 _rnxPathLineEdit = new QLineEdit(settings.value("rnxPath").toString());
130 _ephPathLineEdit = new QLineEdit(settings.value("ephPath").toString());
131 _corrPathLineEdit = new QLineEdit(settings.value("corrPath").toString());
132
133 _rnxV3CheckBox = new QCheckBox();
134 _rnxV3CheckBox->setCheckState(Qt::CheckState(settings.value("rnxV3").toInt()));
135 _ephV3CheckBox = new QCheckBox();
136 _ephV3CheckBox->setCheckState(Qt::CheckState(settings.value("ephV3").toInt()));
137 _rnxScrpLineEdit = new QLineEdit(settings.value("rnxScript").toString());
138 _rnxSkelLineEdit = new QLineEdit(settings.value("rnxSkel").toString());
139 _rnxSkelLineEdit->setMaximumWidth(5*ww);
140 _rnxAppendCheckBox = new QCheckBox();
141 _rnxAppendCheckBox->setCheckState(Qt::CheckState(
142 settings.value("rnxAppend").toInt()));
143 _rnxIntrComboBox = new QComboBox();
144 _rnxIntrComboBox->setMaximumWidth(9*ww);
145 _rnxIntrComboBox->setEditable(false);
146 _rnxIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
147 int ii = _rnxIntrComboBox->findText(settings.value("rnxIntr").toString());
148 if (ii != -1) {
149 _rnxIntrComboBox->setCurrentIndex(ii);
150 }
151 _onTheFlyComboBox = new QComboBox();
152 _onTheFlyComboBox->setMaximumWidth(9*ww);
153 _onTheFlyComboBox->setEditable(false);
154 _onTheFlyComboBox->addItems(QString("1 min,1 hour,1 day").split(","));
155 ii = _onTheFlyComboBox->findText(settings.value("onTheFlyInterval").toString());
156 if (ii != -1) {
157 _onTheFlyComboBox->setCurrentIndex(ii);
158 }
159 _ephIntrComboBox = new QComboBox();
160 _ephIntrComboBox->setMaximumWidth(9*ww);
161 _ephIntrComboBox->setEditable(false);
162 _ephIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
163 int jj = _ephIntrComboBox->findText(settings.value("ephIntr").toString());
164 if (jj != -1) {
165 _ephIntrComboBox->setCurrentIndex(jj);
166 }
167 _corrIntrComboBox = new QComboBox();
168 _corrIntrComboBox->setMaximumWidth(9*ww);
169 _corrIntrComboBox->setEditable(false);
170 _corrIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
171 int mm = _corrIntrComboBox->findText(settings.value("corrIntr").toString());
172 if (mm != -1) {
173 _corrIntrComboBox->setCurrentIndex(mm);
174 }
175 _corrTimeSpinBox = new QSpinBox();
176 _corrTimeSpinBox->setMinimum(1);
177 _corrTimeSpinBox->setMaximum(30);
178 _corrTimeSpinBox->setSingleStep(1);
179 _corrTimeSpinBox->setSuffix(" sec");
180 _corrTimeSpinBox->setMaximumWidth(9*ww);
181 _corrTimeSpinBox->setValue(settings.value("corrTime").toInt());
182 _rnxSamplSpinBox = new QSpinBox();
183 _rnxSamplSpinBox->setMinimum(0);
184 _rnxSamplSpinBox->setMaximum(60);
185 _rnxSamplSpinBox->setSingleStep(5);
186 _rnxSamplSpinBox->setMaximumWidth(9*ww);
187 _rnxSamplSpinBox->setValue(settings.value("rnxSampl").toInt());
188 _rnxSamplSpinBox->setSuffix(" sec");
189
190 _binSamplSpinBox = new QSpinBox();
191 _binSamplSpinBox->setMinimum(0);
192 _binSamplSpinBox->setMaximum(60);
193 _binSamplSpinBox->setSingleStep(5);
194 _binSamplSpinBox->setMaximumWidth(9*ww);
195 _binSamplSpinBox->setValue(settings.value("binSampl").toInt());
196 _binSamplSpinBox->setSuffix(" sec");
197
198 _obsRateComboBox = new QComboBox();
199 _obsRateComboBox->setMaximumWidth(9*ww);
200 _obsRateComboBox->setEditable(false);
201 _obsRateComboBox->addItems(QString(",0.1 Hz,0.2 Hz,0.5 Hz,1 Hz,5 Hz").split(","));
202 int kk = _obsRateComboBox->findText(settings.value("obsRate").toString());
203 if (kk != -1) {
204 _obsRateComboBox->setCurrentIndex(kk);
205 }
206 _makePauseCheckBox = new QCheckBox();
207 _makePauseCheckBox->setCheckState(Qt::CheckState(
208 settings.value("makePause").toInt()));
209 _adviseRecoSpinBox = new QSpinBox();
210 _adviseRecoSpinBox->setMinimum(0);
211 _adviseRecoSpinBox->setMaximum(60);
212 _adviseRecoSpinBox->setSingleStep(1);
213 _adviseRecoSpinBox->setSuffix(" min");
214 _adviseRecoSpinBox->setMaximumWidth(9*ww);
215 _adviseRecoSpinBox->setValue(settings.value("adviseReco").toInt());
216 _adviseFailSpinBox = new QSpinBox();
217 _adviseFailSpinBox->setMinimum(0);
218 _adviseFailSpinBox->setMaximum(60);
219 _adviseFailSpinBox->setSingleStep(1);
220 _adviseFailSpinBox->setSuffix(" min");
221 _adviseFailSpinBox->setMaximumWidth(9*ww);
222 _adviseFailSpinBox->setValue(settings.value("adviseFail").toInt());
223 _logFileLineEdit = new QLineEdit(settings.value("logFile").toString());
224 _adviseScriptLineEdit = new QLineEdit(settings.value("adviseScript").toString());
225
226 _perfIntrComboBox = new QComboBox();
227 _perfIntrComboBox->setMaximumWidth(9*ww);
228 _perfIntrComboBox->setEditable(false);
229 _perfIntrComboBox->addItems(QString(",1 min,5 min,15 min,1 hour,6 hours,1 day").split(","));
230 int ll = _perfIntrComboBox->findText(settings.value("perfIntr").toString());
231 if (ll != -1) {
232 _perfIntrComboBox->setCurrentIndex(ll);
233 }
234
235 _mountPointsTable = new QTableWidget(0,7);
236
237 _mountPointsTable->horizontalHeader()->resizeSection(1,34*ww);
238 _mountPointsTable->horizontalHeader()->resizeSection(2,9*ww);
239 _mountPointsTable->horizontalHeader()->resizeSection(3,7*ww);
240 _mountPointsTable->horizontalHeader()->resizeSection(4,7*ww);
241 _mountPointsTable->horizontalHeader()->resizeSection(5,5*ww);
242 _mountPointsTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
243 _mountPointsTable->horizontalHeader()->setStretchLastSection(true);
244 _mountPointsTable->setHorizontalHeaderLabels(labels);
245 _mountPointsTable->setGridStyle(Qt::NoPen);
246 _mountPointsTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
247 _mountPointsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
248 _mountPointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
249 QListIterator<QString> it(settings.value("mountPoints").toStringList());
250 if (!it.hasNext()) {
251 _actGetData->setEnabled(false);
252 }
253 int iRow = 0;
254 while (it.hasNext()) {
255 QStringList hlp = it.next().split(" ");
256 if (hlp.size() < 5) continue;
257 _mountPointsTable->insertRow(iRow);
258
259 QUrl url(hlp[0]);
260
261 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
262 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
263 QString nmea(hlp[4]);
264
265 QTableWidgetItem* it;
266 it = new QTableWidgetItem(url.userInfo());
267 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
268 _mountPointsTable->setItem(iRow, 0, it);
269
270 it = new QTableWidgetItem(fullPath);
271 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
272 _mountPointsTable->setItem(iRow, 1, it);
273
274 it = new QTableWidgetItem(format);
275 _mountPointsTable->setItem(iRow, 2, it);
276
277 if (nmea == "yes") {
278 it = new QTableWidgetItem(latitude);
279 _mountPointsTable->setItem(iRow, 3, it);
280 it = new QTableWidgetItem(longitude);
281 _mountPointsTable->setItem(iRow, 4, it);
282 } else {
283 it = new QTableWidgetItem(latitude);
284 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
285 _mountPointsTable->setItem(iRow, 3, it);
286 it = new QTableWidgetItem(longitude);
287 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
288 _mountPointsTable->setItem(iRow, 4, it);
289 }
290
291 it = new QTableWidgetItem(nmea);
292 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
293 _mountPointsTable->setItem(iRow, 5, it);
294
295 bncTableItem* bncIt = new bncTableItem();
296 bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
297 _mountPointsTable->setItem(iRow, 6, bncIt);
298
299 iRow++;
300 }
301 _mountPointsTable->hideColumn(0);
302 _mountPointsTable->sortItems(1);
303
304 connect(_mountPointsTable, SIGNAL(itemSelectionChanged()),
305 SLOT(slotSelectionChanged()));
306
307 _log = new QTextBrowser();
308 _log->setReadOnly(true);
309
310 // WhatsThis
311 // ---------
312 _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>"));
313 _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>"));
314 _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>"));
315 _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."));
316 _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."));
317 _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."));
318 _corrPortLineEdit->setWhatsThis(tr("BNC can produce Broadcast Ephemeris Corrections on your local host through an IP port. Specify a port number here to activate this function."));
319 _corrTimeSpinBox->setWhatsThis(tr("Concerning output through IP port, BNC drops Broadcast Ephemeris Corrections received later than 'Wait for full epoch' seconds. A value of 2 to 5 seconds is recommended, depending on the latency of the incoming correction stream(s) and the delay acceptable to your real-time application."));
320 _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."));
321 _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."));
322 _corrPathLineEdit->setWhatsThis(tr("Specify a directory for saving Broadcast Ephemeris Correction files. If the specified directory does not exist, BNC will not create the files."));
323 _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>"));
324 _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>"));
325 _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>"));
326 _rnxIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Observation file.</p>"));
327 _ephIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Navigation file.</p>"));
328 _corrIntrComboBox->setWhatsThis(tr("<p>Select the length of the Broadcast Ephemeris Correction files.</p>"));
329 _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>"));
330 _binSamplSpinBox->setWhatsThis(tr("<p>Select the Observation sampling interval in seconds. A value of zero '0' tells BNC to send/store all received epochs.</p>"));
331 _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>"));
332 _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>"));
333 _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>"));
334 _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>"));
335 _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."));
336 _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>"));
337 _perfIntrComboBox->setWhatsThis(tr("<p>BNC can average 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 log' interval together with results of a statistical evaluation (approximate number of covered epochs, data gaps).</p><p>Select a 'Performance log' interval or select the empty option field if you do not want BNC to log latencies and statistical information.</p>"));
338 _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>"));
339 _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."));
340 _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."));
341 _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."));
342 _messTypesLineEdit->setWhatsThis(tr("<p>Specify the mountpoint of an RTCM Version 3.x stream to log the numbers of incoming message types as well as contained antenna coordinates and antenna hight.</p><p>An empty option field (default) means that you don't want BNC to log such information.</p>"));
343
344 // Canvas with Editable Fields
345 // ---------------------------
346 _canvas = new QWidget;
347 setCentralWidget(_canvas);
348
349 QTabWidget* aogroup = new QTabWidget();
350 QWidget* pgroup = new QWidget();
351 QWidget* ggroup = new QWidget();
352 QWidget* sgroup = new QWidget();
353 QWidget* egroup = new QWidget();
354 QWidget* agroup = new QWidget();
355 QWidget* cgroup = new QWidget();
356 QWidget* ogroup = new QWidget();
357 QWidget* rgroup = new QWidget();
358 aogroup->addTab(pgroup,tr("Proxy"));
359 aogroup->addTab(ggroup,tr("General"));
360 aogroup->addTab(ogroup,tr("RINEX Observations"));
361 aogroup->addTab(egroup,tr("RINEX Ephemeris"));
362 aogroup->addTab(sgroup,tr("Synchronized Observations"));
363 aogroup->addTab(cgroup,tr("Ephemeris Corrections"));
364 aogroup->addTab(agroup,tr("Monitor"));
365 aogroup->addTab(rgroup,tr("RTCM Scan"));
366
367 QGridLayout* pLayout = new QGridLayout;
368 pLayout->setColumnMinimumWidth(0,14*ww);
369 pLayout->addWidget(new QLabel("Proxy host"),0,0, Qt::AlignLeft);
370 pLayout->addWidget(_proxyHostLineEdit,0, 1);
371 pLayout->addWidget(new QLabel("Proxy port"),1,0, Qt::AlignLeft);
372 pLayout->addWidget(_proxyPortLineEdit,1,1);
373 pLayout->addWidget(new QLabel("Settings for the proxy in protected networks, leave the boxes blank if none."),2, 0, 1, 2, Qt::AlignLeft);
374 pLayout->addWidget(new QLabel(" "),3,0);
375 pLayout->addWidget(new QLabel(" "),4,0);
376 pLayout->addWidget(new QLabel(" "),5,0);
377 pgroup->setLayout(pLayout);
378
379 QGridLayout* gLayout = new QGridLayout;
380 gLayout->setColumnMinimumWidth(0,14*ww);
381 gLayout->addWidget(new QLabel("Logfile (full path)"), 0,0);
382 gLayout->addWidget(_logFileLineEdit, 0,1);
383 gLayout->addWidget(new QLabel("Append files") ,1,0 );
384 gLayout->addWidget(_rnxAppendCheckBox, 1,1 );
385 gLayout->addWidget(new QLabel("Reread Configuration every") ,2,0 );
386 gLayout->addWidget(_onTheFlyComboBox, 2,1 );
387 gLayout->addWidget(new QLabel("General settings for logfile and file handling."),3, 0, 1, 2, Qt::AlignLeft);
388 gLayout->addWidget(new QLabel(" "),4,0);
389 gLayout->addWidget(new QLabel(" "),5,0);
390 gLayout->addWidget(new QLabel(" "),6,0);
391 ggroup->setLayout(gLayout);
392
393 QGridLayout* sLayout = new QGridLayout;
394 sLayout->setColumnMinimumWidth(0,14*ww);
395 sLayout->addWidget(new QLabel("Port"), 0, 0);
396 sLayout->addWidget(_outPortLineEdit, 0, 1);
397 sLayout->addWidget(new QLabel("Wait for full epoch"), 1, 0);
398 sLayout->addWidget(_waitTimeSpinBox, 1, 1);
399 sLayout->addWidget(new QLabel("File (full path)"), 2, 0);
400 sLayout->addWidget(_outFileLineEdit, 2, 1);
401 sLayout->addWidget(new QLabel("Sampling"), 3, 0, Qt::AlignLeft);
402 sLayout->addWidget(_binSamplSpinBox, 3, 1, Qt::AlignLeft);
403 sLayout->addWidget(new QLabel("Output synchronized observations epoch by epoch."),4,0,1,2,Qt::AlignLeft);
404 sLayout->addWidget(new QLabel(" "),5,0);
405 sLayout->addWidget(new QLabel(" "),6,0);
406 sgroup->setLayout(sLayout);
407
408 QGridLayout* eLayout = new QGridLayout;
409 eLayout->setColumnMinimumWidth(0,14*ww);
410 eLayout->addWidget(new QLabel("Directory"), 0, 0);
411 eLayout->addWidget(_ephPathLineEdit, 0, 1);
412 eLayout->addWidget(new QLabel("Interval"), 1, 0);
413 eLayout->addWidget(_ephIntrComboBox, 1, 1);
414 eLayout->addWidget(new QLabel("Port"), 2, 0);
415 eLayout->addWidget(_outEphPortLineEdit, 2, 1);
416 eLayout->addWidget(new QLabel("Version 3"), 3, 0);
417 eLayout->addWidget(_ephV3CheckBox, 3, 1);
418 eLayout->addWidget(new QLabel("Saving RINEX ephemeris files and ephemeris output through IP port."),4,0,1,2,Qt::AlignLeft);
419 eLayout->addWidget(new QLabel(" "),5,0);
420 egroup->setLayout(eLayout);
421
422 QGridLayout* aLayout = new QGridLayout;
423 aLayout->setColumnMinimumWidth(0,14*ww);
424 aLayout->addWidget(new QLabel("Observation rate"), 0, 0);
425 aLayout->addWidget(_obsRateComboBox, 0, 1);
426 aLayout->addWidget(new QLabel("Failure threshold"), 1, 0);
427 aLayout->addWidget(_adviseFailSpinBox, 1, 1);
428 aLayout->addWidget(new QLabel("Recovery threshold"), 2, 0);
429 aLayout->addWidget(_adviseRecoSpinBox, 2, 1);
430 aLayout->addWidget(new QLabel("Pause"), 2, 2, Qt::AlignRight);
431 aLayout->addWidget(_makePauseCheckBox, 2, 3, Qt::AlignLeft);
432 aLayout->addWidget(new QLabel("Script (full path)"), 3, 0);
433 aLayout->addWidget(_adviseScriptLineEdit, 3, 1,1,10);
434 aLayout->addWidget(new QLabel("Performance log"), 4, 0);
435 aLayout->addWidget(_perfIntrComboBox, 4, 1);
436 aLayout->addWidget(new QLabel("Network monitoring, outages, handling of corrupted streams, latencies, statistics."),5,0,1,10,Qt::AlignLeft);
437 agroup->setLayout(aLayout);
438
439 QGridLayout* rLayout = new QGridLayout;
440 rLayout->setColumnMinimumWidth(0,14*ww);
441 rLayout->addWidget(new QLabel("Mountpoint"),0,0, Qt::AlignLeft);
442 rLayout->addWidget(_messTypesLineEdit,0,1,1,15,Qt::AlignLeft);
443 rLayout->addWidget(new QLabel("Scan RTCM Version 3.x stream to log numbers of message types and antenna information."),1, 0, 1, 4, Qt::AlignLeft);
444 rLayout->addWidget(new QLabel(" "),2,0);
445 rLayout->addWidget(new QLabel(" "),3,0);
446 rLayout->addWidget(new QLabel(" "),4,0);
447 rLayout->addWidget(new QLabel(" "),5,0);
448 rgroup->setLayout(rLayout);
449
450 QGridLayout* oLayout = new QGridLayout;
451 oLayout->setColumnMinimumWidth(0,14*ww);
452 oLayout->addWidget(new QLabel("Directory"), 0, 0);
453 oLayout->addWidget(_rnxPathLineEdit, 0, 1,1,12);
454 oLayout->addWidget(new QLabel("Interval"), 1, 0);
455 oLayout->addWidget(_rnxIntrComboBox, 1, 1);
456 oLayout->addWidget(new QLabel("Sampling"), 1, 2, Qt::AlignRight);
457 oLayout->addWidget(_rnxSamplSpinBox, 1, 3, Qt::AlignLeft);
458 oLayout->addWidget(new QLabel("Skeleton extension"), 2, 0);
459 oLayout->addWidget(_rnxSkelLineEdit, 2, 1,1,1, Qt::AlignLeft);
460 oLayout->addWidget(new QLabel("Script (full path)"), 3, 0);
461 oLayout->addWidget(_rnxScrpLineEdit, 3, 1,1,12);
462 oLayout->addWidget(new QLabel("Version 3"), 4, 0);
463 oLayout->addWidget(_rnxV3CheckBox, 4, 1);
464 oLayout->addWidget(new QLabel("Saving RINEX observation files."),5,0,1,12, Qt::AlignLeft);
465 ogroup->setLayout(oLayout);
466
467 QGridLayout* cLayout = new QGridLayout;
468 cLayout->setColumnMinimumWidth(0,14*ww);
469 cLayout->addWidget(new QLabel("Directory"), 0, 0);
470 cLayout->addWidget(_corrPathLineEdit, 0, 1);
471 cLayout->addWidget(new QLabel("Interval"), 1, 0);
472 cLayout->addWidget(_corrIntrComboBox, 1, 1);
473 cLayout->addWidget(new QLabel("Port"), 2, 0);
474 cLayout->addWidget(_corrPortLineEdit, 2, 1);
475 cLayout->addWidget(new QLabel("Wait for full epoch"), 3, 0);
476 cLayout->addWidget(_corrTimeSpinBox, 3, 1);
477 cLayout->addWidget(new QLabel("Saving Broadcast Ephemeris correction files and correction output through IP port."),4,0,1,2,Qt::AlignLeft);
478 cLayout->addWidget(new QLabel(" "),5,0);
479 cgroup->setLayout(cLayout);
480
481 QVBoxLayout* mLayout = new QVBoxLayout;
482 mLayout->addWidget(aogroup);
483 mLayout->addWidget(_mountPointsTable);
484 mLayout->addWidget(_log);
485
486 _canvas->setLayout(mLayout);
487}
488
489// Destructor
490////////////////////////////////////////////////////////////////////////////
491bncWindow::~bncWindow() {
492 delete _caster;
493}
494
495// Retrieve Table
496////////////////////////////////////////////////////////////////////////////
497void bncWindow::slotAddMountPoints() {
498
499 QSettings settings;
500 QString proxyHost = settings.value("proxyHost").toString();
501 int proxyPort = settings.value("proxyPort").toInt();
502 if (proxyHost != _proxyHostLineEdit->text() ||
503 proxyPort != _proxyPortLineEdit->text().toInt()) {
504 int iRet = QMessageBox::question(this, "Question", "Proxy options "
505 "changed. Use the new ones?",
506 QMessageBox::Yes, QMessageBox::No,
507 QMessageBox::NoButton);
508 if (iRet == QMessageBox::Yes) {
509 settings.setValue("proxyHost", _proxyHostLineEdit->text());
510 settings.setValue("proxyPort", _proxyPortLineEdit->text());
511 }
512 }
513
514 bncTableDlg* dlg = new bncTableDlg(this);
515 dlg->move(this->pos().x()+50, this->pos().y()+50);
516 connect(dlg, SIGNAL(newMountPoints(QStringList*)),
517 this, SLOT(slotNewMountPoints(QStringList*)));
518 dlg->exec();
519 delete dlg;
520
521}
522
523// Delete Selected Mount Points
524////////////////////////////////////////////////////////////////////////////
525void bncWindow::slotDeleteMountPoints() {
526
527 int nRows = _mountPointsTable->rowCount();
528 bool flg[nRows];
529 for (int iRow = 0; iRow < nRows; iRow++) {
530 if (_mountPointsTable->isItemSelected(_mountPointsTable->item(iRow,1))) {
531 flg[iRow] = true;
532 }
533 else {
534 flg[iRow] = false;
535 }
536 }
537 for (int iRow = nRows-1; iRow >= 0; iRow--) {
538 if (flg[iRow]) {
539 _mountPointsTable->removeRow(iRow);
540 }
541 }
542 _actDeleteMountPoints->setEnabled(false);
543
544 if (_mountPointsTable->rowCount() == 0) {
545 _actGetData->setEnabled(false);
546 }
547}
548
549// New Mount Points Selected
550////////////////////////////////////////////////////////////////////////////
551void bncWindow::slotNewMountPoints(QStringList* mountPoints) {
552 int iRow = 0;
553 QListIterator<QString> it(*mountPoints);
554 while (it.hasNext()) {
555 QStringList hlp = it.next().split(" ");
556 QUrl url(hlp[0]);
557 QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
558 QString format(hlp[1]); QString latitude(hlp[2]); QString longitude(hlp[3]);
559 QString nmea(hlp[4]);
560
561 _mountPointsTable->insertRow(iRow);
562
563 QTableWidgetItem* it;
564 it = new QTableWidgetItem(url.userInfo());
565 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
566 _mountPointsTable->setItem(iRow, 0, it);
567
568 it = new QTableWidgetItem(fullPath);
569 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
570 _mountPointsTable->setItem(iRow, 1, it);
571
572 it = new QTableWidgetItem(format);
573 _mountPointsTable->setItem(iRow, 2, it);
574
575 if (nmea == "yes") {
576 it = new QTableWidgetItem(latitude);
577 _mountPointsTable->setItem(iRow, 3, it);
578 it = new QTableWidgetItem(longitude);
579 _mountPointsTable->setItem(iRow, 4, it);
580 } else {
581 it = new QTableWidgetItem(latitude);
582 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
583 _mountPointsTable->setItem(iRow, 3, it);
584 it = new QTableWidgetItem(longitude);
585 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
586 _mountPointsTable->setItem(iRow, 4, it);
587 }
588
589 it = new QTableWidgetItem(nmea);
590 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
591 _mountPointsTable->setItem(iRow, 5, it);
592
593 bncTableItem* bncIt = new bncTableItem();
594 _mountPointsTable->setItem(iRow, 6, bncIt);
595
596 iRow++;
597 }
598 _mountPointsTable->hideColumn(0);
599 _mountPointsTable->sortItems(1);
600 if (mountPoints->count() > 0) {
601 _actGetData->setEnabled(true);
602 }
603 delete mountPoints;
604}
605
606// Save Options
607////////////////////////////////////////////////////////////////////////////
608void bncWindow::slotSaveOptions() {
609 QSettings settings;
610 settings.setValue("proxyHost", _proxyHostLineEdit->text());
611 settings.setValue("proxyPort", _proxyPortLineEdit->text());
612 settings.setValue("waitTime", _waitTimeSpinBox->value());
613 settings.setValue("obsRate", _obsRateComboBox->currentText());
614 settings.setValue("adviseFail", _adviseFailSpinBox->value());
615 settings.setValue("adviseReco", _adviseRecoSpinBox->value());
616 settings.setValue("makePause", _makePauseCheckBox->checkState());
617 settings.setValue("outFile", _outFileLineEdit->text());
618 settings.setValue("perfIntr", _perfIntrComboBox->currentText());
619 settings.setValue("outPort", _outPortLineEdit->text());
620 settings.setValue("outEphPort", _outEphPortLineEdit->text());
621 settings.setValue("corrPort", _corrPortLineEdit->text());
622 settings.setValue("corrTime", _corrTimeSpinBox->value());
623 settings.setValue("rnxPath", _rnxPathLineEdit->text());
624 settings.setValue("ephPath", _ephPathLineEdit->text());
625 settings.setValue("corrPath", _corrPathLineEdit->text());
626 settings.setValue("rnxScript", _rnxScrpLineEdit->text());
627 settings.setValue("rnxIntr", _rnxIntrComboBox->currentText());
628 settings.setValue("onTheFlyInterval", _onTheFlyComboBox->currentText());
629 settings.setValue("ephIntr", _ephIntrComboBox->currentText());
630 settings.setValue("corrIntr", _corrIntrComboBox->currentText());
631 settings.setValue("rnxSampl", _rnxSamplSpinBox->value());
632 settings.setValue("binSampl", _binSamplSpinBox->value());
633 settings.setValue("rnxSkel", _rnxSkelLineEdit->text());
634 settings.setValue("rnxAppend", _rnxAppendCheckBox->checkState());
635 settings.setValue("rnxV3", _rnxV3CheckBox->checkState());
636 settings.setValue("ephV3", _ephV3CheckBox->checkState());
637 settings.setValue("logFile", _logFileLineEdit->text());
638 settings.setValue("adviseScript",_adviseScriptLineEdit->text());
639 settings.setValue("messTypes", _messTypesLineEdit->text());
640
641QStringList mountPoints;
642
643 for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
644 QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
645 "@" + _mountPointsTable->item(iRow, 1)->text() );
646
647 mountPoints.append(url.toString() + " " +
648 _mountPointsTable->item(iRow, 2)->text()
649 + " " + _mountPointsTable->item(iRow, 3)->text()
650 + " " + _mountPointsTable->item(iRow, 4)->text()
651 + " " + _mountPointsTable->item(iRow, 5)->text());
652 }
653 settings.setValue("mountPoints", mountPoints);
654}
655
656// All get slots terminated
657////////////////////////////////////////////////////////////////////////////
658void bncWindow::slotGetThreadErrors() {
659 ((bncApp*)qApp)->slotMessage("All Get Threads Terminated");
660 _actAddMountPoints->setEnabled(true);
661 _actGetData->setEnabled(true);
662}
663
664// Retrieve Data
665////////////////////////////////////////////////////////////////////////////
666void bncWindow::slotGetData() {
667 slotSaveOptions();
668
669 _actAddMountPoints->setEnabled(false);
670 _actDeleteMountPoints->setEnabled(false);
671 _actGetData->setEnabled(false);
672 _actStop->setEnabled(true);
673
674 _caster = new bncCaster(_outFileLineEdit->text(),
675 _outPortLineEdit->text().toInt());
676
677 ((bncApp*)qApp)->setPort(_outEphPortLineEdit->text().toInt());
678 ((bncApp*)qApp)->setPortCorr(_corrPortLineEdit->text().toInt());
679
680 connect(_caster, SIGNAL(getThreadErrors()),
681 this, SLOT(slotGetThreadErrors()));
682
683 _caster->slotReadMountpoints();
684
685 ((bncApp*)qApp)->slotMessage("============ Start BNC ============");
686}
687
688// Retrieve Data
689////////////////////////////////////////////////////////////////////////////
690void bncWindow::slotStop() {
691 int iRet = QMessageBox::question(this, "Stop", "Stop retrieving data?",
692 QMessageBox::Yes, QMessageBox::No,
693 QMessageBox::NoButton);
694 if (iRet == QMessageBox::Yes) {
695 delete _caster; _caster = 0;
696 _actGetData->setEnabled(true);
697 _actStop->setEnabled(false);
698 _actAddMountPoints->setEnabled(true);
699 }
700}
701
702// Close Application gracefully
703////////////////////////////////////////////////////////////////////////////
704void bncWindow::closeEvent(QCloseEvent* event) {
705
706 int iRet = QMessageBox::question(this, "Close", "Save Options?",
707 QMessageBox::Yes, QMessageBox::No,
708 QMessageBox::Cancel);
709
710 if (iRet == QMessageBox::Cancel) {
711 event->ignore();
712 return;
713 }
714 else if (iRet == QMessageBox::Yes) {
715 slotSaveOptions();
716 }
717
718 QMainWindow::closeEvent(event);
719}
720
721// User changed the selection of mountPoints
722////////////////////////////////////////////////////////////////////////////
723void bncWindow::slotSelectionChanged() {
724 if (_mountPointsTable->selectedItems().isEmpty()) {
725 _actDeleteMountPoints->setEnabled(false);
726 }
727 else {
728 _actDeleteMountPoints->setEnabled(true);
729 }
730}
731
732// Display Program Messages
733////////////////////////////////////////////////////////////////////////////
734void bncWindow::slotMessage(const QByteArray msg) {
735
736 const int maxBufferSize = 10000;
737
738 QString txt = _log->toPlainText() + "\n" +
739 QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ") + msg;
740 _log->clear();
741 _log->append(txt.right(maxBufferSize));
742}
743
744// About Message
745////////////////////////////////////////////////////////////////////////////
746void bncWindow::slotAbout() {
747 new bncAboutDlg(0);
748}
749
750//Flowchart
751////////////////////////////////////////////////////////////////////////////
752void bncWindow::slotFlowchart() {
753 new bncFlowchartDlg(0);
754}
755
756// Help Window
757////////////////////////////////////////////////////////////////////////////
758void bncWindow::slotHelp() {
759 QUrl url;
760 url.setPath(":bnchelp.html");
761 new bncHlpDlg(0, url);
762}
763
764// Select Fonts
765////////////////////////////////////////////////////////////////////////////
766void bncWindow::slotFontSel() {
767 bool ok;
768 QFont newFont = QFontDialog::getFont(&ok, this->font(), this);
769 if (ok) {
770 QSettings settings;
771 settings.setValue("font", newFont.toString());
772 QApplication::setFont(newFont);
773 int ww = QFontMetrics(newFont).width('w');
774 setMinimumSize(60*ww, 80*ww);
775 resize(60*ww, 80*ww);
776 }
777}
778
779// Whats This Help
780void bncWindow::slotWhatsThis() {
781QWhatsThis::enterWhatsThisMode();
782}
783
784void bncWindow::CreateMenu() {
785 // Create Menus
786 // ------------
787 _menuFile = menuBar()->addMenu(tr("&File"));
788 _menuFile->addAction(_actFontSel);
789 _menuFile->addSeparator();
790 _menuFile->addAction(_actSaveOpt);
791 _menuFile->addSeparator();
792 _menuFile->addAction(_actQuit);
793
794 _menuHlp = menuBar()->addMenu(tr("&Help"));
795 _menuHlp->addAction(_actHelp);
796 _menuHlp->addAction(_actFlowchart);
797 _menuHlp->addAction(_actAbout);
798}
799
800void bncWindow::AddToolbar() {
801 // Tool (Command) Bar
802 // ------------------
803 QToolBar* toolBar = new QToolBar;
804 addToolBar(Qt::BottomToolBarArea, toolBar);
805 toolBar->setMovable(false);
806 toolBar->addAction(_actAddMountPoints);
807 toolBar->addAction(_actDeleteMountPoints);
808 toolBar->addAction(_actGetData);
809 toolBar->addAction(_actStop);
810 toolBar->addWidget(new QLabel(" "));
811 toolBar->addAction(_actwhatsthis);
812}
813
814bncAboutDlg::bncAboutDlg(QWidget* parent) :
815 QDialog(parent) {
816
817 QTextBrowser* tb = new QTextBrowser;
818 QUrl url; url.setPath(":bncabout.html");
819 tb->setSource(url);
820 tb->setReadOnly(true);
821
822 int ww = QFontMetrics(font()).width('w');
823 QPushButton* _closeButton = new QPushButton("Close");
824 _closeButton->setMaximumWidth(10*ww);
825 connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
826
827 QGridLayout* dlgLayout = new QGridLayout();
828 QLabel* img = new QLabel();
829 img->setPixmap(QPixmap(":ntrip-logo.png"));
830 dlgLayout->addWidget(img, 0,0);
831 dlgLayout->addWidget(new QLabel("BKG Ntrip Client (BNC) Version 1.6"), 0,1);
832 dlgLayout->addWidget(tb,1,0,1,2);
833 dlgLayout->addWidget(_closeButton,2,1,Qt::AlignRight);
834
835 setLayout(dlgLayout);
836 resize(60*ww, 60*ww);
837 show();
838}
839
840bncAboutDlg::~bncAboutDlg() {
841};
842
843bncFlowchartDlg::bncFlowchartDlg(QWidget* parent) :
844 QDialog(parent) {
845
846 int ww = QFontMetrics(font()).width('w');
847 QPushButton* _closeButton = new QPushButton("Close");
848 _closeButton->setMaximumWidth(10*ww);
849 connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
850
851 QGridLayout* dlgLayout = new QGridLayout();
852 QLabel* img = new QLabel();
853 img->setPixmap(QPixmap(":bncflowchart.png"));
854 dlgLayout->addWidget(img, 0,0);
855 dlgLayout->addWidget(_closeButton,1,0,Qt::AlignLeft);
856
857 setLayout(dlgLayout);
858 show();
859}
860
861bncFlowchartDlg::~bncFlowchartDlg() {
862};
863
Note: See TracBrowser for help on using the repository browser.