source: ntrip/trunk/BNC/bncapp.cpp@ 643

Last change on this file since 643 was 642, checked in by mervart, 18 years ago

* empty log message *

File size: 18.3 KB
RevLine 
[280]1// Part of BNC, a utility for retrieving decoding and
[464]2// converting GNSS data streams from NTRIP broadcasters.
[280]3//
[464]4// Copyright (C) 2007
[280]5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
[464]7// Czech Technical University Prague, Department of Geodesy
[280]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.
[82]24
25/* -------------------------------------------------------------------------
[93]26 * BKG NTRIP Client
[82]27 * -------------------------------------------------------------------------
28 *
29 * Class: bncApp
30 *
31 * Purpose: This class implements the main application
32 *
33 * Author: L. Mervart
34 *
35 * Created: 29-Aug-2006
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
[149]42#include <QSettings>
[150]43#include <QMessageBox>
[519]44#include <cmath>
[642]45#include <unistd.h>
[82]46
47#include "bncapp.h"
[151]48#include "bncutils.h"
[82]49
50using namespace std;
51
[523]52struct converttimeinfo {
53 int second; /* seconds of GPS time [0..59] */
54 int minute; /* minutes of GPS time [0..59] */
55 int hour; /* hour of GPS time [0..24] */
56 int day; /* day of GPS time [1..28..30(31)*/
57 int month; /* month of GPS time [1..12]*/
58 int year; /* year of GPS time [1980..] */
59};
60
61extern "C" {
62 void converttime(struct converttimeinfo *c, int week, int tow);
63 void updatetime(int *week, int *tow, int tk, int fixnumleap);
64}
65
[82]66// Constructor
67////////////////////////////////////////////////////////////////////////////
68bncApp::bncApp(int argc, char* argv[], bool GUIenabled) :
69 QApplication(argc, argv, GUIenabled) {
[109]70
[565]71 _bncVersion = "BNC 1.5";
[533]72
[150]73 _logFileFlag = 0;
74 _logFile = 0;
75 _logStream = 0;
[621]76 _caster = 0;
[152]77
[516]78 // Lists of Ephemeris
79 // ------------------
80 for (int ii = PRN_GPS_START; ii <= PRN_GPS_END; ii++) {
81 _gpsEph[ii-PRN_GPS_START] = 0;
82 }
83 for (int ii = PRN_GLONASS_START; ii <= PRN_GLONASS_END; ii++) {
84 _glonassEph[ii-PRN_GLONASS_START] = 0;
85 }
86
[533]87 // Eph file(s)
88 // -----------
[534]89 _rinexVers = 0;
[533]90 _ephFileGPS = 0;
91 _ephStreamGPS = 0;
92 _ephFileGlonass = 0;
93 _ephStreamGlonass = 0;
[559]94
[591]95 _port = 0;
[589]96 _server = 0;
97 _sockets = 0;
98
[559]99 _pgmName = _bncVersion.leftJustified(20, ' ', true);
100#ifdef WIN32
101 _userName = QString("${USERNAME}");
102#else
103 _userName = QString("${USER}");
104#endif
105 expandEnvVar(_userName);
106 _userName = _userName.leftJustified(20, ' ', true);
[82]107}
108
109// Destructor
110////////////////////////////////////////////////////////////////////////////
111bncApp::~bncApp() {
[109]112 delete _logStream;
113 delete _logFile;
[533]114 delete _ephStreamGPS;
115 delete _ephFileGPS;
[589]116 delete _server;
117 delete _sockets;
[534]118 if (_rinexVers == 2) {
[533]119 delete _ephStreamGlonass;
120 delete _ephFileGlonass;
121 }
[516]122 for (int ii = PRN_GPS_START; ii <= PRN_GPS_END; ii++) {
123 delete _gpsEph[ii-PRN_GPS_START];
124 }
125 for (int ii = PRN_GLONASS_START; ii <= PRN_GLONASS_END; ii++) {
126 delete _glonassEph[ii-PRN_GLONASS_START];
127 }
[82]128}
129
130// Write a Program Message
131////////////////////////////////////////////////////////////////////////////
132void bncApp::slotMessage(const QByteArray msg) {
[150]133
[243]134 QMutexLocker locker(&_mutex);
135
[150]136 // First time resolve the log file name
137 // ------------------------------------
138 if (_logFileFlag == 0) {
139 _logFileFlag = 1;
140 QSettings settings;
141 QString logFileName = settings.value("logFile").toString();
142 if ( !logFileName.isEmpty() ) {
[151]143 expandEnvVar(logFileName);
[150]144 _logFile = new QFile(logFileName);
[275]145 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked) {
146 _logFile->open(QIODevice::WriteOnly | QIODevice::Append);
147 }
148 else {
149 _logFile->open(QIODevice::WriteOnly);
150 }
[150]151 _logStream = new QTextStream();
152 _logStream->setDevice(_logFile);
153 }
154 }
155
[109]156 if (_logStream) {
[566]157 *_logStream << QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ").toAscii().data();
[109]158 *_logStream << msg.data() << endl;
159 _logStream->flush();
[82]160 }
161}
[511]162
[535]163// New GPS Ephemeris
[511]164////////////////////////////////////////////////////////////////////////////
165void bncApp::slotNewGPSEph(gpsephemeris* gpseph) {
[516]166
167 QMutexLocker locker(&_mutex);
168
[534]169 printEphHeader();
170
[533]171 if (!_ephStreamGPS) {
[517]172 delete gpseph;
173 return;
174 }
175
[532]176 gpsephemeris** ee = &_gpsEph[gpseph->satellite-1];
[538]177 if ( *ee == 0 ||
178 gpseph->GPSweek > (*ee)->GPSweek ||
[594]179 (gpseph->GPSweek == (*ee)->GPSweek && gpseph->TOC > (*ee)->TOC) ) {
[516]180 delete *ee;
181 *ee = gpseph;
[600]182 printGPSEph(gpseph, true);
[516]183 }
184 else {
[600]185 printGPSEph(gpseph, false);
[516]186 delete gpseph;
187 }
[511]188}
189
[535]190// New Glonass Ephemeris
[511]191////////////////////////////////////////////////////////////////////////////
192void bncApp::slotNewGlonassEph(glonassephemeris* glonasseph) {
[516]193
194 QMutexLocker locker(&_mutex);
195
[534]196 printEphHeader();
197
[533]198 if (!_ephStreamGlonass) {
[517]199 delete glonasseph;
200 return;
201 }
202
[532]203 glonassephemeris** ee = &_glonassEph[glonasseph->almanac_number-1];
[531]204
[578]205 int wwOld, towOld, wwNew, towNew;
[577]206 if (*ee != 0) {
[578]207 wwOld = (*ee)->GPSWeek;
208 towOld = (*ee)->GPSTOW;
209 updatetime(&wwOld, &towOld, (*ee)->tb*1000, 1);
[577]210
[578]211 wwNew = glonasseph->GPSWeek;
212 towNew = glonasseph->GPSTOW;
213 updatetime(&wwNew, &towNew, glonasseph->tb*1000, 1);
[577]214 }
215
[578]216 if ( *ee == 0 ||
217 wwNew > wwOld ||
218 (wwNew == wwOld && towNew > towOld) ) {
[531]219 delete *ee;
220 *ee = glonasseph;
[600]221 printGlonassEph(glonasseph, true);
[531]222 }
223 else {
[600]224 printGlonassEph(glonasseph, false);
[531]225 delete glonasseph;
226 }
[511]227}
228
[535]229// Print Header of the output File(s)
[516]230////////////////////////////////////////////////////////////////////////////
231void bncApp::printEphHeader() {
[528]232
[535]233 QSettings settings;
234
[534]235 // Initialization
236 // --------------
237 if (_rinexVers == 0) {
[528]238
[533]239 if ( Qt::CheckState(settings.value("ephV3").toInt()) == Qt::Checked) {
[534]240 _rinexVers = 3;
[533]241 }
242 else {
[534]243 _rinexVers = 2;
[533]244 }
[529]245
[533]246 _ephPath = settings.value("ephPath").toString();
247
248 if ( !_ephPath.isEmpty() ) {
249 if ( _ephPath[_ephPath.length()-1] != QDir::separator() ) {
250 _ephPath += QDir::separator();
251 }
252 expandEnvVar(_ephPath);
253 }
[517]254 }
[533]255
[534]256 // (Re-)Open output File(s)
257 // ------------------------
[533]258 if (!_ephPath.isEmpty()) {
259
[566]260 QDateTime datTim = QDateTime::currentDateTime().toUTC();
[533]261
[583]262 QString ephFileNameGPS = _ephPath + "BRDC" +
[563]263 QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0'));
[533]264
[563]265 QString hlpStr;
266 QString intStr = settings.value("ephIntr").toString();
267 if (intStr == "1 day") {
268 hlpStr = "0";
269 }
270 else if (intStr == "1 hour") {
271 char ch = 'A' + datTim.time().hour();
272 hlpStr = ch;
273 }
[584]274 else if (intStr == "15 min") {
[563]275 char ch = 'A' + datTim.time().hour();
276 hlpStr = ch;
277 if (datTim.time().minute() < 15) {
278 hlpStr += "00";
279 }
280 else if (datTim.time().minute() < 30) {
281 hlpStr += "15";
282 }
283 else if (datTim.time().minute() < 45) {
284 hlpStr += "30";
285 }
286 else {
287 hlpStr += "45";
288 }
289 }
[584]290 else {
291 char ch = 'A' + datTim.time().hour();
292 hlpStr = ch;
293 if (datTim.time().minute() < 5) {
294 hlpStr += "00";
295 }
296 else if (datTim.time().minute() < 10) {
297 hlpStr += "05";
298 }
299 else if (datTim.time().minute() < 15) {
300 hlpStr += "10";
301 }
302 else if (datTim.time().minute() < 20) {
303 hlpStr += "15";
304 }
305 else if (datTim.time().minute() < 25) {
306 hlpStr += "20";
307 }
308 else if (datTim.time().minute() < 30) {
309 hlpStr += "25";
310 }
311 else if (datTim.time().minute() < 35) {
312 hlpStr += "30";
313 }
314 else if (datTim.time().minute() < 40) {
315 hlpStr += "35";
316 }
317 else if (datTim.time().minute() < 45) {
318 hlpStr += "40";
319 }
320 else if (datTim.time().minute() < 50) {
321 hlpStr += "45";
322 }
323 else if (datTim.time().minute() < 55) {
324 hlpStr += "50";
325 }
326 else {
327 hlpStr += "55";
328 }
329 }
330
[575]331 if (_rinexVers == 3) {
332 ephFileNameGPS += hlpStr + datTim.toString(".yyP");
333 }
334 else {
335 ephFileNameGPS += hlpStr + datTim.toString(".yyN");
336 }
[563]337
[533]338 if (_ephFileNameGPS == ephFileNameGPS) {
339 return;
340 }
341 else {
342 _ephFileNameGPS = ephFileNameGPS;
343 }
344
[575]345 for (int ii = PRN_GPS_START; ii <= PRN_GPS_END; ii++) {
346 delete _gpsEph[ii-PRN_GPS_START];
347 _gpsEph[ii-PRN_GPS_START] = 0;
348 }
349 for (int ii = PRN_GLONASS_START; ii <= PRN_GLONASS_END; ii++) {
350 delete _glonassEph[ii-PRN_GLONASS_START];
351 _glonassEph[ii-PRN_GLONASS_START] = 0;
352 }
353
[533]354 delete _ephStreamGPS;
355 delete _ephFileGPS;
356
[535]357 QFlags<QIODevice::OpenModeFlag> appendFlagGPS;
[536]358 QFlags<QIODevice::OpenModeFlag> appendFlagGlonass;
359
[535]360 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
361 QFile::exists(ephFileNameGPS) ) {
362 appendFlagGPS = QIODevice::Append;
363 }
364
[533]365 _ephFileGPS = new QFile(ephFileNameGPS);
[535]366 _ephFileGPS->open(QIODevice::WriteOnly | appendFlagGPS);
[533]367 _ephStreamGPS = new QTextStream();
368 _ephStreamGPS->setDevice(_ephFileGPS);
369
[534]370 if (_rinexVers == 3) {
[533]371 _ephFileGlonass = _ephFileGPS;
372 _ephStreamGlonass = _ephStreamGPS;
373 }
[534]374 else if (_rinexVers == 2) {
[583]375 QString ephFileNameGlonass = _ephPath + "BRDC" +
[563]376 QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
[575]377 hlpStr + datTim.toString(".yyG");
[533]378
379 delete _ephStreamGlonass;
380 delete _ephFileGlonass;
381
[535]382 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
383 QFile::exists(ephFileNameGlonass) ) {
384 appendFlagGlonass = QIODevice::Append;
385 }
386
[533]387 _ephFileGlonass = new QFile(ephFileNameGlonass);
[535]388 _ephFileGlonass->open(QIODevice::WriteOnly | appendFlagGlonass);
[533]389 _ephStreamGlonass = new QTextStream();
390 _ephStreamGlonass->setDevice(_ephFileGlonass);
391 }
392
[534]393 // Header - RINEX Version 3
394 // ------------------------
395 if (_rinexVers == 3) {
[537]396 if ( ! (appendFlagGPS & QIODevice::Append)) {
397 QString line;
398 line.sprintf(
399 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n",
400 3.0, "", "");
401 *_ephStreamGPS << line;
402
[566]403 QString hlp = QDateTime::currentDateTime().toUTC().toString("yyyyMMdd hhmmss UTC").leftJustified(20, ' ', true);
[559]404 *_ephStreamGPS << _pgmName.toAscii().data()
405 << _userName.toAscii().data()
406 << hlp.toAscii().data()
407 << "PGM / RUN BY / DATE" << endl;
408
409 line.sprintf("%60sEND OF HEADER\n", "");
[537]410 *_ephStreamGPS << line;
411
412 _ephStreamGPS->flush();
[535]413 }
[533]414 }
415
[536]416 // Headers - RINEX Version 2
417 // -------------------------
[534]418 else if (_rinexVers == 2) {
[536]419 if (! (appendFlagGPS & QIODevice::Append)) {
420 QString line;
421 line.sprintf(
[565]422 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.11, "", "");
[536]423 *_ephStreamGPS << line;
424
[566]425 QString hlp = QDateTime::currentDateTime().toUTC().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
[559]426 *_ephStreamGPS << _pgmName.toAscii().data()
427 << _userName.toAscii().data()
428 << hlp.toAscii().data()
429 << "PGM / RUN BY / DATE" << endl;
430
431 line.sprintf("%60sEND OF HEADER\n", "");
[536]432 *_ephStreamGPS << line;
[537]433
434 _ephStreamGPS->flush();
[536]435 }
436 if (! (appendFlagGlonass & QIODevice::Append)) {
437 QString line;
438 line.sprintf(
[582]439 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n",2.11,"","");
[536]440 *_ephStreamGlonass << line;
441
[566]442 QString hlp = QDateTime::currentDateTime().toUTC().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
[559]443 *_ephStreamGlonass << _pgmName.toAscii().data()
444 << _userName.toAscii().data()
445 << hlp.toAscii().data()
446 << "PGM / RUN BY / DATE" << endl;
447
448 line.sprintf("%60sEND OF HEADER\n", "");
[536]449 *_ephStreamGlonass << line;
[537]450
451 _ephStreamGlonass->flush();
[536]452 }
[533]453 }
454 }
[516]455}
456
[535]457// Print One GPS Ephemeris
[516]458////////////////////////////////////////////////////////////////////////////
[600]459void bncApp::printGPSEph(gpsephemeris* ep, bool printFile) {
[519]460
[590]461 QString line;
462 QByteArray allLines;
[533]463
[590]464 struct converttimeinfo cti;
465 converttime(&cti, ep->GPSweek, ep->TOC);
466 if (_rinexVers == 3) {
467 line.sprintf("G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
[589]468 ep->satellite, cti.year, cti.month, cti.day, cti.hour,
469 cti.minute, cti.second, ep->clock_bias, ep->clock_drift,
470 ep->clock_driftrate);
[590]471 }
472 else if (_rinexVers == 2) {
473 line.sprintf("%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
474 ep->satellite, cti.year%100, cti.month, cti.day, cti.hour,
475 cti.minute, (double) cti.second, ep->clock_bias,
476 ep->clock_drift, ep->clock_driftrate);
477 }
478 allLines += line;
[520]479
[590]480 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", (double)ep->IODE,
481 ep->Crs, ep->Delta_n, ep->M0);
482 allLines += line;
483
484 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->Cuc,
485 ep->e, ep->Cus, ep->sqrt_A);
486 allLines += line;
[520]487
[590]488 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n",
489 (double) ep->TOE, ep->Cic, ep->OMEGA0, ep->Cis);
490 allLines += line;
491
492 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->i0,
493 ep->Crc, ep->omega, ep->OMEGADOT);
494 allLines += line;
[520]495
[590]496 double dd = 0;
497 unsigned long ii = ep->flags;
498 if(ii & GPSEPHF_L2CACODE)
499 dd += 2.0;
500 if(ii & GPSEPHF_L2PCODE)
501 dd += 1.0;
502 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->IDOT, dd,
503 (double) ep->GPSweek, ii & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
504 allLines += line;
[520]505
[590]506 if(ep->URAindex <= 6) /* URA index */
507 dd = ceil(10.0*pow(2.0, 1.0+((double)ep->URAindex)/2.0))/10.0;
508 else
509 dd = ceil(10.0*pow(2.0, ((double)ep->URAindex)/2.0))/10.0;
510 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", dd,
511 ((double) ep->SVhealth), ep->TGD, ((double) ep->IODC));
512 allLines += line;
[519]513
[590]514 line.sprintf(" %19.12e%19.12e\n", ((double)ep->TOW), 0.0);
515 allLines += line;
[519]516
[590]517 // Output into file
518 // ----------------
[600]519 if (printFile && _ephStreamGPS) {
[592]520 *_ephStreamGPS << allLines;
[533]521 _ephStreamGPS->flush();
[590]522 }
[589]523
[590]524 // Output into the socket
525 // ----------------------
526 if (_sockets) {
[642]527 QMutableListIterator<QTcpSocket*> is(*_sockets);
[590]528 while (is.hasNext()) {
529 QTcpSocket* sock = is.next();
530 if (sock->state() == QAbstractSocket::ConnectedState) {
[642]531 int fd = sock->socketDescriptor();
532 if (::write(fd, allLines.data(), allLines.size()) != allLines.size()) {
533 delete sock;
534 is.remove();
535 }
[589]536 }
[642]537 else if (sock->state() != QAbstractSocket::ConnectingState) {
538 delete sock;
539 is.remove();
540 }
[589]541 }
[517]542 }
[516]543}
544
[535]545// Print One Glonass Ephemeris
[516]546////////////////////////////////////////////////////////////////////////////
[600]547void bncApp::printGlonassEph(glonassephemeris* ep, bool printFile) {
[523]548
[590]549 QString line;
550 QByteArray allLines;
[523]551
[590]552 int ww = ep->GPSWeek;
553 int tow = ep->GPSTOW;
554 struct converttimeinfo cti;
[523]555
[590]556 updatetime(&ww, &tow, ep->tb*1000, 1);
557 converttime(&cti, ww, tow);
[525]558
[590]559 int ii = ep->tk-3*60*60;
560 if (ii < 0) {
561 ii += 86400;
562 }
[525]563
[590]564 if (_rinexVers == 3) {
565 line.sprintf("R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
566 ep->almanac_number, cti.year, cti.month, cti.day, cti.hour,
567 cti.minute, cti.second, -ep->tau, ep->gamma, (double) ii);
568 }
569 else if (_rinexVers == 2) {
570 line.sprintf("%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
571 ep->almanac_number, cti.year%100, cti.month, cti.day,
572 cti.hour, cti.minute, (double) cti.second, -ep->tau,
573 ep->gamma, (double) ii);
574 }
575 allLines += line;
576
577 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->x_pos,
578 ep->x_velocity, ep->x_acceleration,
579 (ep->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
580 allLines += line;
581
582 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->y_pos,
583 ep->y_velocity, ep->y_acceleration,
584 (double) ep->frequency_number);
585 allLines += line;
586
587 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->z_pos,
588 ep->z_velocity, ep->z_acceleration, (double) ep->E);
589 allLines += line;
[525]590
[590]591 // Output into file
592 // ----------------
[600]593 if (printFile && _ephStreamGlonass) {
[592]594 *_ephStreamGlonass << allLines;
[533]595 _ephStreamGlonass->flush();
[517]596 }
[590]597
598 // Output into the socket
599 // ----------------------
600 if (_sockets) {
[642]601 QMutableListIterator<QTcpSocket*> is(*_sockets);
[590]602 while (is.hasNext()) {
603 QTcpSocket* sock = is.next();
604 if (sock->state() == QAbstractSocket::ConnectedState) {
[642]605 int fd = sock->socketDescriptor();
606 if (::write(fd, allLines.data(), allLines.size()) != allLines.size()) {
607 delete sock;
608 is.remove();
609 }
[590]610 }
[642]611 else if (sock->state() != QAbstractSocket::ConnectingState) {
612 delete sock;
613 is.remove();
614 }
[590]615 }
616 }
[516]617}
[589]618
[591]619// Set Port Number
620////////////////////////////////////////////////////////////////////////////
621void bncApp::setPort(int port) {
622 _port = port;
623 if (_port != 0) {
624 _server = new QTcpServer;
625 _server->listen(QHostAddress::Any, _port);
626 connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
627 _sockets = new QList<QTcpSocket*>;
628 }
629}
630
[589]631// New Connection
632////////////////////////////////////////////////////////////////////////////
633void bncApp::slotNewConnection() {
634 _sockets->push_back( _server->nextPendingConnection() );
635}
636
[621]637//
638////////////////////////////////////////////////////////////////////////////
639void bncApp::slotQuit() {
640 cout << "bncApp::slotQuit" << endl;
641 delete _caster;
642 quit();
643}
644
645
Note: See TracBrowser for help on using the repository browser.