Changeset 10657 in ntrip


Ignore:
Timestamp:
Jun 2, 2025, 9:22:52 AM (11 days ago)
Author:
stuerze
Message:

upload to caster revised

Location:
trunk/BNC/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/src/bncmain.cpp

    r10619 r10657  
    318318      "                          euref-ip.net,2101,SSRA02IGS1_EUREF,2,usr,pass,ETRF2000,RTCM-SSR,0,,,,258,2,0\"]}\n"
    319319      "   uploadIntr             {Length of SP3, Clock RINEX and Bias SINEX file interval [character string: 1 min|2 min|5 min|10 min|15 min|30 min|1 hour|1 day]}\n"
    320       "   uploadSamplRtcmEphCorr {Orbit corrections stream sampling rate [integer number of seconds: 0|5|10|15|20|25|30|35|40|45|50|55|60]}\n"
     320      "   uploadSamplRtcmEphCorr {Orbit corrections stream sampling rate [integer number of seconds: 0 sec|1 sec|2 sec|5 sec|10 sec|15 sec|30 sec|60 sec]}\n"
    321321      "   uploadSamplSp3         {SP3 file sampling rate [integer number of seconds: 0 sec|30 sec|60 sec|300 sec|900 sec]}\n"
    322322      "   uploadSamplClkRnx      {Clock RINEX file sampling rate [integer number of seconds: 0|5|10|15|20|25|30|35|40|45|50|55|60]}\n"
  • trunk/BNC/src/bncsettings.cpp

    r10619 r10657  
    2525////////////////////////////////////////////////////////////////////////////
    2626bncSettings::bncSettings() {
    27   QMutexLocker locker(&_mutex);
    28 
    29   // First fill the options
    30   // ----------------------
    31   if (BNC_CORE->_settings.size() == 0) {
    32     reRead();
    33   }
     27    QMutexLocker locker(&_mutex);
     28
     29    // First fill the options
     30    // ----------------------
     31    if (BNC_CORE->_settings.size() == 0) {
     32        reRead();
     33    }
    3434}
    3535
     
    4343void bncSettings::reRead() {
    4444
    45   QSettings settings(BNC_CORE->confFileName(), QSettings::IniFormat);
    46 
    47   // Read from File
    48   // --------------
    49   if (settings.allKeys().size() > 0) {
    50     QStringListIterator it(settings.allKeys());
     45    QSettings settings(BNC_CORE->confFileName(), QSettings::IniFormat);
     46
     47    // Read from File
     48    // --------------
     49    if (settings.allKeys().size() > 0) {
     50        QStringListIterator it(settings.allKeys());
     51        while (it.hasNext()) {
     52            QString key = it.next();
     53            BNC_CORE->_settings[key] = settings.value(key);
     54        }
     55    }
     56
     57    // Set Defaults
     58    // ------------
     59    else {
     60        setValue_p("startTab", "0");
     61        setValue_p("statusTab", "0");
     62        setValue_p("font", "");
     63        setValue_p("casterUrlList", (QStringList()
     64            << "http://user:pass@euref-ip.net:2101"
     65            << "http://user:pass@igs-ip.net:2101"
     66            << "http://user:pass@products.igs-ip.net:2101"
     67            << "http://user:pass@mgex.igs-ip.net:2101"));
     68        setValue_p("mountPoints", "");
     69        setValue_p("ntripVersion", "2");
     70        // Network
     71        setValue_p("proxyHost", "");
     72        setValue_p("proxyPort", "");
     73        setValue_p("sslCaCertPath", "");
     74        setValue_p("sslClientCertPath", "");
     75        setValue_p("sslIgnoreErrors", "0");
     76        // General
     77        setValue_p("logFile", "");
     78        setValue_p("rnxAppend", "0");
     79        setValue_p("onTheFlyInterval", "no");
     80        setValue_p("autoStart", "0");
     81        setValue_p("rawOutFile", "");
     82        // RINEX Observations
     83        setValue_p("rnxPath", "");
     84        setValue_p("rnxIntr", "1 day");
     85        setValue_p("rnxOnlyWithSKL", "");
     86        setValue_p("rnxSampl", "1 sec");
     87        setValue_p("rnxSkel", "skl");
     88        setValue_p("rnxSkelPath", "");
     89        setValue_p("rnxV2Priority", "");
     90        setValue_p("rnxScript", "");
     91        setValue_p("rnxVersion", "3");
     92        // RINEX Ephemeris
     93        setValue_p("ephPath", "");
     94        setValue_p("ephIntr", "1 day");
     95        setValue_p("ephOutPort", "");
     96        setValue_p("ephVersion", "3");
     97        // Reqc
     98        setValue_p("reqcAction", "");
     99        setValue_p("reqcObsFile", "");
     100        setValue_p("reqcNavFile", "");
     101        setValue_p("reqcOutObsFile", "");
     102        setValue_p("reqcOutNavFile", "");
     103        setValue_p("reqcOutLogFile", "");
     104        setValue_p("reqcSkyPlotSignals", "G:1&2&5 R:1&2&3 E:1&7 C:2&6 J:1&2 I:5&9 S:1&5");
     105        setValue_p("reqcPlotDir", "");
     106        setValue_p("reqcRnxVersion", "");
     107        setValue_p("reqcSampling", "1 sec");
     108        setValue_p("reqcStartDateTime", "1967-11-02T00:00:00");
     109        setValue_p("reqcEndDateTime", "2099-01-01T00:00:00");
     110        setValue_p("reqcLogSummaryOnly", "");
     111        setValue_p("reqcRunBy", "");
     112        setValue_p("reqcComment", "");
     113        setValue_p("reqcOldMarkerName", "");
     114        setValue_p("reqcNewMarkerName", "");
     115        setValue_p("reqcOldAntennaName", "");
     116        setValue_p("reqcNewAntennaName", "");
     117        setValue_p("reqcOldReceiverName", "");
     118        setValue_p("reqcNewReceiverName", "");
     119        setValue_p("reqcOldAntennaNumber", "");
     120        setValue_p("reqcNewAntennaNumber", "");
     121        setValue_p("reqcOldAntennadE", "");
     122        setValue_p("reqcNewAntennadE", "");
     123        setValue_p("reqcOldAntennadN", "");
     124        setValue_p("reqcNewAntennadN", "");
     125        setValue_p("reqcOldAntennadU", "");
     126        setValue_p("reqcNewAntennadU", "");
     127        setValue_p("reqcOldReceiverNumber", "");
     128        setValue_p("reqcNewReceiverNumber", "");
     129        setValue_p("reqcUseObsTypes", "");
     130        setValue_p("reqcV2Priority", "G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX R:46&ABX E:16&BCXZ E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:267&IQX C:18&DPX I:ABCX S:1&C S:5&IQX");
     131        // SP3
     132        setValue_p("sp3CompFile", "");
     133        setValue_p("sp3CompExclude", "");
     134        setValue_p("sp3CompOutLogFile", "");
     135        setValue_p("sp3CompSummaryOnly", "");
     136        // Braodcast Corrections
     137        setValue_p("corrPath", "");
     138        setValue_p("corrIntr", "1 day");
     139        setValue_p("corrPort", "");
     140        // Feed Engine
     141        setValue_p("outPort", "");
     142        setValue_p("outWait", "5");
     143        setValue_p("outSampl", "1 sec");
     144        setValue_p("outFile", "");
     145        setValue_p("outUPort", "");
     146        setValue_p("outLockTime", "0");
     147        // Serial Output
     148        setValue_p("serialMountPoint", "");
     149        setValue_p("serialPortName", "");
     150        setValue_p("serialBaudRate", "9600");
     151        setValue_p("serialFlowControl", "OFF");
     152        setValue_p("serialDataBits", "8");
     153        setValue_p("serialParity", "NONE");
     154        setValue_p("serialStopBits", "1");
     155        setValue_p("serialAutoNMEA", "Auto");
     156        setValue_p("serialFileNMEA", "");
     157        setValue_p("serialHeightNMEA", "");
     158        setValue_p("serialNMEASampling", "10");
     159        // Outages
     160        setValue_p("adviseObsRate", "");
     161        setValue_p("adviseFail", "15");
     162        setValue_p("adviseReco", "5");
     163        setValue_p("adviseScript", "");
     164        // Miscellaneous
     165        setValue_p("miscMount", "");
     166        setValue_p("miscIntr", "");
     167        setValue_p("miscScanRTCM", "0");
     168        setValue_p("miscPort", "");
     169        // Combination
     170        setValue_p("cmbStreams", "");
     171        setValue_p("cmbMethod", "");
     172        setValue_p("cmbMaxres", "");
     173        setValue_p("cmbMaxdisplacement", "");
     174        setValue_p("cmbSampl", "10 sec");
     175        setValue_p("cmbLogpath", "");
     176        setValue_p("cmbGps", "2");
     177        setValue_p("cmbGlo", "2");
     178        setValue_p("cmbGal", "2");
     179        setValue_p("cmbBds", "2");
     180        setValue_p("cmbQzss", "0");
     181        setValue_p("cmbSbas", "0");
     182        setValue_p("cmbNavic", "0");
     183
     184        // Upload (clk)
     185        setValue_p("uploadMountpointsOut", "");
     186        setValue_p("uploadIntr", "1 day");
     187        setValue_p("uploadSamplRtcmEphCorr", "5 sec");
     188        setValue_p("uploadSamplSp3", "30 sec");
     189        setValue_p("uploadSamplClkRnx", "5 sec");
     190        setValue_p("uploadSamplBiaSnx", "5 sec");
     191        setValue_p("trafo_dx", "");
     192        setValue_p("trafo_dy", "");
     193        setValue_p("trafo_dz", "");
     194        setValue_p("trafo_dxr", "");
     195        setValue_p("trafo_dyr", "");
     196        setValue_p("trafo_dzr", "");
     197        setValue_p("trafo_ox", "");
     198        setValue_p("trafo_oy", "");
     199        setValue_p("trafo_oz", "");
     200        setValue_p("trafo_oxr", "");
     201        setValue_p("trafo_oyr", "");
     202        setValue_p("trafo_ozr", "");
     203        setValue_p("trafo_sc", "");
     204        setValue_p("trafo_scr", "");
     205        setValue_p("trafo_t0", "");
     206        // Upload (eph)
     207        setValue_p("uploadEphMountpointsOut", "");
     208        setValue_p("uploadSamplRtcmEph", "5");
     209    }
     210}
     211
     212//
     213////////////////////////////////////////////////////////////////////////////
     214QVariant bncSettings::value(const QString& key,
     215    const QVariant& defaultValue) const {
     216    QMutexLocker locker(&_mutex);
     217
     218    if (BNC_CORE->_settings.contains(key)) {
     219        return BNC_CORE->_settings[key];
     220    }
     221    else {
     222        return defaultValue;
     223    }
     224}
     225
     226//
     227////////////////////////////////////////////////////////////////////////////
     228void bncSettings::setValue(const QString& key, const QVariant& value) {
     229    QMutexLocker locker(&_mutex);
     230    setValue_p(key, value);
     231}
     232
     233//
     234////////////////////////////////////////////////////////////////////////////
     235void bncSettings::setValue_p(const QString& key, const QVariant& value) {
     236    BNC_CORE->_settings[key] = value;
     237}
     238
     239//
     240////////////////////////////////////////////////////////////////////////////
     241void bncSettings::remove(const QString& key) {
     242    QMutexLocker locker(&_mutex);
     243    BNC_CORE->_settings.remove(key);
     244}
     245
     246//
     247////////////////////////////////////////////////////////////////////////////
     248bool bncSettings::contains(const QString& key) const {
     249    QMutexLocker locker(&_mutex);
     250    return BNC_CORE->_settings.contains(key);
     251}
     252
     253//
     254////////////////////////////////////////////////////////////////////////////
     255void bncSettings::sync() {
     256    QMutexLocker locker(&_mutex);
     257    QSettings settings(BNC_CORE->confFileName(), QSettings::IniFormat);
     258    settings.clear();
     259    QMapIterator<QString, QVariant> it(BNC_CORE->_settings);
     260
    51261    while (it.hasNext()) {
    52       QString key = it.next();
    53       BNC_CORE->_settings[key] = settings.value(key);
    54     }
    55   }
    56 
    57   // Set Defaults
    58   // ------------
    59   else {
    60     setValue_p("startTab",            "0");
    61     setValue_p("statusTab",           "0");
    62     setValue_p("font",                "");
    63     setValue_p("casterUrlList", (QStringList()
    64                                << "http://user:pass@euref-ip.net:2101"
    65                                << "http://user:pass@igs-ip.net:2101"
    66                                << "http://user:pass@products.igs-ip.net:2101"
    67                                << "http://user:pass@mgex.igs-ip.net:2101"));
    68     setValue_p("mountPoints",         "");
    69     setValue_p("ntripVersion",       "2");
    70     // Network
    71     setValue_p("proxyHost",           "");
    72     setValue_p("proxyPort",           "");
    73     setValue_p("sslCaCertPath",       "");
    74     setValue_p("sslClientCertPath",   "");
    75     setValue_p("sslIgnoreErrors",    "0");
    76     // General
    77     setValue_p("logFile",             "");
    78     setValue_p("rnxAppend",          "0");
    79     setValue_p("onTheFlyInterval",  "no");
    80     setValue_p("autoStart",          "0");
    81     setValue_p("rawOutFile",          "");
    82     // RINEX Observations
    83     setValue_p("rnxPath",             "");
    84     setValue_p("rnxIntr",        "1 day");
    85     setValue_p("rnxOnlyWithSKL",      "");
    86     setValue_p("rnxSampl",       "1 sec");
    87     setValue_p("rnxSkel",          "skl");
    88     setValue_p("rnxSkelPath",         "");
    89     setValue_p("rnxV2Priority",       "");
    90     setValue_p("rnxScript",           "");
    91     setValue_p("rnxVersion",         "3");
    92     // RINEX Ephemeris
    93     setValue_p("ephPath",             "");
    94     setValue_p("ephIntr",        "1 day");
    95     setValue_p("ephOutPort",          "");
    96     setValue_p("ephVersion",         "3");
    97     // Reqc
    98     setValue_p("reqcAction",          "");
    99     setValue_p("reqcObsFile",         "");
    100     setValue_p("reqcNavFile",         "");
    101     setValue_p("reqcOutObsFile",      "");
    102     setValue_p("reqcOutNavFile",      "");
    103     setValue_p("reqcOutLogFile",      "");
    104     setValue_p("reqcSkyPlotSignals",  "G:1&2&5 R:1&2&3 E:1&7 C:2&6 J:1&2 I:5&9 S:1&5");
    105     setValue_p("reqcPlotDir",         "");
    106     setValue_p("reqcRnxVersion",      "");
    107     setValue_p("reqcSampling",        "1 sec");
    108     setValue_p("reqcStartDateTime",   "1967-11-02T00:00:00");
    109     setValue_p("reqcEndDateTime",     "2099-01-01T00:00:00");
    110     setValue_p("reqcLogSummaryOnly",  "");
    111     setValue_p("reqcRunBy",           "");
    112     setValue_p("reqcComment",         "");
    113     setValue_p("reqcOldMarkerName",   "");
    114     setValue_p("reqcNewMarkerName",   "");
    115     setValue_p("reqcOldAntennaName",  "");
    116     setValue_p("reqcNewAntennaName",  "");
    117     setValue_p("reqcOldReceiverName", "");
    118     setValue_p("reqcNewReceiverName", "");
    119     setValue_p("reqcOldAntennaNumber", "");
    120     setValue_p("reqcNewAntennaNumber","");
    121     setValue_p("reqcOldAntennadE",    "");
    122     setValue_p("reqcNewAntennadE",    "");
    123     setValue_p("reqcOldAntennadN",    "");
    124     setValue_p("reqcNewAntennadN",    "");
    125     setValue_p("reqcOldAntennadU",    "");
    126     setValue_p("reqcNewAntennadU",    "");
    127     setValue_p("reqcOldReceiverNumber", "");
    128     setValue_p("reqcNewReceiverNumber", "");
    129     setValue_p("reqcUseObsTypes",     "");
    130     setValue_p("reqcV2Priority",      "G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX R:46&ABX E:16&BCXZ E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:267&IQX C:18&DPX I:ABCX S:1&C S:5&IQX");
    131     // SP3
    132     setValue_p("sp3CompFile",         "");
    133     setValue_p("sp3CompExclude",      "");
    134     setValue_p("sp3CompOutLogFile",   "");
    135     setValue_p("sp3CompSummaryOnly",  "");
    136     // Braodcast Corrections
    137     setValue_p("corrPath",            "");
    138     setValue_p("corrIntr",       "1 day");
    139     setValue_p("corrPort",            "");
    140     // Feed Engine
    141     setValue_p("outPort",             "");
    142     setValue_p("outWait",            "5");
    143     setValue_p("outSampl",       "1 sec");
    144     setValue_p("outFile",             "");
    145     setValue_p("outUPort",            "");
    146     setValue_p("outLockTime",        "0");
    147     // Serial Output
    148     setValue_p("serialMountPoint",    "");
    149     setValue_p("serialPortName",      "");
    150     setValue_p("serialBaudRate",  "9600");
    151     setValue_p("serialFlowControl",   "OFF");
    152     setValue_p("serialDataBits",     "8");
    153     setValue_p("serialParity",    "NONE");
    154     setValue_p("serialStopBits",     "1");
    155     setValue_p("serialAutoNMEA",  "Auto");
    156     setValue_p("serialFileNMEA",      "");
    157     setValue_p("serialHeightNMEA",    "");
    158     setValue_p("serialNMEASampling", "10");
    159     // Outages
    160     setValue_p("adviseObsRate",       "");
    161     setValue_p("adviseFail",        "15");
    162     setValue_p("adviseReco",         "5");
    163     setValue_p("adviseScript",        "");
    164     // Miscellaneous
    165     setValue_p("miscMount",           "");
    166     setValue_p("miscIntr",            "");
    167     setValue_p("miscScanRTCM",       "0");
    168     setValue_p("miscPort",            "");
    169     // Combination
    170     setValue_p("cmbStreams",          "");
    171     setValue_p("cmbMethod",           "");
    172     setValue_p("cmbMaxres",           "");
    173     setValue_p("cmbMaxdisplacement",  "");
    174     setValue_p("cmbSampl",          "10");
    175     setValue_p("cmbLogpath",          "");
    176     setValue_p("cmbGps",             "2");
    177     setValue_p("cmbGlo",             "2");
    178     setValue_p("cmbGal",             "2");
    179     setValue_p("cmbBds",             "2");
    180     setValue_p("cmbQzss",            "0");
    181     setValue_p("cmbSbas",            "0");
    182     setValue_p("cmbNavic",           "0");
    183 
    184     // Upload (clk)
    185     setValue_p("uploadMountpointsOut","");
    186     setValue_p("uploadIntr",     "1 day");
    187     setValue_p("uploadSamplRtcmEphCorr", "0");
    188     setValue_p("uploadSamplSp3",    "0 sec");
    189     setValue_p("uploadSamplClkRnx", "0");
    190     setValue_p("uploadSamplBiaSnx", "0");
    191     setValue_p("trafo_dx",            "");
    192     setValue_p("trafo_dy",            "");
    193     setValue_p("trafo_dz",            "");
    194     setValue_p("trafo_dxr",           "");
    195     setValue_p("trafo_dyr",           "");
    196     setValue_p("trafo_dzr",           "");
    197     setValue_p("trafo_ox",            "");
    198     setValue_p("trafo_oy",            "");
    199     setValue_p("trafo_oz",            "");
    200     setValue_p("trafo_oxr",           "");
    201     setValue_p("trafo_oyr",           "");
    202     setValue_p("trafo_ozr",           "");
    203     setValue_p("trafo_sc",            "");
    204     setValue_p("trafo_scr",           "");
    205     setValue_p("trafo_t0",            "");
    206     // Upload (eph)
    207     setValue_p("uploadEphMountpointsOut","");
    208     setValue_p("uploadSamplRtcmEph",     "5");
    209   }
    210 }
    211 
    212 //
    213 ////////////////////////////////////////////////////////////////////////////
    214 QVariant bncSettings::value(const QString& key,
    215                             const QVariant& defaultValue) const {
    216   QMutexLocker locker(&_mutex);
    217 
    218   if (BNC_CORE->_settings.contains(key)) {
    219     return BNC_CORE->_settings[key];
    220   }
    221   else {
    222     return defaultValue;
    223   }
    224 }
    225 
    226 //
    227 ////////////////////////////////////////////////////////////////////////////
    228 void bncSettings::setValue(const QString &key, const QVariant& value) {
    229   QMutexLocker locker(&_mutex);
    230   setValue_p(key, value);
    231 }
    232 
    233 //
    234 ////////////////////////////////////////////////////////////////////////////
    235 void bncSettings::setValue_p(const QString &key, const QVariant& value) {
    236   BNC_CORE->_settings[key] = value;
    237 }
    238 
    239 //
    240 ////////////////////////////////////////////////////////////////////////////
    241 void bncSettings::remove(const QString& key ) {
    242   QMutexLocker locker(&_mutex);
    243   BNC_CORE->_settings.remove(key);
    244 }
    245 
    246 //
    247 ////////////////////////////////////////////////////////////////////////////
    248 bool bncSettings::contains(const QString& key) const {
    249   QMutexLocker locker(&_mutex);
    250   return BNC_CORE->_settings.contains(key);
    251 }
    252 
    253 //
    254 ////////////////////////////////////////////////////////////////////////////
    255 void bncSettings::sync() {
    256   QMutexLocker locker(&_mutex);
    257   QSettings settings(BNC_CORE->confFileName(), QSettings::IniFormat);
    258   settings.clear();
    259   QMapIterator<QString, QVariant> it(BNC_CORE->_settings);
    260 
    261   while (it.hasNext()) {
    262     it.next();
    263     settings.setValue(it.key(), it.value());
    264   }
    265 
    266   settings.sync();
    267 }
     262        it.next();
     263        settings.setValue(it.key(), it.value());
     264    }
     265
     266    settings.sync();
     267}
  • trunk/BNC/src/bncwindow.cpp

    r10638 r10657  
    102102bncWindow::bncWindow() {
    103103
    104   const static QPalette paletteWhite(QColor(255, 255, 255));
    105   const static QPalette paletteGray(QColor(230, 230, 230));
    106 
    107   _caster    = 0;
    108   _casterEph = 0;
    109 
    110   _bncFigure    = new bncFigure(this);
    111   _bncFigureLate = new bncFigureLate(this);
    112   _bncFigurePPP  = new bncFigurePPP(this);
    113 
    114   connect(BNC_CORE, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)),
    115           _bncFigurePPP, SLOT(slotNewPosition(QByteArray, bncTime, QVector<double>)));
    116 
    117   connect(BNC_CORE, SIGNAL(progressRnxPPP(int)), this, SLOT(slotPostProcessingProgress(int)));
    118   connect(BNC_CORE, SIGNAL(finishedRnxPPP()),    this, SLOT(slotPostProcessingFinished()));
    119 
    120   _runningRealTime    = false;
    121   _runningPPP        = false;
    122   _runningEdit        = false;
    123   _runningQC          = false;
    124   _runningSp3Comp    = false;
    125   _reqcActionComboBox = 0; // necessary for enableStartStop()
    126 
    127   _mapWin = 0;
    128 
    129   int ww = QFontMetrics(this->font()).horizontalAdvance('w');
    130 
    131   static const QStringList labels = QString("account, Streams:   resource loader / mountpoint, decoder, country, lat, long, nmea, ntrip, bytes").split(",");
    132 
    133   setMinimumSize(100*ww, 70*ww);
    134 
    135   setWindowTitle(tr("BKG Ntrip Client (BNC) Version " BNCVERSION));
    136 
    137   connect(BNC_CORE, SIGNAL(newMessage(QByteArray,bool)),
    138           this, SLOT(slotWindowMessage(QByteArray,bool)));
    139 
    140   // Create Actions
    141   // --------------
    142   _actHelp = new QAction(tr("&Help Contents"),this);
    143   connect(_actHelp, SIGNAL(triggered()), SLOT(slotHelp()));
    144 
    145   _actAbout = new QAction(tr("&About BNC"),this);
    146   connect(_actAbout, SIGNAL(triggered()), SLOT(slotAbout()));
    147 
    148   _actFlowchart = new QAction(tr("&Flow Chart"),this);
    149   connect(_actFlowchart, SIGNAL(triggered()), SLOT(slotFlowchart()));
    150 
    151   _actFontSel = new QAction(tr("Select &Font"),this);
    152   connect(_actFontSel, SIGNAL(triggered()), SLOT(slotFontSel()));
    153 
    154   _actSaveOpt = new QAction(tr("&Reread && Save Configuration"),this);
    155   connect(_actSaveOpt, SIGNAL(triggered()), SLOT(slotSaveOptions()));
    156 
    157   _actQuit  = new QAction(tr("&Quit"),this);
    158   connect(_actQuit, SIGNAL(triggered()), SLOT(close()));
    159 
    160   _actAddMountPoints = new QAction(tr("Add &Stream"),this);
    161   connect(_actAddMountPoints, SIGNAL(triggered()), SLOT(slotAddMountPoints()));
    162 
    163   _actDeleteMountPoints = new QAction(tr("&Delete Stream"),this);
    164   connect(_actDeleteMountPoints, SIGNAL(triggered()), SLOT(slotDeleteMountPoints()));
    165   _actDeleteMountPoints->setEnabled(false);
    166 
    167   _actMapMountPoints = new QAction(tr("&Map"),this);
    168   connect(_actMapMountPoints, SIGNAL(triggered()), SLOT(slotMapMountPoints()));
    169 
    170   _actStart = new QAction(tr("Sta&rt"),this);
    171   connect(_actStart, SIGNAL(triggered()), SLOT(slotStart()));
    172 
    173   _actStop = new QAction(tr("Sto&p"),this);
    174   connect(_actStop, SIGNAL(triggered()), SLOT(slotStop()));
    175   connect(_actStop, SIGNAL(triggered()), SLOT(slotMapPPPClosed()));
    176 
    177   _actwhatsthis= new QAction(tr("Help?=Shift+F1"),this);
    178   connect(_actwhatsthis, SIGNAL(triggered()), SLOT(slotWhatsThis()));
    179 
    180   CreateMenu();
    181   AddToolbar();
    182 
    183   bncSettings settings;
    184 
    185   // Network Options
    186   // ---------------
    187   _proxyHostLineEdit  = new QLineEdit(settings.value("proxyHost").toString());
    188   _proxyPortLineEdit  = new QLineEdit(settings.value("proxyPort").toString());
    189 
    190   connect(_proxyHostLineEdit, SIGNAL(textChanged(const QString &)),
    191           this, SLOT(slotBncTextChanged()));
    192 
    193   _sslCaCertPathLineEdit    = new QLineEdit(settings.value("sslCaCertPath").toString());
    194   _sslClientCertPathLineEdit = new QLineEdit(settings.value("sslClientCertPath").toString());
    195   _sslIgnoreErrorsCheckBox  = new QCheckBox();
    196   _sslIgnoreErrorsCheckBox->setCheckState(Qt::CheckState(
    197                                           settings.value("sslIgnoreErrors").toInt()));
    198 
    199   // General Options
    200   // ---------------
    201   _logFileLineEdit    = new QLineEdit(settings.value("logFile").toString());
    202   _rawOutFileLineEdit = new QLineEdit(settings.value("rawOutFile").toString());
    203   _rnxAppendCheckBox  = new QCheckBox();
    204   _rnxAppendCheckBox->setCheckState(Qt::CheckState(
    205                                     settings.value("rnxAppend").toInt()));
    206   _onTheFlyComboBox = new QComboBox();
    207   _onTheFlyComboBox->setEditable(false);
    208   _onTheFlyComboBox->addItems(QString("no,1 day,1 hour,5 min,1 min").split(","));
    209   int go = _onTheFlyComboBox->findText(settings.value("onTheFlyInterval").toString());
    210   if (go != -1) {
    211     _onTheFlyComboBox->setCurrentIndex(go);
    212   }
    213   _autoStartCheckBox  = new QCheckBox();
    214   _autoStartCheckBox->setCheckState(Qt::CheckState(
    215                                     settings.value("autoStart").toInt()));
    216 
    217   // RINEX Observations Options
    218   // --------------------------
    219   _rnxPathLineEdit = new QLineEdit(settings.value("rnxPath").toString());
    220   _rnxIntrComboBox = new QComboBox();
    221   _rnxIntrComboBox->setEditable(false);
    222   _rnxIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
    223   int ii = _rnxIntrComboBox->findText(settings.value("rnxIntr").toString());
    224   if (ii != -1) {
    225     _rnxIntrComboBox->setCurrentIndex(ii);
    226   }
    227   _rnxSamplComboBox = new QComboBox();
    228   _rnxSamplComboBox->setEditable(false);
    229   _rnxSamplComboBox->addItems(QString("0.1 sec,1 sec,5 sec,10 sec,15 sec,30 sec,60 sec").split(","));
    230   int ij = _rnxSamplComboBox->findText(settings.value("rnxSampl").toString());
    231   if (ij != -1) {
    232     _rnxSamplComboBox->setCurrentIndex(ij);
    233   }
    234   _rnxFileCheckBox = new QCheckBox();
    235   _rnxFileCheckBox->setCheckState(Qt::CheckState(settings.value("rnxOnlyWithSKL").toInt()));
    236   _rnxSkelExtComboBox  = new QComboBox();
    237   _rnxSkelExtComboBox->setEditable(false);
    238   _rnxSkelExtComboBox->addItems(QString("skl,SKL").split(","));
    239   int ik = _rnxSkelExtComboBox->findText(settings.value("rnxSkel").toString());
    240   if (ik != -1) {
    241     _rnxSkelExtComboBox->setCurrentIndex(ik);
    242   }
    243   _rnxSkelPathLineEdit = new QLineEdit(settings.value("rnxSkelPath").toString());
    244   _rnxScrpLineEdit = new QLineEdit(settings.value("rnxScript").toString());
    245   _rnxVersComboBox = new QComboBox();
    246   _rnxVersComboBox->setEditable(false);
    247   _rnxVersComboBox->addItems(QString("4,3,2").split(","));
    248   _rnxVersComboBox->setMaximumWidth(7*ww);
    249   int il = _rnxVersComboBox->findText(settings.value("rnxVersion").toString());
    250   if (il != -1) {
    251     _rnxVersComboBox->setCurrentIndex(il);
    252   }
    253   QString hlp = settings.value("rnxV2Priority").toString();
    254   if (hlp.isEmpty()) {
    255     hlp = "G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX R:46&ABX E:16&BCXZ E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:267&IQX C:18&DPX I:ABCX S:1&C S:5&IQX";
    256   }
    257   _rnxV2Priority = new QLineEdit(hlp);
    258 
    259   connect(_rnxPathLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(slotBncTextChanged()));
    260   connect(_rnxSkelPathLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(slotBncTextChanged()));
    261   connect(_rnxVersComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(slotBncTextChanged()));
    262 
    263   // RINEX Ephemeris Options
    264   // -----------------------
    265   _ephPathLineEdit = new QLineEdit(settings.value("ephPath").toString());
    266   _ephIntrComboBox = new QComboBox();
    267   _ephIntrComboBox->setEditable(false);
    268   _ephIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
    269   int ji = _ephIntrComboBox->findText(settings.value("ephIntr").toString());
    270   if (ji != -1) {
    271     _ephIntrComboBox->setCurrentIndex(ji);
    272   }
    273   _ephOutPortLineEdit = new QLineEdit(settings.value("ephOutPort").toString());
    274   _ephVersComboBox = new QComboBox();
    275   _ephVersComboBox->setEditable(false);
    276   _ephVersComboBox->addItems(QString("4,3,2").split(","));
    277   _ephVersComboBox->setMaximumWidth(7*ww);
    278   int jk = _ephVersComboBox->findText(settings.value("ephVersion").toString());
    279   if (jk != -1) {
    280     _ephVersComboBox->setCurrentIndex(jk);
    281   }
    282   //_ephFilePerStation = new QCheckBox();
    283   //_ephFilePerStation->setCheckState(Qt::CheckState(settings.value("ephFilePerStation").toInt()));
    284 
    285   connect(_ephOutPortLineEdit, SIGNAL(textChanged(const QString &)),
    286           this, SLOT(slotBncTextChanged()));
    287 
    288   connect(_ephPathLineEdit, SIGNAL(textChanged(const QString &)),
    289           this, SLOT(slotBncTextChanged()));
    290 
    291   // Broadcast Corrections Options
    292   // -----------------------------
    293   _corrPathLineEdit    = new QLineEdit(settings.value("corrPath").toString());
    294   _corrIntrComboBox    = new QComboBox();
    295   _corrIntrComboBox->setEditable(false);
    296   _corrIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
    297   int bi = _corrIntrComboBox->findText(settings.value("corrIntr").toString());
    298   if (bi != -1) {
    299     _corrIntrComboBox->setCurrentIndex(bi);
    300   }
    301   _corrPortLineEdit    = new QLineEdit(settings.value("corrPort").toString());
    302 
    303   connect(_corrPathLineEdit, SIGNAL(textChanged(const QString &)),
    304           this, SLOT(slotBncTextChanged()));
    305 
    306   connect(_corrPortLineEdit, SIGNAL(textChanged(const QString &)),
    307           this, SLOT(slotBncTextChanged()));
    308 
    309   // Feed Engine Options
    310   // -------------------
    311   _outPortLineEdit = new QLineEdit(settings.value("outPort").toString());
    312   _outWaitSpinBox = new QSpinBox();
    313   _outWaitSpinBox->setMinimum(0);
    314   _outWaitSpinBox->setMaximum(30);
    315   _outWaitSpinBox->setSingleStep(1);
    316   _outWaitSpinBox->setSuffix(" sec");
    317   _outWaitSpinBox->setValue(settings.value("outWait").toInt());
    318   _outSamplComboBox = new QComboBox();
    319   _outSamplComboBox->addItems(QString("0.1 sec,1 sec,5 sec,10 sec,15 sec,30 sec,60 sec").split(","));
    320   int nn = _outSamplComboBox->findText(settings.value("outSampl").toString());
     104    const static QPalette paletteWhite(QColor(255, 255, 255));
     105    const static QPalette paletteGray(QColor(230, 230, 230));
     106
     107    _caster = 0;
     108    _casterEph = 0;
     109
     110    _bncFigure = new bncFigure(this);
     111    _bncFigureLate = new bncFigureLate(this);
     112    _bncFigurePPP = new bncFigurePPP(this);
     113
     114    connect(BNC_CORE, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)),
     115        _bncFigurePPP, SLOT(slotNewPosition(QByteArray, bncTime, QVector<double>)));
     116
     117    connect(BNC_CORE, SIGNAL(progressRnxPPP(int)), this, SLOT(slotPostProcessingProgress(int)));
     118    connect(BNC_CORE, SIGNAL(finishedRnxPPP()), this, SLOT(slotPostProcessingFinished()));
     119
     120    _runningRealTime = false;
     121    _runningPPP = false;
     122    _runningEdit = false;
     123    _runningQC = false;
     124    _runningSp3Comp = false;
     125    _reqcActionComboBox = 0; // necessary for enableStartStop()
     126
     127    _mapWin = 0;
     128
     129    int ww = QFontMetrics(this->font()).horizontalAdvance('w');
     130
     131    static const QStringList labels = QString("account, Streams:   resource loader / mountpoint, decoder, country, lat, long, nmea, ntrip, bytes").split(",");
     132
     133    setMinimumSize(100 * ww, 70 * ww);
     134
     135    setWindowTitle(tr("BKG Ntrip Client (BNC) Version " BNCVERSION));
     136
     137    connect(BNC_CORE, SIGNAL(newMessage(QByteArray, bool)),
     138        this, SLOT(slotWindowMessage(QByteArray, bool)));
     139
     140    // Create Actions
     141    // --------------
     142    _actHelp = new QAction(tr("&Help Contents"), this);
     143    connect(_actHelp, SIGNAL(triggered()), SLOT(slotHelp()));
     144
     145    _actAbout = new QAction(tr("&About BNC"), this);
     146    connect(_actAbout, SIGNAL(triggered()), SLOT(slotAbout()));
     147
     148    _actFlowchart = new QAction(tr("&Flow Chart"), this);
     149    connect(_actFlowchart, SIGNAL(triggered()), SLOT(slotFlowchart()));
     150
     151    _actFontSel = new QAction(tr("Select &Font"), this);
     152    connect(_actFontSel, SIGNAL(triggered()), SLOT(slotFontSel()));
     153
     154    _actSaveOpt = new QAction(tr("&Reread && Save Configuration"), this);
     155    connect(_actSaveOpt, SIGNAL(triggered()), SLOT(slotSaveOptions()));
     156
     157    _actQuit = new QAction(tr("&Quit"), this);
     158    connect(_actQuit, SIGNAL(triggered()), SLOT(close()));
     159
     160    _actAddMountPoints = new QAction(tr("Add &Stream"), this);
     161    connect(_actAddMountPoints, SIGNAL(triggered()), SLOT(slotAddMountPoints()));
     162
     163    _actDeleteMountPoints = new QAction(tr("&Delete Stream"), this);
     164    connect(_actDeleteMountPoints, SIGNAL(triggered()), SLOT(slotDeleteMountPoints()));
     165    _actDeleteMountPoints->setEnabled(false);
     166
     167    _actMapMountPoints = new QAction(tr("&Map"), this);
     168    connect(_actMapMountPoints, SIGNAL(triggered()), SLOT(slotMapMountPoints()));
     169
     170    _actStart = new QAction(tr("Sta&rt"), this);
     171    connect(_actStart, SIGNAL(triggered()), SLOT(slotStart()));
     172
     173    _actStop = new QAction(tr("Sto&p"), this);
     174    connect(_actStop, SIGNAL(triggered()), SLOT(slotStop()));
     175    connect(_actStop, SIGNAL(triggered()), SLOT(slotMapPPPClosed()));
     176
     177    _actwhatsthis = new QAction(tr("Help?=Shift+F1"), this);
     178    connect(_actwhatsthis, SIGNAL(triggered()), SLOT(slotWhatsThis()));
     179
     180    CreateMenu();
     181    AddToolbar();
     182
     183    bncSettings settings;
     184
     185    // Network Options
     186    // ---------------
     187    _proxyHostLineEdit = new QLineEdit(settings.value("proxyHost").toString());
     188    _proxyPortLineEdit = new QLineEdit(settings.value("proxyPort").toString());
     189
     190    connect(_proxyHostLineEdit, SIGNAL(textChanged(const QString&)),
     191        this, SLOT(slotBncTextChanged()));
     192
     193    _sslCaCertPathLineEdit = new QLineEdit(settings.value("sslCaCertPath").toString());
     194    _sslClientCertPathLineEdit = new QLineEdit(settings.value("sslClientCertPath").toString());
     195    _sslIgnoreErrorsCheckBox = new QCheckBox();
     196    _sslIgnoreErrorsCheckBox->setCheckState(Qt::CheckState(
     197        settings.value("sslIgnoreErrors").toInt()));
     198
     199    // General Options
     200    // ---------------
     201    _logFileLineEdit = new QLineEdit(settings.value("logFile").toString());
     202    _rawOutFileLineEdit = new QLineEdit(settings.value("rawOutFile").toString());
     203    _rnxAppendCheckBox = new QCheckBox();
     204    _rnxAppendCheckBox->setCheckState(Qt::CheckState(
     205        settings.value("rnxAppend").toInt()));
     206    _onTheFlyComboBox = new QComboBox();
     207    _onTheFlyComboBox->setEditable(false);
     208    _onTheFlyComboBox->addItems(QString("no,1 day,1 hour,5 min,1 min").split(","));
     209    int go = _onTheFlyComboBox->findText(settings.value("onTheFlyInterval").toString());
     210    if (go != -1) {
     211        _onTheFlyComboBox->setCurrentIndex(go);
     212    }
     213    _autoStartCheckBox = new QCheckBox();
     214    _autoStartCheckBox->setCheckState(Qt::CheckState(
     215        settings.value("autoStart").toInt()));
     216
     217    // RINEX Observations Options
     218    // --------------------------
     219    _rnxPathLineEdit = new QLineEdit(settings.value("rnxPath").toString());
     220    _rnxIntrComboBox = new QComboBox();
     221    _rnxIntrComboBox->setEditable(false);
     222    _rnxIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
     223    int ii = _rnxIntrComboBox->findText(settings.value("rnxIntr").toString());
     224    if (ii != -1) {
     225        _rnxIntrComboBox->setCurrentIndex(ii);
     226    }
     227    _rnxSamplComboBox = new QComboBox();
     228    _rnxSamplComboBox->setEditable(false);
     229    _rnxSamplComboBox->addItems(QString("0.1 sec,1 sec,5 sec,10 sec,15 sec,30 sec,60 sec").split(","));
     230    int ij = _rnxSamplComboBox->findText(settings.value("rnxSampl").toString());
     231    if (ij != -1) {
     232        _rnxSamplComboBox->setCurrentIndex(ij);
     233    }
     234    _rnxFileCheckBox = new QCheckBox();
     235    _rnxFileCheckBox->setCheckState(Qt::CheckState(settings.value("rnxOnlyWithSKL").toInt()));
     236    _rnxSkelExtComboBox = new QComboBox();
     237    _rnxSkelExtComboBox->setEditable(false);
     238    _rnxSkelExtComboBox->addItems(QString("skl,SKL").split(","));
     239    int ik = _rnxSkelExtComboBox->findText(settings.value("rnxSkel").toString());
     240    if (ik != -1) {
     241        _rnxSkelExtComboBox->setCurrentIndex(ik);
     242    }
     243    _rnxSkelPathLineEdit = new QLineEdit(settings.value("rnxSkelPath").toString());
     244    _rnxScrpLineEdit = new QLineEdit(settings.value("rnxScript").toString());
     245    _rnxVersComboBox = new QComboBox();
     246    _rnxVersComboBox->setEditable(false);
     247    _rnxVersComboBox->addItems(QString("4,3,2").split(","));
     248    _rnxVersComboBox->setMaximumWidth(7 * ww);
     249    int il = _rnxVersComboBox->findText(settings.value("rnxVersion").toString());
     250    if (il != -1) {
     251        _rnxVersComboBox->setCurrentIndex(il);
     252    }
     253    QString hlp = settings.value("rnxV2Priority").toString();
     254    if (hlp.isEmpty()) {
     255        hlp = "G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX R:46&ABX E:16&BCXZ E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:267&IQX C:18&DPX I:ABCX S:1&C S:5&IQX";
     256    }
     257    _rnxV2Priority = new QLineEdit(hlp);
     258
     259    connect(_rnxPathLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(slotBncTextChanged()));
     260    connect(_rnxSkelPathLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(slotBncTextChanged()));
     261    connect(_rnxVersComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(slotBncTextChanged()));
     262
     263    // RINEX Ephemeris Options
     264    // -----------------------
     265    _ephPathLineEdit = new QLineEdit(settings.value("ephPath").toString());
     266    _ephIntrComboBox = new QComboBox();
     267    _ephIntrComboBox->setEditable(false);
     268    _ephIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
     269    int ji = _ephIntrComboBox->findText(settings.value("ephIntr").toString());
     270    if (ji != -1) {
     271        _ephIntrComboBox->setCurrentIndex(ji);
     272    }
     273    _ephOutPortLineEdit = new QLineEdit(settings.value("ephOutPort").toString());
     274    _ephVersComboBox = new QComboBox();
     275    _ephVersComboBox->setEditable(false);
     276    _ephVersComboBox->addItems(QString("4,3,2").split(","));
     277    _ephVersComboBox->setMaximumWidth(7 * ww);
     278    int jk = _ephVersComboBox->findText(settings.value("ephVersion").toString());
     279    if (jk != -1) {
     280        _ephVersComboBox->setCurrentIndex(jk);
     281    }
     282    //_ephFilePerStation = new QCheckBox();
     283    //_ephFilePerStation->setCheckState(Qt::CheckState(settings.value("ephFilePerStation").toInt()));
     284
     285    connect(_ephOutPortLineEdit, SIGNAL(textChanged(const QString&)),
     286        this, SLOT(slotBncTextChanged()));
     287
     288    connect(_ephPathLineEdit, SIGNAL(textChanged(const QString&)),
     289        this, SLOT(slotBncTextChanged()));
     290
     291    // Broadcast Corrections Options
     292    // -----------------------------
     293    _corrPathLineEdit = new QLineEdit(settings.value("corrPath").toString());
     294    _corrIntrComboBox = new QComboBox();
     295    _corrIntrComboBox->setEditable(false);
     296    _corrIntrComboBox->addItems(QString("1 min,2 min,5 min,10 min,15 min,30 min,1 hour,1 day").split(","));
     297    int bi = _corrIntrComboBox->findText(settings.value("corrIntr").toString());
     298    if (bi != -1) {
     299        _corrIntrComboBox->setCurrentIndex(bi);
     300    }
     301    _corrPortLineEdit = new QLineEdit(settings.value("corrPort").toString());
     302
     303    connect(_corrPathLineEdit, SIGNAL(textChanged(const QString&)),
     304        this, SLOT(slotBncTextChanged()));
     305
     306    connect(_corrPortLineEdit, SIGNAL(textChanged(const QString&)),
     307        this, SLOT(slotBncTextChanged()));
     308
     309    // Feed Engine Options
     310    // -------------------
     311    _outPortLineEdit = new QLineEdit(settings.value("outPort").toString());
     312    _outWaitSpinBox = new QSpinBox();
     313    _outWaitSpinBox->setMinimum(0);
     314    _outWaitSpinBox->setMaximum(30);
     315    _outWaitSpinBox->setSingleStep(1);
     316    _outWaitSpinBox->setSuffix(" sec");
     317    _outWaitSpinBox->setValue(settings.value("outWait").toInt());
     318    _outSamplComboBox = new QComboBox();
     319    _outSamplComboBox->addItems(QString("0.1 sec,1 sec,5 sec,10 sec,15 sec,30 sec,60 sec").split(","));
     320    int nn = _outSamplComboBox->findText(settings.value("outSampl").toString());
    321321    if (nn != -1) {
    322       _outSamplComboBox->setCurrentIndex(nn);
    323     }
    324   _outFileLineEdit = new QLineEdit(settings.value("outFile").toString());
    325   _outUPortLineEdit = new QLineEdit(settings.value("outUPort").toString());
    326   _outLockTimeCheckBox = new QCheckBox();
    327   _outLockTimeCheckBox->setCheckState(Qt::CheckState(settings.value("outLockTime").toInt()));
    328 
    329   connect(_outPortLineEdit, SIGNAL(textChanged(const QString &)),
    330           this, SLOT(slotBncTextChanged()));
    331 
    332   connect(_outFileLineEdit, SIGNAL(textChanged(const QString &)),
    333           this, SLOT(slotBncTextChanged()));
    334 
    335   connect(_outLockTimeCheckBox, SIGNAL(stateChanged(int)),
    336           this, SLOT(slotBncTextChanged()));
    337 
    338   // Serial Output Options
    339   // ---------------------
    340   _serialMountPointLineEdit = new QLineEdit(settings.value("serialMountPoint").toString());
    341   _serialPortNameLineEdit = new QLineEdit(settings.value("serialPortName").toString());
    342   _serialBaudRateComboBox = new QComboBox();
    343   _serialBaudRateComboBox->addItems(QString("110,300,600,"
    344             "1200,2400,4800,9600,19200,38400,57600,115200").split(","));
    345   int kk = _serialBaudRateComboBox->findText(settings.value("serialBaudRate").toString());
    346   if (kk != -1) {
    347     _serialBaudRateComboBox->setCurrentIndex(kk);
    348   }
    349   _serialFlowControlComboBox = new QComboBox();
    350   _serialFlowControlComboBox->addItems(QString("OFF,XONXOFF,HARDWARE").split(","));
    351   kk = _serialFlowControlComboBox->findText(settings.value("serialFlowControl").toString());
    352   if (kk != -1) {
    353     _serialFlowControlComboBox->setCurrentIndex(kk);
    354   }
    355   _serialDataBitsComboBox = new QComboBox();
    356   _serialDataBitsComboBox->addItems(QString("5,6,7,8").split(","));
    357   kk = _serialDataBitsComboBox->findText(settings.value("serialDataBits").toString());
    358   if (kk != -1) {
    359     _serialDataBitsComboBox->setCurrentIndex(kk);
    360   }
    361   _serialParityComboBox  = new QComboBox();
    362   _serialParityComboBox->addItems(QString("NONE,ODD,EVEN,SPACE").split(","));
    363   kk = _serialParityComboBox->findText(settings.value("serialParity").toString());
    364   if (kk != -1) {
    365     _serialParityComboBox->setCurrentIndex(kk);
    366   }
    367   _serialStopBitsComboBox = new QComboBox();
    368   _serialStopBitsComboBox->addItems(QString("1,2").split(","));
    369   kk = _serialStopBitsComboBox->findText(settings.value("serialStopBits").toString());
    370   if (kk != -1) {
    371     _serialStopBitsComboBox->setCurrentIndex(kk);
    372   }
    373   _serialAutoNMEAComboBox  = new QComboBox();
    374   _serialAutoNMEAComboBox->addItems(QString("no,Auto,Manual GPGGA,Manual GNGGA").split(","));
    375   kk = _serialAutoNMEAComboBox->findText(settings.value("serialAutoNMEA").toString());
    376   if (kk != -1) {
    377     _serialAutoNMEAComboBox->setCurrentIndex(kk);
    378   }
    379   _serialFileNMEALineEdit    = new QLineEdit(settings.value("serialFileNMEA").toString());
    380   _serialHeightNMEALineEdit  = new QLineEdit(settings.value("serialHeightNMEA").toString());
    381 
    382   _serialNMEASamplingSpinBox = new QSpinBox();
    383   _serialNMEASamplingSpinBox->setMinimum(0);
    384   _serialNMEASamplingSpinBox->setMaximum(300);
    385   _serialNMEASamplingSpinBox->setSingleStep(10);
    386   _serialNMEASamplingSpinBox->setValue(settings.value("serialNMEASampling").toInt());
    387   _serialNMEASamplingSpinBox->setSuffix(" sec");
    388 
    389   connect(_serialMountPointLineEdit, SIGNAL(textChanged(const QString &)),
    390           this, SLOT(slotBncTextChanged()));
    391 
    392   connect(_serialAutoNMEAComboBox, SIGNAL(currentIndexChanged(const QString &)),
    393           this, SLOT(slotBncTextChanged()));
    394 
    395   // Outages Options
    396   // ---------------
    397   _adviseObsRateComboBox    = new QComboBox();
    398   _adviseObsRateComboBox->setEditable(false);
    399   _adviseObsRateComboBox->addItems(QString(",0.1 Hz,0.2 Hz,0.5 Hz,1 Hz,5 Hz").split(","));
    400   kk = _adviseObsRateComboBox->findText(settings.value("adviseObsRate").toString());
    401   if (kk != -1) {
    402     _adviseObsRateComboBox->setCurrentIndex(kk);
    403   }
    404   _adviseFailSpinBox = new QSpinBox();
    405   _adviseFailSpinBox->setMinimum(0);
    406   _adviseFailSpinBox->setMaximum(60);
    407   _adviseFailSpinBox->setSingleStep(1);
    408   _adviseFailSpinBox->setSuffix(" min");
    409   _adviseFailSpinBox->setValue(settings.value("adviseFail").toInt());
    410   _adviseRecoSpinBox = new QSpinBox();
    411   _adviseRecoSpinBox->setMinimum(0);
    412   _adviseRecoSpinBox->setMaximum(60);
    413   _adviseRecoSpinBox->setSingleStep(1);
    414   _adviseRecoSpinBox->setSuffix(" min");
    415   _adviseRecoSpinBox->setValue(settings.value("adviseReco").toInt());
    416   _adviseScriptLineEdit    = new QLineEdit(settings.value("adviseScript").toString());
    417 
    418   connect(_adviseObsRateComboBox, SIGNAL(currentIndexChanged(const QString &)),
    419           this, SLOT(slotBncTextChanged()));
    420 
    421   // Miscellaneous Options
    422   // ---------------------
    423   _miscMountLineEdit  = new QLineEdit(settings.value("miscMount").toString());
    424   _miscPortLineEdit  = new QLineEdit(settings.value("miscPort").toString());
    425   _miscIntrComboBox  = new QComboBox();
    426   _miscIntrComboBox->setEditable(false);
    427   _miscIntrComboBox->addItems(QString(",2 sec,10 sec,1 min,5 min,15 min,1 hour,6 hours,1 day").split(","));
    428   int ll = _miscIntrComboBox->findText(settings.value("miscIntr").toString());
    429   if (ll != -1) {
    430     _miscIntrComboBox->setCurrentIndex(ll);
    431   }
    432   _miscScanRTCMCheckBox  = new QCheckBox();
    433   _miscScanRTCMCheckBox->setCheckState(Qt::CheckState(
    434                                     settings.value("miscScanRTCM").toInt()));
    435 
    436   connect(_miscMountLineEdit, SIGNAL(textChanged(const QString &)),
    437           this, SLOT(slotBncTextChanged()));
    438 
    439   // Streams
    440   // -------
    441   _mountPointsTable  = new QTableWidget(0,9);
    442 
    443   _mountPointsTable->horizontalHeader()->resizeSection(1,34*ww);
    444   _mountPointsTable->horizontalHeader()->resizeSection(2,9*ww);
    445   _mountPointsTable->horizontalHeader()->resizeSection(3,9*ww);
    446   _mountPointsTable->horizontalHeader()->resizeSection(4,7*ww);
    447   _mountPointsTable->horizontalHeader()->resizeSection(5,7*ww);
    448   _mountPointsTable->horizontalHeader()->resizeSection(6,5*ww);
    449   _mountPointsTable->horizontalHeader()->resizeSection(7,5*ww);
     322        _outSamplComboBox->setCurrentIndex(nn);
     323    }
     324    _outFileLineEdit = new QLineEdit(settings.value("outFile").toString());
     325    _outUPortLineEdit = new QLineEdit(settings.value("outUPort").toString());
     326    _outLockTimeCheckBox = new QCheckBox();
     327    _outLockTimeCheckBox->setCheckState(Qt::CheckState(settings.value("outLockTime").toInt()));
     328
     329    connect(_outPortLineEdit, SIGNAL(textChanged(const QString&)),
     330        this, SLOT(slotBncTextChanged()));
     331
     332    connect(_outFileLineEdit, SIGNAL(textChanged(const QString&)),
     333        this, SLOT(slotBncTextChanged()));
     334
     335    connect(_outLockTimeCheckBox, SIGNAL(stateChanged(int)),
     336        this, SLOT(slotBncTextChanged()));
     337
     338    // Serial Output Options
     339    // ---------------------
     340    _serialMountPointLineEdit = new QLineEdit(settings.value("serialMountPoint").toString());
     341    _serialPortNameLineEdit = new QLineEdit(settings.value("serialPortName").toString());
     342    _serialBaudRateComboBox = new QComboBox();
     343    _serialBaudRateComboBox->addItems(QString("110,300,600,"
     344        "1200,2400,4800,9600,19200,38400,57600,115200").split(","));
     345    int kk = _serialBaudRateComboBox->findText(settings.value("serialBaudRate").toString());
     346    if (kk != -1) {
     347        _serialBaudRateComboBox->setCurrentIndex(kk);
     348    }
     349    _serialFlowControlComboBox = new QComboBox();
     350    _serialFlowControlComboBox->addItems(QString("OFF,XONXOFF,HARDWARE").split(","));
     351    kk = _serialFlowControlComboBox->findText(settings.value("serialFlowControl").toString());
     352    if (kk != -1) {
     353        _serialFlowControlComboBox->setCurrentIndex(kk);
     354    }
     355    _serialDataBitsComboBox = new QComboBox();
     356    _serialDataBitsComboBox->addItems(QString("5,6,7,8").split(","));
     357    kk = _serialDataBitsComboBox->findText(settings.value("serialDataBits").toString());
     358    if (kk != -1) {
     359        _serialDataBitsComboBox->setCurrentIndex(kk);
     360    }
     361    _serialParityComboBox = new QComboBox();
     362    _serialParityComboBox->addItems(QString("NONE,ODD,EVEN,SPACE").split(","));
     363    kk = _serialParityComboBox->findText(settings.value("serialParity").toString());
     364    if (kk != -1) {
     365        _serialParityComboBox->setCurrentIndex(kk);
     366    }
     367    _serialStopBitsComboBox = new QComboBox();
     368    _serialStopBitsComboBox->addItems(QString("1,2").split(","));
     369    kk = _serialStopBitsComboBox->findText(settings.value("serialStopBits").toString());
     370    if (kk != -1) {
     371        _serialStopBitsComboBox->setCurrentIndex(kk);
     372    }
     373    _serialAutoNMEAComboBox = new QComboBox();
     374    _serialAutoNMEAComboBox->addItems(QString("no,Auto,Manual GPGGA,Manual GNGGA").split(","));
     375    kk = _serialAutoNMEAComboBox->findText(settings.value("serialAutoNMEA").toString());
     376    if (kk != -1) {
     377        _serialAutoNMEAComboBox->setCurrentIndex(kk);
     378    }
     379    _serialFileNMEALineEdit = new QLineEdit(settings.value("serialFileNMEA").toString());
     380    _serialHeightNMEALineEdit = new QLineEdit(settings.value("serialHeightNMEA").toString());
     381
     382    _serialNMEASamplingSpinBox = new QSpinBox();
     383    _serialNMEASamplingSpinBox->setMinimum(0);
     384    _serialNMEASamplingSpinBox->setMaximum(300);
     385    _serialNMEASamplingSpinBox->setSingleStep(10);
     386    _serialNMEASamplingSpinBox->setValue(settings.value("serialNMEASampling").toInt());
     387    _serialNMEASamplingSpinBox->setSuffix(" sec");
     388
     389    connect(_serialMountPointLineEdit, SIGNAL(textChanged(const QString&)),
     390        this, SLOT(slotBncTextChanged()));
     391
     392    connect(_serialAutoNMEAComboBox, SIGNAL(currentIndexChanged(const QString&)),
     393        this, SLOT(slotBncTextChanged()));
     394
     395    // Outages Options
     396    // ---------------
     397    _adviseObsRateComboBox = new QComboBox();
     398    _adviseObsRateComboBox->setEditable(false);
     399    _adviseObsRateComboBox->addItems(QString(",0.1 Hz,0.2 Hz,0.5 Hz,1 Hz,5 Hz").split(","));
     400    kk = _adviseObsRateComboBox->findText(settings.value("adviseObsRate").toString());
     401    if (kk != -1) {
     402        _adviseObsRateComboBox->setCurrentIndex(kk);
     403    }
     404    _adviseFailSpinBox = new QSpinBox();
     405    _adviseFailSpinBox->setMinimum(0);
     406    _adviseFailSpinBox->setMaximum(60);
     407    _adviseFailSpinBox->setSingleStep(1);
     408    _adviseFailSpinBox->setSuffix(" min");
     409    _adviseFailSpinBox->setValue(settings.value("adviseFail").toInt());
     410    _adviseRecoSpinBox = new QSpinBox();
     411    _adviseRecoSpinBox->setMinimum(0);
     412    _adviseRecoSpinBox->setMaximum(60);
     413    _adviseRecoSpinBox->setSingleStep(1);
     414    _adviseRecoSpinBox->setSuffix(" min");
     415    _adviseRecoSpinBox->setValue(settings.value("adviseReco").toInt());
     416    _adviseScriptLineEdit = new QLineEdit(settings.value("adviseScript").toString());
     417
     418    connect(_adviseObsRateComboBox, SIGNAL(currentIndexChanged(const QString&)),
     419        this, SLOT(slotBncTextChanged()));
     420
     421    // Miscellaneous Options
     422    // ---------------------
     423    _miscMountLineEdit = new QLineEdit(settings.value("miscMount").toString());
     424    _miscPortLineEdit = new QLineEdit(settings.value("miscPort").toString());
     425    _miscIntrComboBox = new QComboBox();
     426    _miscIntrComboBox->setEditable(false);
     427    _miscIntrComboBox->addItems(QString(",2 sec,10 sec,1 min,5 min,15 min,1 hour,6 hours,1 day").split(","));
     428    int ll = _miscIntrComboBox->findText(settings.value("miscIntr").toString());
     429    if (ll != -1) {
     430        _miscIntrComboBox->setCurrentIndex(ll);
     431    }
     432    _miscScanRTCMCheckBox = new QCheckBox();
     433    _miscScanRTCMCheckBox->setCheckState(Qt::CheckState(
     434        settings.value("miscScanRTCM").toInt()));
     435
     436    connect(_miscMountLineEdit, SIGNAL(textChanged(const QString&)),
     437        this, SLOT(slotBncTextChanged()));
     438
     439    // Streams
     440    // -------
     441    _mountPointsTable = new QTableWidget(0, 9);
     442
     443    _mountPointsTable->horizontalHeader()->resizeSection(1, 34 * ww);
     444    _mountPointsTable->horizontalHeader()->resizeSection(2, 9 * ww);
     445    _mountPointsTable->horizontalHeader()->resizeSection(3, 9 * ww);
     446    _mountPointsTable->horizontalHeader()->resizeSection(4, 7 * ww);
     447    _mountPointsTable->horizontalHeader()->resizeSection(5, 7 * ww);
     448    _mountPointsTable->horizontalHeader()->resizeSection(6, 5 * ww);
     449    _mountPointsTable->horizontalHeader()->resizeSection(7, 5 * ww);
    450450#if QT_VERSION < 0x050000
    451   _mountPointsTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
     451    _mountPointsTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
    452452#else
    453   _mountPointsTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
     453    _mountPointsTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    454454#endif
    455   _mountPointsTable->horizontalHeader()->setStretchLastSection(true);
    456   _mountPointsTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
    457   _mountPointsTable->setHorizontalHeaderLabels(labels);
    458   _mountPointsTable->setGridStyle(Qt::NoPen);
    459   _mountPointsTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    460   _mountPointsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
    461   _mountPointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    462   _mountPointsTable->hideColumn(0);
    463   _mountPointsTable->hideColumn(3);
    464   connect(_mountPointsTable, SIGNAL(itemSelectionChanged()),
    465           SLOT(slotSelectionChanged()));
    466   populateMountPointsTable();
    467 
    468   _log = new QTextEdit();
    469   _log->setReadOnly(true);
    470   QFont msFont(""); msFont.setStyleHint(QFont::TypeWriter); // default monospace font
    471   _log->setFont(msFont);
    472   _log->document()->setMaximumBlockCount(1000);
    473 
    474   // Combine Corrections
    475   // -------------------
    476   _cmbTable = new QTableWidget(0,4);
    477   _cmbTable->setHorizontalHeaderLabels(QString("Mountpoint, AC Name, Weight Factor, Exclude Satellites").split(","));
    478   _cmbTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
    479   _cmbTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    480   _cmbTable->setMaximumWidth(40*ww);
    481   _cmbTable->horizontalHeader()->resizeSection(0,10*ww);
    482   _cmbTable->horizontalHeader()->resizeSection(1,6*ww);
    483   _cmbTable->horizontalHeader()->resizeSection(2,9*ww);
    484   _cmbTable->horizontalHeader()->resizeSection(3,9*ww);
     455    _mountPointsTable->horizontalHeader()->setStretchLastSection(true);
     456    _mountPointsTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
     457    _mountPointsTable->setHorizontalHeaderLabels(labels);
     458    _mountPointsTable->setGridStyle(Qt::NoPen);
     459    _mountPointsTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     460    _mountPointsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
     461    _mountPointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
     462    _mountPointsTable->hideColumn(0);
     463    _mountPointsTable->hideColumn(3);
     464    connect(_mountPointsTable, SIGNAL(itemSelectionChanged()),
     465        SLOT(slotSelectionChanged()));
     466    populateMountPointsTable();
     467
     468    _log = new QTextEdit();
     469    _log->setReadOnly(true);
     470    QFont msFont(""); msFont.setStyleHint(QFont::TypeWriter); // default monospace font
     471    _log->setFont(msFont);
     472    _log->document()->setMaximumBlockCount(1000);
     473
     474    // Combine Corrections
     475    // -------------------
     476    _cmbTable = new QTableWidget(0, 4);
     477    _cmbTable->setHorizontalHeaderLabels(QString("Mountpoint, AC Name, Weight Factor, Exclude Satellites").split(","));
     478    _cmbTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
     479    _cmbTable->setSelectionBehavior(QAbstractItemView::SelectRows);
     480    _cmbTable->setMaximumWidth(40 * ww);
     481    _cmbTable->horizontalHeader()->resizeSection(0, 10 * ww);
     482    _cmbTable->horizontalHeader()->resizeSection(1, 6 * ww);
     483    _cmbTable->horizontalHeader()->resizeSection(2, 9 * ww);
     484    _cmbTable->horizontalHeader()->resizeSection(3, 9 * ww);
    485485#if QT_VERSION < 0x050000
    486   _cmbTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
     486    _cmbTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
    487487#else
    488   _cmbTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
     488    _cmbTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    489489#endif
    490   _cmbTable->horizontalHeader()->setStretchLastSection(true);
    491   _cmbTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
    492 
    493   _cmbMaxresLineEdit = new QLineEdit(settings.value("cmbMaxres").toString());
    494   _cmbMaxdisplacementLineEdit = new QLineEdit(settings.value("cmbMaxdisplacement").toString());
    495 
    496   _cmbSamplSpinBox = new QSpinBox;
    497   _cmbSamplSpinBox->setMinimum(0);
    498   _cmbSamplSpinBox->setMaximum(60);
    499   _cmbSamplSpinBox->setSingleStep(5);
    500   _cmbSamplSpinBox->setMaximumWidth(9*ww);
    501   _cmbSamplSpinBox->setValue(settings.value("cmbSampl").toInt());
    502   _cmbSamplSpinBox->setSuffix(" sec");
    503 
    504   _cmbLogPath = new QLineEdit(settings.value("cmbLogpath").toString());
    505 
    506   QPushButton* addCmbRowButton = new QPushButton("Add Row");
    507   QPushButton* delCmbRowButton = new QPushButton("Delete");
    508 
    509   connect(_cmbTable, SIGNAL(itemSelectionChanged()), SLOT(slotBncTextChanged()));
    510 
    511   _cmbMethodComboBox = new QComboBox();
    512   _cmbMethodComboBox->setEditable(false);
    513   _cmbMethodComboBox->addItems(QString("Kalman Filter,Single-Epoch").split(","));
    514   int cm = _cmbMethodComboBox->findText(settings.value("cmbMethod").toString());
    515   if (cm != -1) {
    516     _cmbMethodComboBox->setCurrentIndex(cm);
    517   }
    518 
    519   int iRow = _cmbTable->rowCount();
    520   if (iRow > 0) {
    521     enableWidget(true, _cmbMethodComboBox);
    522     enableWidget(true, _cmbMaxresLineEdit);
    523     enableWidget(true, _cmbMaxdisplacementLineEdit);
    524     enableWidget(true, _cmbSamplSpinBox);
    525     enableWidget(true, _cmbLogPath);
    526   }
    527   else {
    528     enableWidget(false, _cmbMethodComboBox);
    529     enableWidget(false, _cmbMaxresLineEdit);
    530     enableWidget(false, _cmbMaxdisplacementLineEdit);
    531     enableWidget(false, _cmbSamplSpinBox);
    532     enableWidget(false, _cmbLogPath);
    533   }
    534   _cmbGpsCheckBox = new QCheckBox();
    535   _cmbGpsCheckBox->setCheckState(Qt::CheckState(settings.value("cmbGps").toInt()));
    536   _cmbGloCheckBox = new QCheckBox();
    537   _cmbGloCheckBox->setCheckState(Qt::CheckState(settings.value("cmbGlo").toInt()));
    538   _cmbGalCheckBox = new QCheckBox();
    539   _cmbGalCheckBox->setCheckState(Qt::CheckState(settings.value("cmbGal").toInt()));
    540   _cmbBdsCheckBox = new QCheckBox();
    541   _cmbBdsCheckBox->setCheckState(Qt::CheckState(settings.value("cmbBds").toInt()));
    542   _cmbQzssCheckBox = new QCheckBox();
    543   _cmbQzssCheckBox->setCheckState(Qt::CheckState(settings.value("cmbQzss").toInt()));
    544   _cmbSbasCheckBox = new QCheckBox();
    545   _cmbSbasCheckBox->setCheckState(Qt::CheckState(settings.value("cmbSbas").toInt()));
    546   _cmbNavicCheckBox = new QCheckBox();
    547   _cmbNavicCheckBox->setCheckState(Qt::CheckState(settings.value("cmbNavic").toInt()));
    548 
    549   connect(_cmbGpsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
    550   connect(_cmbGloCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
    551   connect(_cmbGalCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
    552   connect(_cmbBdsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
    553   connect(_cmbQzssCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
    554   connect(_cmbSbasCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
    555   connect(_cmbNavicCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
    556 
    557   _cmbBsxFile      = new qtFileChooser(0, qtFileChooser::File);
    558   _cmbBsxFile->setFileName(settings.value("cmbBsxFile").toString());
    559 
    560   // Upload Results
    561   // -------------
    562   _uploadTable = new QTableWidget(0,16);
    563   _uploadTable->setHorizontalHeaderLabels(QString("Host, Port, Mount, Ntrip, User, Password, System, Format, CoM, SP3 File, RNX File, BSX File, PID, SID, IOD, bytes").split(","));
    564   _uploadTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
    565   _uploadTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    566   _uploadTable->horizontalHeader()->resizeSection( 0,13*ww);
    567   _uploadTable->horizontalHeader()->resizeSection( 1, 5*ww);
    568   _uploadTable->horizontalHeader()->resizeSection( 2, 6*ww);
    569   _uploadTable->horizontalHeader()->resizeSection( 3, 6*ww);
    570   _uploadTable->horizontalHeader()->resizeSection( 4, 8*ww);
    571   _uploadTable->horizontalHeader()->resizeSection( 5, 8*ww);
    572   _uploadTable->horizontalHeader()->resizeSection( 6,11*ww);
    573   _uploadTable->horizontalHeader()->resizeSection( 7,11*ww);
    574   _uploadTable->horizontalHeader()->resizeSection( 8, 4*ww);
    575   _uploadTable->horizontalHeader()->resizeSection( 9,15*ww);
    576   _uploadTable->horizontalHeader()->resizeSection(10,15*ww);
    577   _uploadTable->horizontalHeader()->resizeSection(11,15*ww);
    578   _uploadTable->horizontalHeader()->resizeSection(12, 4*ww);
    579   _uploadTable->horizontalHeader()->resizeSection(13, 4*ww);
    580   _uploadTable->horizontalHeader()->resizeSection(14, 4*ww);
    581   _uploadTable->horizontalHeader()->resizeSection(15,12*ww);
     490    _cmbTable->horizontalHeader()->setStretchLastSection(true);
     491    _cmbTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
     492
     493    _cmbMaxresLineEdit = new QLineEdit(settings.value("cmbMaxres").toString());
     494    _cmbMaxdisplacementLineEdit = new QLineEdit(settings.value("cmbMaxdisplacement").toString());
     495
     496    _cmbSamplComboBox = new QComboBox();
     497    _cmbSamplComboBox->setEditable(false);
     498    _cmbSamplComboBox->addItems(QString("1 sec,2 sec,5 sec,10 sec,15 sec,30 sec,60 sec").split(","));
     499    int kl = _cmbSamplComboBox->findText(settings.value("cmbSampl").toString());
     500    if (kl != -1) {
     501        _cmbSamplComboBox->setCurrentIndex(kl);
     502    }
     503
     504    _cmbLogPath = new QLineEdit(settings.value("cmbLogpath").toString());
     505
     506    QPushButton* addCmbRowButton = new QPushButton("Add Row");
     507    QPushButton* delCmbRowButton = new QPushButton("Delete");
     508
     509    connect(_cmbTable, SIGNAL(itemSelectionChanged()), SLOT(slotBncTextChanged()));
     510
     511    _cmbMethodComboBox = new QComboBox();
     512    _cmbMethodComboBox->setEditable(false);
     513    _cmbMethodComboBox->addItems(QString("Kalman Filter,Single-Epoch").split(","));
     514    int cm = _cmbMethodComboBox->findText(settings.value("cmbMethod").toString());
     515    if (cm != -1) {
     516        _cmbMethodComboBox->setCurrentIndex(cm);
     517    }
     518
     519    int iRow = _cmbTable->rowCount();
     520    if (iRow > 0) {
     521        enableWidget(true, _cmbMethodComboBox);
     522        enableWidget(true, _cmbMaxresLineEdit);
     523        enableWidget(true, _cmbMaxdisplacementLineEdit);
     524        enableWidget(true, _cmbSamplComboBox);
     525        enableWidget(true, _cmbLogPath);
     526    }
     527    else {
     528        enableWidget(false, _cmbMethodComboBox);
     529        enableWidget(false, _cmbMaxresLineEdit);
     530        enableWidget(false, _cmbMaxdisplacementLineEdit);
     531        enableWidget(false, _cmbSamplComboBox);
     532        enableWidget(false, _cmbLogPath);
     533    }
     534    _cmbGpsCheckBox = new QCheckBox();
     535    _cmbGpsCheckBox->setCheckState(Qt::CheckState(settings.value("cmbGps").toInt()));
     536    _cmbGloCheckBox = new QCheckBox();
     537    _cmbGloCheckBox->setCheckState(Qt::CheckState(settings.value("cmbGlo").toInt()));
     538    _cmbGalCheckBox = new QCheckBox();
     539    _cmbGalCheckBox->setCheckState(Qt::CheckState(settings.value("cmbGal").toInt()));
     540    _cmbBdsCheckBox = new QCheckBox();
     541    _cmbBdsCheckBox->setCheckState(Qt::CheckState(settings.value("cmbBds").toInt()));
     542    _cmbQzssCheckBox = new QCheckBox();
     543    _cmbQzssCheckBox->setCheckState(Qt::CheckState(settings.value("cmbQzss").toInt()));
     544    _cmbSbasCheckBox = new QCheckBox();
     545    _cmbSbasCheckBox->setCheckState(Qt::CheckState(settings.value("cmbSbas").toInt()));
     546    _cmbNavicCheckBox = new QCheckBox();
     547    _cmbNavicCheckBox->setCheckState(Qt::CheckState(settings.value("cmbNavic").toInt()));
     548
     549    connect(_cmbGpsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
     550    connect(_cmbGloCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
     551    connect(_cmbGalCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
     552    connect(_cmbBdsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
     553    connect(_cmbQzssCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
     554    connect(_cmbSbasCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
     555    connect(_cmbNavicCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotBncTextChanged()));
     556
     557    _cmbBsxFile = new qtFileChooser(0, qtFileChooser::File);
     558    _cmbBsxFile->setFileName(settings.value("cmbBsxFile").toString());
     559
     560    // Upload Results
     561    // -------------
     562    _uploadTable = new QTableWidget(0, 16);
     563    _uploadTable->setHorizontalHeaderLabels(QString("Host, Port, Mount, Ntrip, User, Password, System, Format, CoM, SP3 File, RNX File, BSX File, PID, SID, IOD, bytes").split(","));
     564    _uploadTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
     565    _uploadTable->setSelectionBehavior(QAbstractItemView::SelectRows);
     566    _uploadTable->horizontalHeader()->resizeSection(0, 13 * ww);
     567    _uploadTable->horizontalHeader()->resizeSection(1, 5 * ww);
     568    _uploadTable->horizontalHeader()->resizeSection(2, 6 * ww);
     569    _uploadTable->horizontalHeader()->resizeSection(3, 6 * ww);
     570    _uploadTable->horizontalHeader()->resizeSection(4, 8 * ww);
     571    _uploadTable->horizontalHeader()->resizeSection(5, 8 * ww);
     572    _uploadTable->horizontalHeader()->resizeSection(6, 11 * ww);
     573    _uploadTable->horizontalHeader()->resizeSection(7, 11 * ww);
     574    _uploadTable->horizontalHeader()->resizeSection(8, 4 * ww);
     575    _uploadTable->horizontalHeader()->resizeSection(9, 15 * ww);
     576    _uploadTable->horizontalHeader()->resizeSection(10, 15 * ww);
     577    _uploadTable->horizontalHeader()->resizeSection(11, 15 * ww);
     578    _uploadTable->horizontalHeader()->resizeSection(12, 4 * ww);
     579    _uploadTable->horizontalHeader()->resizeSection(13, 4 * ww);
     580    _uploadTable->horizontalHeader()->resizeSection(14, 4 * ww);
     581    _uploadTable->horizontalHeader()->resizeSection(15, 12 * ww);
    582582#if QT_VERSION < 0x050000
    583   _uploadTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
     583    _uploadTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
    584584#else
    585   _uploadTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
     585    _uploadTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    586586#endif
    587   _uploadTable->horizontalHeader()->setStretchLastSection(true);
    588   _uploadTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
    589 
    590   connect(_uploadTable, SIGNAL(itemSelectionChanged()),
    591           SLOT(slotBncTextChanged()));
    592 
    593   QPushButton* addUploadRowButton = new QPushButton("Add Row");
    594   QPushButton* delUploadRowButton = new QPushButton("Del Row");
    595   QPushButton* setUploadTrafoButton = new QPushButton("Custom Trafo");
    596   _uploadIntrComboBox = new QComboBox;
    597   _uploadIntrComboBox->setEditable(false);
    598   _uploadIntrComboBox->addItems(QString("1 day,1 hour, 30 min,15 min,10 min,5 min,2 min,1 min").split(","));
    599   ii = _uploadIntrComboBox->findText(settings.value("uploadIntr").toString());
    600   if (ii != -1) {
    601     _uploadIntrComboBox->setCurrentIndex(ii);
    602   }
    603 
    604   _uploadAntexFile      = new qtFileChooser(0, qtFileChooser::File);
    605   _uploadAntexFile->setFileName(settings.value("uploadAntexFile").toString());
    606 
    607   _uploadSamplRtcmEphCorrSpinBox = new QSpinBox;
    608   _uploadSamplRtcmEphCorrSpinBox->setMinimum(0);
    609   _uploadSamplRtcmEphCorrSpinBox->setMaximum(60);
    610   _uploadSamplRtcmEphCorrSpinBox->setSingleStep(5);
    611   _uploadSamplRtcmEphCorrSpinBox->setMaximumWidth(9*ww);
    612   _uploadSamplRtcmEphCorrSpinBox->setValue(settings.value("uploadSamplRtcmEphCorr").toInt());
    613   _uploadSamplRtcmEphCorrSpinBox->setSuffix(" sec");
    614 
    615   _uploadSamplSp3ComboBox = new QComboBox();
    616   _uploadSamplSp3ComboBox->addItems(QString("0 sec,30 sec,60 sec,300 sec,900 sec").split(","));
    617   int oo = _uploadSamplSp3ComboBox->findText(settings.value("uploadSamplSp3").toString());
     587    _uploadTable->horizontalHeader()->setStretchLastSection(true);
     588    _uploadTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
     589
     590    connect(_uploadTable, SIGNAL(itemSelectionChanged()),
     591        SLOT(slotBncTextChanged()));
     592
     593    QPushButton* addUploadRowButton = new QPushButton("Add Row");
     594    QPushButton* delUploadRowButton = new QPushButton("Del Row");
     595    QPushButton* setUploadTrafoButton = new QPushButton("Custom Trafo");
     596    _uploadIntrComboBox = new QComboBox;
     597    _uploadIntrComboBox->setEditable(false);
     598    _uploadIntrComboBox->addItems(QString("1 day,1 hour, 30 min,15 min,10 min,5 min,2 min,1 min").split(","));
     599    ii = _uploadIntrComboBox->findText(settings.value("uploadIntr").toString());
     600    if (ii != -1) {
     601        _uploadIntrComboBox->setCurrentIndex(ii);
     602    }
     603
     604    _uploadAntexFile = new qtFileChooser(0, qtFileChooser::File);
     605    _uploadAntexFile->setFileName(settings.value("uploadAntexFile").toString());
     606
     607    _uploadSamplRtcmEphCorrComboBox = new QComboBox();
     608    _uploadSamplRtcmEphCorrComboBox->setEditable(false);
     609    _uploadSamplRtcmEphCorrComboBox->addItems(QString("0 sec,1 sec,2 sec,5 sec,10 sec,15 sec,30 sec,60 sec").split(","));
     610    int pp = _uploadSamplRtcmEphCorrComboBox->findText(settings.value("uploadSamplRtcmEphCorr").toString());
     611    if (pp != -1) {
     612        _uploadSamplRtcmEphCorrComboBox->setCurrentIndex(pp);
     613    }
     614
     615    _uploadSamplSp3ComboBox = new QComboBox();
     616    _uploadSamplSp3ComboBox->addItems(QString("0 sec,30 sec,60 sec,300 sec,900 sec").split(","));
     617    int oo = _uploadSamplSp3ComboBox->findText(settings.value("uploadSamplSp3").toString());
    618618    if (oo != -1) {
    619       _uploadSamplSp3ComboBox->setCurrentIndex(oo);
    620     }
    621 
    622   _uploadSamplClkRnxSpinBox = new QSpinBox;
    623   _uploadSamplClkRnxSpinBox->setMinimum(0);
    624   _uploadSamplClkRnxSpinBox->setMaximum(60);
    625   _uploadSamplClkRnxSpinBox->setSingleStep(5);
    626   _uploadSamplClkRnxSpinBox->setMaximumWidth(9*ww);
    627   _uploadSamplClkRnxSpinBox->setValue(settings.value("uploadSamplClkRnx").toInt());
    628   _uploadSamplClkRnxSpinBox->setSuffix(" sec");
    629 
    630   _uploadSamplBiaSnxSpinBox = new QSpinBox;
    631   _uploadSamplBiaSnxSpinBox->setMinimum(0);
    632   _uploadSamplBiaSnxSpinBox->setMaximum(60);
    633   _uploadSamplBiaSnxSpinBox->setSingleStep(5);
    634   _uploadSamplBiaSnxSpinBox->setMaximumWidth(9*ww);
    635   _uploadSamplBiaSnxSpinBox->setValue(settings.value("uploadSamplBiaSnx").toInt());
    636   _uploadSamplBiaSnxSpinBox->setSuffix(" sec");
    637 
    638   int iRowT = _uploadTable->rowCount();
    639   if (iRowT > 0) {
    640     enableWidget(true, _uploadIntrComboBox);
    641     enableWidget(true, _uploadSamplRtcmEphCorrSpinBox);
    642     enableWidget(true, _uploadSamplSp3ComboBox);
    643     enableWidget(true, _uploadSamplClkRnxSpinBox);
    644     enableWidget(true, _uploadSamplBiaSnxSpinBox);
    645     enableWidget(true, _uploadAntexFile);
    646   }
    647   else {
    648     enableWidget(false, _uploadIntrComboBox);
    649     enableWidget(false, _uploadSamplRtcmEphCorrSpinBox);
    650     enableWidget(false, _uploadSamplSp3ComboBox);
    651     enableWidget(false, _uploadSamplClkRnxSpinBox);
    652     enableWidget(true, _uploadSamplBiaSnxSpinBox);
    653     enableWidget(false, _uploadAntexFile);
    654   }
    655 
    656   // Upload RTCM3 Ephemeris
    657   // ----------------------
    658   _uploadEphTable = new QTableWidget(0,6);
    659   _uploadEphTable->setColumnCount(8);
    660   _uploadEphTable->setRowCount(0);
    661   _uploadEphTable->setHorizontalHeaderLabels(QString("Host, Port, Mount,  Ntrip, User, Password, System, bytes").split(","));
    662   _uploadEphTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
    663   _uploadEphTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    664   _uploadEphTable->horizontalHeader()->resizeSection( 0,13*ww);
    665   _uploadEphTable->horizontalHeader()->resizeSection( 1, 5*ww);
    666   _uploadEphTable->horizontalHeader()->resizeSection( 2, 8*ww);
    667   _uploadEphTable->horizontalHeader()->resizeSection( 3, 6*ww);
    668   _uploadEphTable->horizontalHeader()->resizeSection( 4, 8*ww);
    669   _uploadEphTable->horizontalHeader()->resizeSection( 3, 8*ww);
    670   _uploadEphTable->horizontalHeader()->resizeSection( 5,10*ww);
    671   _uploadEphTable->horizontalHeader()->resizeSection( 6,12*ww);
     619        _uploadSamplSp3ComboBox->setCurrentIndex(oo);
     620    }
     621
     622    _uploadSamplClkRnxSpinBox = new QSpinBox;
     623    _uploadSamplClkRnxSpinBox->setMinimum(0);
     624    _uploadSamplClkRnxSpinBox->setMaximum(60);
     625    _uploadSamplClkRnxSpinBox->setSingleStep(5);
     626    _uploadSamplClkRnxSpinBox->setMaximumWidth(9 * ww);
     627    _uploadSamplClkRnxSpinBox->setValue(settings.value("uploadSamplClkRnx").toInt());
     628    _uploadSamplClkRnxSpinBox->setSuffix(" sec");
     629
     630    _uploadSamplBiaSnxSpinBox = new QSpinBox;
     631    _uploadSamplBiaSnxSpinBox->setMinimum(0);
     632    _uploadSamplBiaSnxSpinBox->setMaximum(60);
     633    _uploadSamplBiaSnxSpinBox->setSingleStep(5);
     634    _uploadSamplBiaSnxSpinBox->setMaximumWidth(9 * ww);
     635    _uploadSamplBiaSnxSpinBox->setValue(settings.value("uploadSamplBiaSnx").toInt());
     636    _uploadSamplBiaSnxSpinBox->setSuffix(" sec");
     637
     638    int iRowT = _uploadTable->rowCount();
     639    if (iRowT > 0) {
     640        enableWidget(true, _uploadIntrComboBox);
     641        enableWidget(true, _uploadSamplRtcmEphCorrComboBox);
     642        enableWidget(true, _uploadSamplSp3ComboBox);
     643        enableWidget(true, _uploadSamplClkRnxSpinBox);
     644        enableWidget(true, _uploadSamplBiaSnxSpinBox);
     645        enableWidget(true, _uploadAntexFile);
     646    }
     647    else {
     648        enableWidget(false, _uploadIntrComboBox);
     649        enableWidget(false, _uploadSamplRtcmEphCorrComboBox);
     650        enableWidget(false, _uploadSamplSp3ComboBox);
     651        enableWidget(false, _uploadSamplClkRnxSpinBox);
     652        enableWidget(true, _uploadSamplBiaSnxSpinBox);
     653        enableWidget(false, _uploadAntexFile);
     654    }
     655
     656    // Upload RTCM3 Ephemeris
     657    // ----------------------
     658    _uploadEphTable = new QTableWidget(0, 6);
     659    _uploadEphTable->setColumnCount(8);
     660    _uploadEphTable->setRowCount(0);
     661    _uploadEphTable->setHorizontalHeaderLabels(QString("Host, Port, Mount,  Ntrip, User, Password, System, bytes").split(","));
     662    _uploadEphTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
     663    _uploadEphTable->setSelectionBehavior(QAbstractItemView::SelectRows);
     664    _uploadEphTable->horizontalHeader()->resizeSection(0, 13 * ww);
     665    _uploadEphTable->horizontalHeader()->resizeSection(1, 5 * ww);
     666    _uploadEphTable->horizontalHeader()->resizeSection(2, 8 * ww);
     667    _uploadEphTable->horizontalHeader()->resizeSection(3, 6 * ww);
     668    _uploadEphTable->horizontalHeader()->resizeSection(4, 8 * ww);
     669    _uploadEphTable->horizontalHeader()->resizeSection(3, 8 * ww);
     670    _uploadEphTable->horizontalHeader()->resizeSection(5, 10 * ww);
     671    _uploadEphTable->horizontalHeader()->resizeSection(6, 12 * ww);
    672672#if QT_VERSION < 0x050000
    673   _uploadEphTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
     673    _uploadEphTable->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
    674674#else
    675   _uploadEphTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
     675    _uploadEphTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    676676#endif
    677   _uploadEphTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
    678 
    679   connect(_uploadEphTable, SIGNAL(itemSelectionChanged()),
    680           SLOT(slotBncTextChanged()));
    681 
    682   QPushButton* addUploadEphRowButton = new QPushButton("Add Row");
    683   addUploadEphRowButton->setMaximumWidth(9*ww);
    684   QPushButton* delUploadEphRowButton = new QPushButton("Del Row");
    685   delUploadEphRowButton->setMaximumWidth(9*ww);
    686 
    687   _uploadSamplRtcmEphSpinBox = new QSpinBox;
    688   _uploadSamplRtcmEphSpinBox->setMinimum(0);
    689   _uploadSamplRtcmEphSpinBox->setMaximum(60);
    690   _uploadSamplRtcmEphSpinBox->setSingleStep(5);
    691   _uploadSamplRtcmEphSpinBox->setMaximumWidth(9*ww);
    692   _uploadSamplRtcmEphSpinBox->setValue(settings.value("uploadSamplRtcmEph").toInt());
    693   _uploadSamplRtcmEphSpinBox->setSuffix(" sec");
    694 
    695   iRowT = _uploadEphTable->rowCount();
    696   if (iRowT > 0) {
    697     enableWidget(true, _uploadSamplRtcmEphSpinBox);
    698   }
    699   else {
    700     enableWidget(false, _uploadSamplRtcmEphSpinBox);
    701   }
    702 
    703   // Canvas with Editable Fields
    704   // ---------------------------
    705   _canvas = new QWidget;
    706   setCentralWidget(_canvas);
    707 
    708   _aogroup = new QTabWidget();
    709   _aogroup->setElideMode(Qt::ElideNone);
    710   _aogroup->setUsesScrollButtons(true);
    711   QWidget* pgroup = new QWidget();
    712   QWidget* ggroup = new QWidget();
    713   QWidget* sgroup = new QWidget();
    714   QWidget* egroup = new QWidget();
    715   QWidget* agroup = new QWidget();
    716   QWidget* cgroup = new QWidget();
    717   QWidget* ogroup = new QWidget();
    718   QWidget* rgroup = new QWidget();
    719   QWidget* sergroup = new QWidget();
    720   QWidget* pppGroup1 = new QWidget();
    721   QWidget* pppGroup2 = new QWidget();
    722   QWidget* pppGroup3 = new QWidget();
    723   QWidget* pppGroup4 = new QWidget();
    724   QWidget* reqcgroup = new QWidget();
    725   QWidget* sp3CompGroup = new QWidget();
    726   QWidget* cmbgroup = new QWidget();
    727   QWidget* uploadgroup = new QWidget();
    728   QWidget* uploadEphgroup = new QWidget();
    729   _aogroup->addTab(pgroup,tr("Network"));
    730   _aogroup->addTab(ggroup,tr("General"));
    731   _aogroup->addTab(ogroup,tr("RINEX Observations"));
    732   _aogroup->addTab(egroup,tr("RINEX Ephemeris"));
    733   _aogroup->addTab(reqcgroup,tr("RINEX Editing && QC"));
    734   _aogroup->addTab(sp3CompGroup,tr("SP3 Comparison"));
    735   _aogroup->addTab(cgroup,tr("Broadcast Corrections"));
    736   _aogroup->addTab(sgroup,tr("Feed Engine"));
    737   _aogroup->addTab(sergroup,tr("Serial Output"));
    738   _aogroup->addTab(agroup,tr("Outages"));
    739   _aogroup->addTab(rgroup,tr("Miscellaneous"));
    740   _aogroup->addTab(pppGroup1,tr("PPP (1)"));
    741   _aogroup->addTab(pppGroup2,tr("PPP (2)"));
    742   _aogroup->addTab(pppGroup3,tr("PPP (3)"));
    743   _aogroup->addTab(pppGroup4,tr("PPP (4)"));
    744   _aogroup->addTab(cmbgroup,tr("Combine Corrections"));
    745   _aogroup->addTab(uploadgroup,tr("Upload Corrections"));
    746   _aogroup->addTab(uploadEphgroup,tr("Upload Ephemeris"));
    747 
    748   // Log Tab
    749   // -------
    750   _loggroup = new QTabWidget();
    751   _loggroup->addTab(_log,tr("Log"));
    752   _loggroup->addTab(_bncFigure,tr("Throughput"));
    753   _loggroup->addTab(_bncFigureLate,tr("Latency"));
    754   _loggroup->addTab(_bncFigurePPP,tr("PPP Plot"));
    755 
    756   // Netowork (Proxy and SSL) Tab
    757   // ----------------------------
    758   QGridLayout* pLayout = new QGridLayout;
    759   pLayout->setColumnMinimumWidth(0,13*ww);
    760   _proxyPortLineEdit->setMaximumWidth(9*ww);
    761 
    762   pLayout->addWidget(new QLabel("Settings for proxy in protected networks and for SSL authorization, leave boxes blank if none.<br>"),0, 0, 1, 50);
    763   pLayout->addWidget(new QLabel("Proxy host"),                               1, 0);
    764   pLayout->addWidget(_proxyHostLineEdit,                                     1, 1, 1,10);
    765   pLayout->addWidget(new QLabel("Proxy port"),                               2, 0);
    766   pLayout->addWidget(_proxyPortLineEdit,                                     2, 1);
    767   pLayout->addWidget(new QLabel("Path to SSL certificates"),                 3, 0);
    768   pLayout->addWidget(_sslCaCertPathLineEdit,                                 3, 1, 1,10);
    769   pLayout->addWidget(new QLabel("Default:  " + bncSslConfig::defaultPath()), 3,11, 1,20);
    770   pLayout->addWidget(new QLabel("Path to SSL client certificates"),          4, 0);
    771   pLayout->addWidget(_sslClientCertPathLineEdit,                             4, 1, 1,10);
    772   pLayout->addWidget(new QLabel("Ignore SSL authorization errors"),          5, 0);
    773   pLayout->addWidget(_sslIgnoreErrorsCheckBox,                               5, 1, 1,10);
    774   pLayout->addWidget(new QLabel(""),                                         6, 1);
    775   pLayout->setRowStretch(6, 999);
    776 
    777   pgroup->setLayout(pLayout);
    778 
    779   // General Tab
    780   // -----------
    781   QGridLayout* gLayout = new QGridLayout;
    782   gLayout->setColumnMinimumWidth(0,14*ww);
    783   _onTheFlyComboBox->setMaximumWidth(9*ww);
    784 
    785   gLayout->addWidget(new QLabel("General settings for logfile, file handling, configuration on-the-fly, auto-start, and raw file output.<br>"),0, 0, 1, 50);
    786   gLayout->addWidget(new QLabel("Logfile (full path)"),          1, 0);
    787   gLayout->addWidget(_logFileLineEdit,                           1, 1, 1,20);
    788   gLayout->addWidget(new QLabel("Append files"),                 2, 0);
    789   gLayout->addWidget(_rnxAppendCheckBox,                         2, 1);
    790   gLayout->addWidget(new QLabel("Reread configuration"),         3, 0);
    791   gLayout->addWidget(_onTheFlyComboBox,                          3, 1);
    792   gLayout->addWidget(new QLabel("Auto start"),                   4, 0);
    793   gLayout->addWidget(_autoStartCheckBox,                         4, 1);
    794   gLayout->addWidget(new QLabel("Raw output file (full path)"),  5, 0);
    795   gLayout->addWidget(_rawOutFileLineEdit,                        5, 1, 1,20);
    796   gLayout->addWidget(new QLabel(""),                             6, 1);
    797   gLayout->setRowStretch(7, 999);
    798 
    799   ggroup->setLayout(gLayout);
    800 
    801   // RINEX Observations
    802   // ------------------
    803   QGridLayout* oLayout = new QGridLayout;
    804   oLayout->setColumnMinimumWidth(0,14*ww);
    805   _rnxIntrComboBox->setMaximumWidth(9*ww);
    806   _rnxSamplComboBox->setMaximumWidth(9*ww);
    807   _rnxSkelExtComboBox->setMaximumWidth(9*ww);
    808 
    809   oLayout->addWidget(new QLabel("Saving RINEX observation files.<br>"),0, 0, 1,50);
    810   oLayout->addWidget(new QLabel("Directory"),                      1, 0);
    811   oLayout->addWidget(_rnxPathLineEdit,                             1, 1, 1, 15);
    812   oLayout->addWidget(new QLabel("Interval"),                       2, 0);
    813   oLayout->addWidget(_rnxIntrComboBox,                             2, 1);
    814   oLayout->addWidget(new QLabel("  Sampling"),                     2, 2, Qt::AlignRight);
    815   oLayout->addWidget(_rnxSamplComboBox,                            2, 3, Qt::AlignRight);
    816   oLayout->addWidget(new QLabel("Skeleton extension"),             3, 0);
    817   oLayout->addWidget(_rnxSkelExtComboBox,                          3, 1, Qt::AlignLeft);
    818   oLayout->addWidget(new QLabel("Skeleton mandatory"),             3, 2, Qt::AlignRight);
    819   oLayout->addWidget(_rnxFileCheckBox,                             3, 3);
    820   oLayout->addWidget(new QLabel("Skeleton Directory"),             4, 0);
    821   oLayout->addWidget(_rnxSkelPathLineEdit,                          4, 1, 1, 15);
    822   oLayout->addWidget(new QLabel("Script (full path)"),             5, 0);
    823   oLayout->addWidget(_rnxScrpLineEdit,                             5, 1, 1, 15);
    824   oLayout->addWidget(new QLabel("Version"),                        6, 0);
    825   oLayout->addWidget(_rnxVersComboBox,                             6, 1);
    826   oLayout->addWidget(new QLabel("Signal priority"),                6, 2, Qt::AlignRight);
    827   oLayout->addWidget(_rnxV2Priority,                               6, 3, 1, 13);
    828   oLayout->addWidget(new QLabel(""),                               7, 1);
    829   oLayout->setRowStretch(8, 999);
    830 
    831   ogroup->setLayout(oLayout);
    832 
    833   // RINEX Ephemeris
    834   // ---------------
    835   QGridLayout* eLayout = new QGridLayout;
    836   eLayout->setColumnMinimumWidth(0,14*ww);
    837   _ephIntrComboBox->setMaximumWidth(9*ww);
    838   _ephOutPortLineEdit->setMaximumWidth(9*ww);
    839 
    840   eLayout->addWidget(new QLabel("Saving RINEX navigation files and ephemeris output through IP port.<br>"),0,0,1,70);
    841   eLayout->addWidget(new QLabel("Directory"),                     1, 0);
    842   eLayout->addWidget(_ephPathLineEdit,                            1, 1, 1,30);
    843   eLayout->addWidget(new QLabel("Interval"),                      2, 0);
    844   eLayout->addWidget(_ephIntrComboBox,                            2, 1);
    845   eLayout->addWidget(new QLabel("Port"),                          3, 0);
    846   eLayout->addWidget(_ephOutPortLineEdit,                         3, 1);
    847   eLayout->addWidget(new QLabel("Version"),                       4, 0);
    848   eLayout->addWidget(_ephVersComboBox,                            4, 1);
    849   eLayout->setRowStretch(5, 999);
    850   //eLayout->addWidget(new QLabel("File per Station"),              5, 0);
    851   //eLayout->addWidget(_ephFilePerStation,                          5, 1);
    852   //eLayout->setRowStretch(6, 999);
    853 
    854   egroup->setLayout(eLayout);
    855 
    856 
     677    _uploadEphTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
     678
     679    connect(_uploadEphTable, SIGNAL(itemSelectionChanged()),
     680        SLOT(slotBncTextChanged()));
     681
     682    QPushButton* addUploadEphRowButton = new QPushButton("Add Row");
     683    addUploadEphRowButton->setMaximumWidth(9 * ww);
     684    QPushButton* delUploadEphRowButton = new QPushButton("Del Row");
     685    delUploadEphRowButton->setMaximumWidth(9 * ww);
     686
     687    _uploadSamplRtcmEphSpinBox = new QSpinBox;
     688    _uploadSamplRtcmEphSpinBox->setMinimum(0);
     689    _uploadSamplRtcmEphSpinBox->setMaximum(60);
     690    _uploadSamplRtcmEphSpinBox->setSingleStep(5);
     691    _uploadSamplRtcmEphSpinBox->setMaximumWidth(9 * ww);
     692    _uploadSamplRtcmEphSpinBox->setValue(settings.value("uploadSamplRtcmEph").toInt());
     693    _uploadSamplRtcmEphSpinBox->setSuffix(" sec");
     694
     695    iRowT = _uploadEphTable->rowCount();
     696    if (iRowT > 0) {
     697        enableWidget(true, _uploadSamplRtcmEphSpinBox);
     698    }
     699    else {
     700        enableWidget(false, _uploadSamplRtcmEphSpinBox);
     701    }
     702
     703    // Canvas with Editable Fields
     704    // ---------------------------
     705    _canvas = new QWidget;
     706    setCentralWidget(_canvas);
     707
     708    _aogroup = new QTabWidget();
     709    _aogroup->setElideMode(Qt::ElideNone);
     710    _aogroup->setUsesScrollButtons(true);
     711    QWidget* pgroup = new QWidget();
     712    QWidget* ggroup = new QWidget();
     713    QWidget* sgroup = new QWidget();
     714    QWidget* egroup = new QWidget();
     715    QWidget* agroup = new QWidget();
     716    QWidget* cgroup = new QWidget();
     717    QWidget* ogroup = new QWidget();
     718    QWidget* rgroup = new QWidget();
     719    QWidget* sergroup = new QWidget();
     720    QWidget* pppGroup1 = new QWidget();
     721    QWidget* pppGroup2 = new QWidget();
     722    QWidget* pppGroup3 = new QWidget();
     723    QWidget* pppGroup4 = new QWidget();
     724    QWidget* reqcgroup = new QWidget();
     725    QWidget* sp3CompGroup = new QWidget();
     726    QWidget* cmbgroup = new QWidget();
     727    QWidget* uploadgroup = new QWidget();
     728    QWidget* uploadEphgroup = new QWidget();
     729    _aogroup->addTab(pgroup, tr("Network"));
     730    _aogroup->addTab(ggroup, tr("General"));
     731    _aogroup->addTab(ogroup, tr("RINEX Observations"));
     732    _aogroup->addTab(egroup, tr("RINEX Ephemeris"));
     733    _aogroup->addTab(reqcgroup, tr("RINEX Editing && QC"));
     734    _aogroup->addTab(sp3CompGroup, tr("SP3 Comparison"));
     735    _aogroup->addTab(cgroup, tr("Broadcast Corrections"));
     736    _aogroup->addTab(sgroup, tr("Feed Engine"));
     737    _aogroup->addTab(sergroup, tr("Serial Output"));
     738    _aogroup->addTab(agroup, tr("Outages"));
     739    _aogroup->addTab(rgroup, tr("Miscellaneous"));
     740    _aogroup->addTab(pppGroup1, tr("PPP (1)"));
     741    _aogroup->addTab(pppGroup2, tr("PPP (2)"));
     742    _aogroup->addTab(pppGroup3, tr("PPP (3)"));
     743    _aogroup->addTab(pppGroup4, tr("PPP (4)"));
     744    _aogroup->addTab(cmbgroup, tr("Combine Corrections"));
     745    _aogroup->addTab(uploadgroup, tr("Upload Corrections"));
     746    _aogroup->addTab(uploadEphgroup, tr("Upload Ephemeris"));
     747
     748    // Log Tab
     749    // -------
     750    _loggroup = new QTabWidget();
     751    _loggroup->addTab(_log, tr("Log"));
     752    _loggroup->addTab(_bncFigure, tr("Throughput"));
     753    _loggroup->addTab(_bncFigureLate, tr("Latency"));
     754    _loggroup->addTab(_bncFigurePPP, tr("PPP Plot"));
     755
     756    // Netowork (Proxy and SSL) Tab
     757    // ----------------------------
     758    QGridLayout* pLayout = new QGridLayout;
     759    pLayout->setColumnMinimumWidth(0, 13 * ww);
     760    _proxyPortLineEdit->setMaximumWidth(9 * ww);
     761
     762    pLayout->addWidget(new QLabel("Settings for proxy in protected networks and for SSL authorization, leave boxes blank if none.<br>"), 0, 0, 1, 50);
     763    pLayout->addWidget(new QLabel("Proxy host"), 1, 0);
     764    pLayout->addWidget(_proxyHostLineEdit, 1, 1, 1, 10);
     765    pLayout->addWidget(new QLabel("Proxy port"), 2, 0);
     766    pLayout->addWidget(_proxyPortLineEdit, 2, 1);
     767    pLayout->addWidget(new QLabel("Path to SSL certificates"), 3, 0);
     768    pLayout->addWidget(_sslCaCertPathLineEdit, 3, 1, 1, 10);
     769    pLayout->addWidget(new QLabel("Default:  " + bncSslConfig::defaultPath()), 3, 11, 1, 20);
     770    pLayout->addWidget(new QLabel("Path to SSL client certificates"), 4, 0);
     771    pLayout->addWidget(_sslClientCertPathLineEdit, 4, 1, 1, 10);
     772    pLayout->addWidget(new QLabel("Ignore SSL authorization errors"), 5, 0);
     773    pLayout->addWidget(_sslIgnoreErrorsCheckBox, 5, 1, 1, 10);
     774    pLayout->addWidget(new QLabel(""), 6, 1);
     775    pLayout->setRowStretch(6, 999);
     776
     777    pgroup->setLayout(pLayout);
     778
     779    // General Tab
     780    // -----------
     781    QGridLayout* gLayout = new QGridLayout;
     782    gLayout->setColumnMinimumWidth(0, 14 * ww);
     783    _onTheFlyComboBox->setMaximumWidth(9 * ww);
     784
     785    gLayout->addWidget(new QLabel("General settings for logfile, file handling, configuration on-the-fly, auto-start, and raw file output.<br>"), 0, 0, 1, 50);
     786    gLayout->addWidget(new QLabel("Logfile (full path)"), 1, 0);
     787    gLayout->addWidget(_logFileLineEdit, 1, 1, 1, 20);
     788    gLayout->addWidget(new QLabel("Append files"), 2, 0);
     789    gLayout->addWidget(_rnxAppendCheckBox, 2, 1);
     790    gLayout->addWidget(new QLabel("Reread configuration"), 3, 0);
     791    gLayout->addWidget(_onTheFlyComboBox, 3, 1);
     792    gLayout->addWidget(new QLabel("Auto start"), 4, 0);
     793    gLayout->addWidget(_autoStartCheckBox, 4, 1);
     794    gLayout->addWidget(new QLabel("Raw output file (full path)"), 5, 0);
     795    gLayout->addWidget(_rawOutFileLineEdit, 5, 1, 1, 20);
     796    gLayout->addWidget(new QLabel(""), 6, 1);
     797    gLayout->setRowStretch(7, 999);
     798
     799    ggroup->setLayout(gLayout);
     800
     801    // RINEX Observations
     802    // ------------------
     803    QGridLayout* oLayout = new QGridLayout;
     804    oLayout->setColumnMinimumWidth(0, 14 * ww);
     805    _rnxIntrComboBox->setMaximumWidth(9 * ww);
     806    _rnxSamplComboBox->setMaximumWidth(9 * ww);
     807    _rnxSkelExtComboBox->setMaximumWidth(9 * ww);
     808
     809    oLayout->addWidget(new QLabel("Saving RINEX observation files.<br>"), 0, 0, 1, 50);
     810    oLayout->addWidget(new QLabel("Directory"), 1, 0);
     811    oLayout->addWidget(_rnxPathLineEdit, 1, 1, 1, 15);
     812    oLayout->addWidget(new QLabel("Interval"), 2, 0);
     813    oLayout->addWidget(_rnxIntrComboBox, 2, 1);
     814    oLayout->addWidget(new QLabel("  Sampling"), 2, 2, Qt::AlignRight);
     815    oLayout->addWidget(_rnxSamplComboBox, 2, 3, Qt::AlignRight);
     816    oLayout->addWidget(new QLabel("Skeleton extension"), 3, 0);
     817    oLayout->addWidget(_rnxSkelExtComboBox, 3, 1, Qt::AlignLeft);
     818    oLayout->addWidget(new QLabel("Skeleton mandatory"), 3, 2, Qt::AlignRight);
     819    oLayout->addWidget(_rnxFileCheckBox, 3, 3);
     820    oLayout->addWidget(new QLabel("Skeleton Directory"), 4, 0);
     821    oLayout->addWidget(_rnxSkelPathLineEdit, 4, 1, 1, 15);
     822    oLayout->addWidget(new QLabel("Script (full path)"), 5, 0);
     823    oLayout->addWidget(_rnxScrpLineEdit, 5, 1, 1, 15);
     824    oLayout->addWidget(new QLabel("Version"), 6, 0);
     825    oLayout->addWidget(_rnxVersComboBox, 6, 1);
     826    oLayout->addWidget(new QLabel("Signal priority"), 6, 2, Qt::AlignRight);
     827    oLayout->addWidget(_rnxV2Priority, 6, 3, 1, 13);
     828    oLayout->addWidget(new QLabel(""), 7, 1);
     829    oLayout->setRowStretch(8, 999);
     830
     831    ogroup->setLayout(oLayout);
     832
     833    // RINEX Ephemeris
     834    // ---------------
     835    QGridLayout* eLayout = new QGridLayout;
     836    eLayout->setColumnMinimumWidth(0, 14 * ww);
     837    _ephIntrComboBox->setMaximumWidth(9 * ww);
     838    _ephOutPortLineEdit->setMaximumWidth(9 * ww);
     839
     840    eLayout->addWidget(new QLabel("Saving RINEX navigation files and ephemeris output through IP port.<br>"), 0, 0, 1, 70);
     841    eLayout->addWidget(new QLabel("Directory"), 1, 0);
     842    eLayout->addWidget(_ephPathLineEdit, 1, 1, 1, 30);
     843    eLayout->addWidget(new QLabel("Interval"), 2, 0);
     844    eLayout->addWidget(_ephIntrComboBox, 2, 1);
     845    eLayout->addWidget(new QLabel("Port"), 3, 0);
     846    eLayout->addWidget(_ephOutPortLineEdit, 3, 1);
     847    eLayout->addWidget(new QLabel("Version"), 4, 0);
     848    eLayout->addWidget(_ephVersComboBox, 4, 1);
     849    eLayout->setRowStretch(5, 999);
     850    //eLayout->addWidget(new QLabel("File per Station"),              5, 0);
     851    //eLayout->addWidget(_ephFilePerStation,                          5, 1);
     852    //eLayout->setRowStretch(6, 999);
     853
     854    egroup->setLayout(eLayout);
     855
     856
     857    // Broadcast Corrections
     858    // ---------------------
     859    QGridLayout* cLayout = new QGridLayout;
     860    cLayout->setColumnMinimumWidth(0, 14 * ww);
     861    _corrIntrComboBox->setMaximumWidth(9 * ww);
     862    _corrPortLineEdit->setMaximumWidth(9 * ww);
     863
     864    cLayout->addWidget(new QLabel("Saving Broadcast Ephemeris correction files and correction output through IP port.<br>"), 0, 0, 1, 70);
     865    cLayout->addWidget(new QLabel("Directory, ASCII"), 1, 0);
     866    cLayout->addWidget(_corrPathLineEdit, 1, 1, 1, 30);
     867    cLayout->addWidget(new QLabel("Interval"), 2, 0);
     868    cLayout->addWidget(_corrIntrComboBox, 2, 1);
     869    cLayout->addWidget(new QLabel("Port"), 3, 0);
     870    cLayout->addWidget(_corrPortLineEdit, 3, 1);
     871    cLayout->addWidget(new QLabel(""), 4, 1);
     872    cLayout->setRowStretch(7, 999);
     873    cgroup->setLayout(cLayout);
     874
     875    // Feed Engine
     876    // -----------
     877    QGridLayout* sLayout = new QGridLayout;
     878    sLayout->setColumnMinimumWidth(0, 14 * ww);
     879    _outPortLineEdit->setMaximumWidth(9 * ww);
     880    _outWaitSpinBox->setMaximumWidth(9 * ww);
     881    _outSamplComboBox->setMaximumWidth(9 * ww);
     882    _outUPortLineEdit->setMaximumWidth(9 * ww);
     883
     884    sLayout->addWidget(new QLabel("Output decoded observations in ASCII format to feed a real-time GNSS network engine.<br>"), 0, 0, 1, 50);
     885    sLayout->addWidget(new QLabel("Port"), 1, 0);
     886    sLayout->addWidget(_outPortLineEdit, 1, 1);
     887    sLayout->addWidget(new QLabel("       Wait for full obs epoch"), 1, 2, Qt::AlignRight);
     888    sLayout->addWidget(_outWaitSpinBox, 1, 3, Qt::AlignLeft);
     889    sLayout->addWidget(new QLabel("Sampling"), 2, 0);
     890    sLayout->addWidget(_outSamplComboBox, 2, 1, Qt::AlignLeft);
     891    sLayout->addWidget(new QLabel("File (full path)"), 3, 0);
     892    sLayout->addWidget(_outFileLineEdit, 3, 1, 1, 10);
     893    sLayout->addWidget(new QLabel("Port (unsynchronized)"), 4, 0);
     894    sLayout->addWidget(_outUPortLineEdit, 4, 1);
     895    sLayout->addWidget(new QLabel("Print lock time"), 5, 0);
     896    sLayout->addWidget(_outLockTimeCheckBox, 5, 1);
     897    sLayout->addWidget(new QLabel(""), 6, 1);
     898    sLayout->setRowStretch(7, 999);
     899
     900    sgroup->setLayout(sLayout);
     901
     902    // Serial Output
     903    // -------------
     904    QGridLayout* serLayout = new QGridLayout;
     905    serLayout->setColumnMinimumWidth(0, 12 * ww);
     906    _serialBaudRateComboBox->setMaximumWidth(9 * ww);
     907    _serialFlowControlComboBox->setMaximumWidth(11 * ww);
     908    _serialDataBitsComboBox->setMaximumWidth(5 * ww);
     909    _serialParityComboBox->setMaximumWidth(9 * ww);
     910    _serialStopBitsComboBox->setMaximumWidth(5 * ww);
     911    _serialAutoNMEAComboBox->setMaximumWidth(14 * ww);
     912    _serialHeightNMEALineEdit->setMaximumWidth(8 * ww);
     913    _serialNMEASamplingSpinBox->setMaximumWidth(8 * ww);
     914
     915    serLayout->addWidget(new QLabel("Port settings to feed a serial connected receiver.<br>"), 0, 0, 1, 30);
     916    serLayout->addWidget(new QLabel("Mountpoint"), 1, 0, Qt::AlignLeft);
     917    serLayout->addWidget(_serialMountPointLineEdit, 1, 1, 1, 2);
     918    serLayout->addWidget(new QLabel("Port name"), 2, 0, Qt::AlignLeft);
     919    serLayout->addWidget(_serialPortNameLineEdit, 2, 1, 1, 2);
     920    serLayout->addWidget(new QLabel("Baud rate"), 3, 0, Qt::AlignLeft);
     921    serLayout->addWidget(_serialBaudRateComboBox, 3, 1);
     922    serLayout->addWidget(new QLabel("Flow control"), 3, 2, Qt::AlignRight);
     923    serLayout->addWidget(_serialFlowControlComboBox, 3, 3);
     924    serLayout->addWidget(new QLabel("Data bits"), 4, 0, Qt::AlignLeft);
     925    serLayout->addWidget(_serialDataBitsComboBox, 4, 1);
     926    serLayout->addWidget(new QLabel("Parity"), 4, 2, Qt::AlignRight);
     927    serLayout->addWidget(_serialParityComboBox, 4, 3);
     928    serLayout->addWidget(new QLabel("   Stop bits"), 4, 4, Qt::AlignRight);
     929    serLayout->addWidget(_serialStopBitsComboBox, 4, 5);
     930    serLayout->addWidget(new QLabel("NMEA"), 5, 0);
     931    serLayout->addWidget(_serialAutoNMEAComboBox, 5, 1);
     932    serLayout->addWidget(new QLabel("    File (full path)"), 5, 2, Qt::AlignRight);
     933    serLayout->addWidget(_serialFileNMEALineEdit, 5, 3, 1, 10);
     934    serLayout->addWidget(new QLabel("Height"), 5, 14, Qt::AlignRight);
     935    serLayout->addWidget(_serialHeightNMEALineEdit, 5, 15, 1, 11);
     936    serLayout->addWidget(new QLabel("Sampling"), 5, 25, Qt::AlignRight);
     937    serLayout->addWidget(_serialNMEASamplingSpinBox, 5, 26, 1, 12);
     938    serLayout->addWidget(new QLabel(""), 6, 1);
     939    serLayout->setRowStretch(7, 999);
     940
     941    sergroup->setLayout(serLayout);
     942
     943    // Outages
     944    // -------
     945    QGridLayout* aLayout = new QGridLayout;
     946    aLayout->setColumnMinimumWidth(0, 14 * ww);
     947    _adviseObsRateComboBox->setMaximumWidth(9 * ww);
     948    _adviseFailSpinBox->setMaximumWidth(9 * ww);
     949    _adviseRecoSpinBox->setMaximumWidth(9 * ww);
     950
     951    aLayout->addWidget(new QLabel("Failure and recovery reports, advisory notes.<br>"), 0, 0, 1, 50, Qt::AlignLeft);
     952    aLayout->addWidget(new QLabel("Observation rate"), 1, 0);
     953    aLayout->addWidget(_adviseObsRateComboBox, 1, 1);
     954    aLayout->addWidget(new QLabel("Failure threshold"), 2, 0);
     955    aLayout->addWidget(_adviseFailSpinBox, 2, 1);
     956    aLayout->addWidget(new QLabel("Recovery threshold"), 3, 0);
     957    aLayout->addWidget(_adviseRecoSpinBox, 3, 1);
     958    aLayout->addWidget(new QLabel("Script (full path)"), 4, 0);
     959    aLayout->addWidget(_adviseScriptLineEdit, 4, 1, 1, 20);
     960    aLayout->addWidget(new QLabel(""), 5, 1);
     961    aLayout->setRowStretch(6, 999);
     962
     963    agroup->setLayout(aLayout);
     964
     965    // Miscellaneous
     966    // -------------
     967    QGridLayout* rLayout = new QGridLayout;
     968    rLayout->setColumnMinimumWidth(0, 14 * ww);
     969    _miscIntrComboBox->setMaximumWidth(9 * ww);
     970    _miscPortLineEdit->setMaximumWidth(9 * ww);
     971
     972    rLayout->addWidget(new QLabel("Log latencies or scan RTCM streams for message types and antenna information or output raw data through TCP/IP port.<br>"), 0, 0, 1, 50);
     973    rLayout->addWidget(new QLabel("Mountpoint"), 1, 0);
     974    rLayout->addWidget(_miscMountLineEdit, 1, 1, 1, 7);
     975    rLayout->addWidget(new QLabel("Log latency"), 2, 0);
     976    rLayout->addWidget(_miscIntrComboBox, 2, 1);
     977    rLayout->addWidget(new QLabel("Scan RTCM"), 3, 0);
     978    rLayout->addWidget(_miscScanRTCMCheckBox, 3, 1);
     979    rLayout->addWidget(new QLabel("Port"), 4, 0);
     980    rLayout->addWidget(_miscPortLineEdit, 4, 1);
     981    rLayout->addWidget(new QLabel(""), 5, 1);
     982    rLayout->setRowStretch(6, 999);
     983
     984    rgroup->setLayout(rLayout);
     985
     986    // PPP
     987    // ---
     988    _pppWidgets._dataSource->setMaximumWidth(15 * ww);
     989    _pppWidgets._corrMount->setMaximumWidth(15 * ww);
     990    _pppWidgets._nmeaPath->setMaximumWidth(35 * ww);
     991    _pppWidgets._logPath->setMaximumWidth(35 * ww);
     992    _pppWidgets._snxtroPath->setMaximumWidth(35 * ww);
     993    _pppWidgets._snxtroIntr->setMaximumWidth(7 * ww);
     994    _pppWidgets._snxtroAc->setMaximumWidth(7 * ww);
     995    _pppWidgets._snxtroSolId->setMaximumWidth(7 * ww);
     996    _pppWidgets._snxtroSolType->setMaximumWidth(7 * ww);
     997    _pppWidgets._snxtroCampId->setMaximumWidth(7 * ww);
     998    _pppWidgets._ionoMount->setMaximumWidth(15 * ww);
     999
     1000
     1001    QGridLayout* pppLayout1 = new QGridLayout();
     1002    int ir = 0;
     1003    pppLayout1->addWidget(new QLabel("Precise Point Positioning - Input and Output.<br>"), ir, 0, 1, 7, Qt::AlignLeft);
     1004    ++ir;
     1005    pppLayout1->addWidget(new QLabel("Data source"), ir, 0);
     1006    pppLayout1->addWidget(_pppWidgets._dataSource, ir, 1);
     1007    pppLayout1->addWidget(new QLabel("   Logfile directory"), ir, 4);
     1008    pppLayout1->addWidget(_pppWidgets._logPath, ir, 5, 1, 3);
     1009    ++ir;
     1010    pppLayout1->addWidget(new QLabel("Corrections stream"), ir, 0);
     1011    pppLayout1->addWidget(_pppWidgets._corrMount, ir, 1);
     1012    pppLayout1->addWidget(new QLabel("Corrections file"), ir, 2);
     1013    pppLayout1->addWidget(_pppWidgets._corrFile, ir, 3);
     1014    pppLayout1->addWidget(new QLabel("   NMEA directory"), ir, 4);
     1015    pppLayout1->addWidget(_pppWidgets._nmeaPath, ir, 5, 1, 3);
     1016    ++ir;
     1017#ifdef USE_PPP
     1018    pppLayout1->addWidget(new QLabel("Ionosphere stream"), ir, 0);
     1019    pppLayout1->addWidget(_pppWidgets._ionoMount, ir, 1);
     1020    pppLayout1->addWidget(new QLabel("Ionosphere file"), ir, 2);
     1021    pppLayout1->addWidget(_pppWidgets._ionoFile, ir, 3);
     1022#endif
     1023    pppLayout1->addWidget(new QLabel("   SNX TRO directory"), ir, 4);
     1024    pppLayout1->addWidget(_pppWidgets._snxtroPath, ir, 5, 1, 3);
     1025    ++ir;
     1026    pppLayout1->addWidget(new QLabel("RINEX Obs file"), ir, 0);
     1027    pppLayout1->addWidget(_pppWidgets._rinexObs, ir, 1);
     1028    pppLayout1->addWidget(new QLabel("RINEX Nav file"), ir, 2);
     1029    pppLayout1->addWidget(_pppWidgets._rinexNav, ir, 3);
     1030    pppLayout1->addWidget(new QLabel("   SNX TRO interval"), ir, 4);
     1031    pppLayout1->addWidget(_pppWidgets._snxtroIntr, ir, 5);
     1032    pppLayout1->addWidget(new QLabel("   SNX TRO sampling"), ir, 6);
     1033    pppLayout1->addWidget(_pppWidgets._snxtroSampl, ir, 7, Qt::AlignRight);
     1034    ++ir;
     1035    pppLayout1->addWidget(new QLabel("ANTEX file"), ir, 0);
     1036    pppLayout1->addWidget(_pppWidgets._antexFile, ir, 1);
     1037    pppLayout1->addWidget(new QLabel("Coordinates file"), ir, 2);
     1038    pppLayout1->addWidget(_pppWidgets._crdFile, ir, 3);
     1039    pppLayout1->addWidget(new QLabel("   SNX TRO AC"), ir, 4);
     1040    pppLayout1->addWidget(_pppWidgets._snxtroAc, ir, 5);
     1041    pppLayout1->addWidget(new QLabel("   SNX TRO solution ID"), ir, 6);
     1042    pppLayout1->addWidget(_pppWidgets._snxtroSolId, ir, 7, Qt::AlignRight);
     1043    ++ir;
     1044#ifdef USE_PPP
     1045    pppLayout1->addWidget(new QLabel("BLQ file"), ir, 0);
     1046    pppLayout1->addWidget(_pppWidgets._blqFile, ir, 1);
     1047    pppLayout1->addWidget(new QLabel("   SNX TRO campaign ID"), ir, 4);
     1048    pppLayout1->addWidget(_pppWidgets._snxtroCampId, ir, 5);
     1049    pppLayout1->addWidget(new QLabel("   SNX TRO solution type"), ir, 6);
     1050    pppLayout1->addWidget(_pppWidgets._snxtroSolType, ir, 7, Qt::AlignRight);
     1051#endif
     1052    pppLayout1->setRowStretch(ir + 1, 999);
     1053    pppGroup1->setLayout(pppLayout1);
     1054
     1055    QGridLayout* pppLayout2 = new QGridLayout();
     1056    ir = 0;
     1057    pppLayout2->addWidget(new QLabel("Precise Point Positioning - Options.<br>"), ir, 0, 1, 2, Qt::AlignLeft);
     1058    ++ir;
     1059    pppLayout2->addWidget(new QLabel("GPS LCs"), ir, 0, Qt::AlignLeft);
     1060    pppLayout2->addWidget(_pppWidgets._lcGPS, ir, 1);
     1061    pppLayout2->addItem(new QSpacerItem(8 * ww, 0), ir, 2);
     1062    pppLayout2->addWidget(new QLabel("Sigma C1"), ir, 3, Qt::AlignLeft);
     1063    pppLayout2->addWidget(_pppWidgets._sigmaC1, ir, 4); _pppWidgets._sigmaC1->setMaximumWidth(8 * ww);
     1064    pppLayout2->addItem(new QSpacerItem(8 * ww, 0), ir, 5);
     1065    pppLayout2->addWidget(new QLabel("Sigma L1"), ir, 6, Qt::AlignLeft);
     1066    pppLayout2->addWidget(_pppWidgets._sigmaL1, ir, 7); _pppWidgets._sigmaL1->setMaximumWidth(8 * ww);
     1067    ++ir;
     1068    pppLayout2->addWidget(new QLabel("GLONASS LCs"), ir, 0, Qt::AlignLeft);
     1069    pppLayout2->addWidget(_pppWidgets._lcGLONASS, ir, 1);
     1070    pppLayout2->addWidget(new QLabel("Max Res C1"), ir, 3, Qt::AlignLeft);
     1071    pppLayout2->addWidget(_pppWidgets._maxResC1, ir, 4); _pppWidgets._maxResC1->setMaximumWidth(8 * ww);
     1072    pppLayout2->addWidget(new QLabel("Max Res L1"), ir, 6, Qt::AlignLeft);
     1073    pppLayout2->addWidget(_pppWidgets._maxResL1, ir, 7); _pppWidgets._maxResL1->setMaximumWidth(8 * ww);
     1074    ++ir;
     1075    pppLayout2->addWidget(new QLabel("Galileo LCs"), ir, 0, Qt::AlignLeft);
     1076    pppLayout2->addWidget(_pppWidgets._lcGalileo, ir, 1);
     1077    pppLayout2->addWidget(new QLabel("Ele Wgt Code"), ir, 3, Qt::AlignLeft);
     1078    pppLayout2->addWidget(_pppWidgets._eleWgtCode, ir, 4);
     1079    pppLayout2->addWidget(new QLabel("Ele Wgt Phase"), ir, 6, Qt::AlignLeft);
     1080    pppLayout2->addWidget(_pppWidgets._eleWgtPhase, ir, 7);
     1081    ++ir;
     1082    pppLayout2->addWidget(new QLabel("BDS LCs"), ir, 0, Qt::AlignLeft);
     1083    pppLayout2->addWidget(_pppWidgets._lcBDS, ir, 1);
     1084    pppLayout2->addWidget(new QLabel("Min # of Obs"), ir, 3, Qt::AlignLeft);
     1085    pppLayout2->addWidget(_pppWidgets._minObs, ir, 4);
     1086    pppLayout2->addWidget(new QLabel("Min Elevation"), ir, 6, Qt::AlignLeft);
     1087    pppLayout2->addWidget(_pppWidgets._minEle, ir, 7); _pppWidgets._minEle->setMaximumWidth(8 * ww);
     1088    ++ir;
     1089#ifdef USE_PPP
     1090    pppLayout2->addWidget(new QLabel("Constraints"), ir, 0, Qt::AlignLeft);
     1091    pppLayout2->addWidget(_pppWidgets._constraints, ir, 1);
     1092    pppLayout2->addWidget(new QLabel("Sigma GIM"), ir, 3, Qt::AlignLeft);
     1093    pppLayout2->addWidget(_pppWidgets._sigmaGIM, ir, 4); _pppWidgets._sigmaGIM->setMaximumWidth(8 * ww);
     1094#endif
     1095    pppLayout2->addItem(new QSpacerItem(8 * ww, 0), ir, 5);
     1096    pppLayout2->addWidget(new QLabel("Wait for clock corr."), ir, 6, Qt::AlignLeft);
     1097    pppLayout2->addWidget(_pppWidgets._corrWaitTime, ir, 7);
     1098    ++ir;
     1099    pppLayout2->addItem(new QSpacerItem(8 * ww, 0), ir, 2);
     1100#ifdef USE_PPP
     1101    pppLayout2->addWidget(new QLabel("Max Res GIM"), ir, 3, Qt::AlignLeft);
     1102    pppLayout2->addWidget(_pppWidgets._maxResGIM, ir, 4); _pppWidgets._maxResGIM->setMaximumWidth(8 * ww);
     1103#endif
     1104    pppLayout2->addWidget(new QLabel("Seeding (sec)"), ir, 6, Qt::AlignLeft);
     1105    pppLayout2->addWidget(_pppWidgets._seedingTime, ir, 7); _pppWidgets._seedingTime->setMaximumWidth(8 * ww);
     1106    ++ir;
     1107    pppLayout2->addWidget(new QLabel(""), ir, 8);
     1108    pppLayout2->setColumnStretch(8, 999);
     1109    ++ir;
     1110    pppLayout2->addWidget(new QLabel(""), ir, 1);
     1111    pppLayout2->setRowStretch(ir, 999);
     1112
     1113    pppGroup2->setLayout(pppLayout2);
     1114
     1115    QVBoxLayout* pppLayout3 = new QVBoxLayout();
     1116    pppLayout3->addWidget(new QLabel("Precise Point Positioning - Processed Stations.<br>"));
     1117    pppLayout3->addWidget(_pppWidgets._staTable, 99);
     1118    QHBoxLayout* pppLayout3sub = new QHBoxLayout();
     1119    pppLayout3sub->addWidget(_pppWidgets._addStaButton);
     1120    pppLayout3sub->addWidget(_pppWidgets._delStaButton);
     1121    pppLayout3sub->addStretch(99);
     1122
     1123    pppLayout3->addLayout(pppLayout3sub);
     1124
     1125    pppGroup3->setLayout(pppLayout3);
     1126
     1127    // ------------------------
     1128    connect(_pppWidgets._mapWinButton, SIGNAL(clicked()), SLOT(slotMapPPP()));
     1129    _pppWidgets._mapSpeedSlider->setMinimumWidth(33 * ww);
     1130    _pppWidgets._audioResponse->setMaximumWidth(8 * ww);
     1131
     1132    QGridLayout* pppLayout4 = new QGridLayout();
     1133    ir = 0;
     1134    pppLayout4->addWidget(new QLabel("Precise Point Positioning - Plots.<br>"), ir, 0, 1, 50, Qt::AlignLeft);
     1135    ++ir;
     1136    pppLayout4->addWidget(new QLabel("PPP Plot"), ir, 0, Qt::AlignLeft);
     1137    pppLayout4->addWidget(_pppWidgets._plotCoordinates, ir, 1, Qt::AlignLeft);
     1138    pppLayout4->addWidget(new QLabel("Mountpoint"), ir, 2, 1, 10, Qt::AlignLeft);
     1139    pppLayout4->addWidget(_pppWidgets._audioResponse, ir, 4, Qt::AlignLeft);
     1140    pppLayout4->addWidget(new QLabel("Audio response"), ir, 5, Qt::AlignRight);
     1141    ++ir;
     1142    pppLayout4->addWidget(new QLabel("Track map"), ir, 0, Qt::AlignLeft);
     1143    pppLayout4->addWidget(_pppWidgets._mapWinButton, ir, 1, Qt::AlignLeft);
     1144    ++ir;
     1145    pppLayout4->addWidget(new QLabel("Dot-properties"), ir, 0, Qt::AlignLeft);
     1146    pppLayout4->addWidget(_pppWidgets._mapWinDotSize, ir, 1, Qt::AlignLeft);
     1147    pppLayout4->addWidget(new QLabel("Size    "), ir, 2, Qt::AlignLeft);
     1148    pppLayout4->addWidget(_pppWidgets._mapWinDotColor, ir, 3, Qt::AlignLeft);
     1149    pppLayout4->addWidget(new QLabel("Color"), ir, 4, Qt::AlignLeft);
     1150    ++ir;
     1151    pppLayout4->addWidget(new QLabel("Post-processing speed"), ir, 0, Qt::AlignLeft);
     1152    pppLayout4->addWidget(_pppWidgets._mapSpeedSlider, ir, 1, 1, 20, Qt::AlignLeft);
     1153    ++ir;
     1154    pppLayout4->addWidget(new QLabel(""), ir, 1);
     1155    pppLayout4->setRowStretch(ir, 999);
     1156
     1157    pppGroup4->setLayout(pppLayout4);
     1158
     1159    // Reqc Processing
     1160    // ---------------
     1161    _reqcActionComboBox = new QComboBox();
     1162    _reqcActionComboBox->setEditable(false);
     1163    _reqcActionComboBox->addItems(QString(",Edit/Concatenate,Analyze").split(","));
     1164    int ip = _reqcActionComboBox->findText(settings.value("reqcAction").toString());
     1165    if (ip != -1) {
     1166        _reqcActionComboBox->setCurrentIndex(ip);
     1167    }
     1168    connect(_reqcActionComboBox, SIGNAL(currentIndexChanged(const QString&)),
     1169        this, SLOT(slotBncTextChanged()));
     1170
     1171    QGridLayout* reqcLayout = new QGridLayout;
     1172    _reqcActionComboBox->setMinimumWidth(15 * ww);
     1173    _reqcActionComboBox->setMaximumWidth(20 * ww);
     1174
     1175    _reqcObsFileChooser = new qtFileChooser(0, qtFileChooser::Files);
     1176    _reqcObsFileChooser->setFileName(settings.value("reqcObsFile").toString());
     1177
     1178    _reqcNavFileChooser = new qtFileChooser(0, qtFileChooser::Files);
     1179    _reqcNavFileChooser->setFileName(settings.value("reqcNavFile").toString());
     1180    _reqcOutObsLineEdit = new QLineEdit(settings.value("reqcOutObsFile").toString());
     1181    _reqcOutNavLineEdit = new QLineEdit(settings.value("reqcOutNavFile").toString());
     1182    _reqcOutLogLineEdit = new QLineEdit(settings.value("reqcOutLogFile").toString());
     1183    _reqcPlotDirLineEdit = new QLineEdit(settings.value("reqcPlotDir").toString());
     1184    _reqcSkyPlotSignals = new QLineEdit(settings.value("reqcSkyPlotSignals").toString());
     1185
     1186    connect(_reqcSkyPlotSignals, SIGNAL(textChanged(const QString&)),
     1187        this, SLOT(slotBncTextChanged()));
     1188
     1189    _reqcLogSummaryOnly = new QCheckBox();
     1190    _reqcLogSummaryOnly->setCheckState(Qt::CheckState(settings.value("reqcLogSummaryOnly").toInt()));
     1191
     1192    ir = 0;
     1193    reqcLayout->addWidget(new QLabel("RINEX file editing, concatenation and quality check.<br>"), ir, 0, 1, 8);
     1194    ++ir;
     1195    reqcLayout->addWidget(new QLabel("Action"), ir, 0);
     1196    reqcLayout->addWidget(_reqcActionComboBox, ir, 1);
     1197    _reqcEditOptionButton = new QPushButton("Set Edit Options");
     1198    _reqcEditOptionButton->setMinimumWidth(15 * ww);
     1199    _reqcEditOptionButton->setMaximumWidth(20 * ww);
     1200
     1201    reqcLayout->addWidget(_reqcEditOptionButton, ir, 3);
     1202    ++ir;
     1203    reqcLayout->addWidget(new QLabel("Input files (full path)"), ir, 0);
     1204    reqcLayout->addWidget(_reqcObsFileChooser, ir, 1);
     1205    _reqcObsFileChooser->setMaximumWidth(40 * ww);
     1206    reqcLayout->addWidget(new QLabel("  Obs"), ir, 2);
     1207    reqcLayout->addWidget(_reqcNavFileChooser, ir, 3);
     1208    _reqcNavFileChooser->setMaximumWidth(40 * ww);
     1209    reqcLayout->addWidget(new QLabel("  Nav"), ir, 4);
     1210    ++ir;
     1211    reqcLayout->addWidget(new QLabel("Output file (full path)"), ir, 0);
     1212    reqcLayout->addWidget(_reqcOutObsLineEdit, ir, 1);
     1213    _reqcOutObsLineEdit->setMaximumWidth(40 * ww);
     1214    reqcLayout->addWidget(new QLabel("  Obs"), ir, 2);
     1215    reqcLayout->addWidget(_reqcOutNavLineEdit, ir, 3);
     1216    _reqcOutNavLineEdit->setMaximumWidth(40 * ww);
     1217    reqcLayout->addWidget(new QLabel("  Nav"), ir, 4);
     1218    ++ir;
     1219    reqcLayout->addWidget(new QLabel("Logfile"), ir, 0);
     1220    reqcLayout->addWidget(_reqcOutLogLineEdit, ir, 1);
     1221    _reqcOutLogLineEdit->setMaximumWidth(40 * ww);
     1222    reqcLayout->addWidget(new QLabel("  Summary only"), ir, 2);
     1223    reqcLayout->addWidget(_reqcLogSummaryOnly, ir, 3);
     1224    ++ir;
     1225    reqcLayout->addWidget(new QLabel("Plots for signals"), ir, 0);
     1226    reqcLayout->addWidget(_reqcSkyPlotSignals, ir, 1);
     1227    _reqcSkyPlotSignals->setMaximumWidth(40 * ww);
     1228    ++ir;
     1229    reqcLayout->addWidget(new QLabel("Directory for plots"), ir, 0);
     1230    reqcLayout->addWidget(_reqcPlotDirLineEdit, ir, 1);
     1231    _reqcPlotDirLineEdit->setMaximumWidth(40 * ww);
     1232    ++ir;
     1233    reqcLayout->setRowStretch(ir, 999);
     1234
     1235    reqcLayout->setColumnMinimumWidth(2, 8 * ww);
     1236    reqcLayout->setColumnMinimumWidth(4, 8 * ww);
     1237
     1238    reqcgroup->setLayout(reqcLayout);
     1239
     1240    connect(_reqcEditOptionButton, SIGNAL(clicked()),
     1241        this, SLOT(slotReqcEditOption()));
     1242
     1243    QGridLayout* sp3CompLayout = new QGridLayout;
     1244
     1245    _sp3CompFileChooser = new qtFileChooser(0, qtFileChooser::Files);
     1246    _sp3CompFileChooser->setFileName(settings.value("sp3CompFile").toString());
     1247    _sp3CompFileChooser->setMinimumWidth(15 * ww);
     1248    _sp3CompFileChooser->setMaximumWidth(40 * ww);
     1249
     1250    _sp3CompExclude = new QLineEdit(settings.value("sp3CompExclude").toString());
     1251    _sp3CompExclude->setMinimumWidth(18 * ww);
     1252    _sp3CompExclude->setMaximumWidth(18 * ww);
     1253
     1254    _sp3CompLogLineEdit = new QLineEdit(settings.value("sp3CompOutLogFile").toString());
     1255    _sp3CompLogLineEdit->setMinimumWidth(18 * ww);
     1256    _sp3CompLogLineEdit->setMaximumWidth(18 * ww);
     1257
     1258    _sp3CompSummaryOnly = new QCheckBox();
     1259    _sp3CompSummaryOnly->setCheckState(Qt::CheckState(settings.value("sp3CompSummaryOnly").toInt()));
     1260
     1261    ir = 0;
     1262    sp3CompLayout->addWidget(new QLabel("Orbit and clock comparison.<br>"), ir, 0, 1, 40);
     1263    ++ir;
     1264    sp3CompLayout->addWidget(new QLabel("Input SP3 files (full path)"), ir, 0, Qt::AlignLeft);
     1265    sp3CompLayout->addWidget(_sp3CompFileChooser, ir, 1, 1, 20);
     1266    ++ir;
     1267    sp3CompLayout->addWidget(new QLabel("Exclude satellites"), ir, 0, Qt::AlignLeft);
     1268    sp3CompLayout->addWidget(_sp3CompExclude, ir, 1, Qt::AlignRight);
     1269    ++ir;
     1270    sp3CompLayout->addWidget(new QLabel("Logfile"), ir, 0, Qt::AlignLeft);
     1271    sp3CompLayout->addWidget(_sp3CompLogLineEdit, ir, 1, Qt::AlignRight);
     1272    ++ir;
     1273    sp3CompLayout->addWidget(new QLabel("Summary only"), ir, 0);
     1274    sp3CompLayout->addWidget(_sp3CompSummaryOnly, ir, 1);
     1275    ++ir;
     1276    sp3CompLayout->addWidget(new QLabel(""), ir, 1);
     1277    ++ir;
     1278    sp3CompLayout->setRowStretch(ir, 999);
     1279
     1280    sp3CompLayout->setColumnMinimumWidth(2, 8 * ww);
     1281    sp3CompLayout->setColumnMinimumWidth(4, 8 * ww);
     1282
     1283    sp3CompGroup->setLayout(sp3CompLayout);
     1284
     1285    connect(_sp3CompFileChooser, SIGNAL(fileNameChanged(const QString&)),
     1286        this, SLOT(slotBncTextChanged()));
     1287
     1288    // Combine Corrections
     1289    // -------------------
     1290    QGridLayout* cmbLayout = new QGridLayout;
     1291
     1292    populateCmbTable();
     1293    cmbLayout->addWidget(_cmbTable, 0, 0, 8, 10);
     1294    cmbLayout->addWidget(new QLabel(" Combine Broadcast Correction streams"), 0, 10, 1, 10);
     1295    cmbLayout->addWidget(addCmbRowButton, 1, 10);
     1296    cmbLayout->addWidget(delCmbRowButton, 1, 11);
     1297    cmbLayout->addWidget(new QLabel("Method"), 2, 10, Qt::AlignLeft);
     1298    cmbLayout->addWidget(_cmbMethodComboBox, 2, 11);
     1299    cmbLayout->addWidget(new QLabel("BSX File"), 3, 10, Qt::AlignLeft);
     1300    cmbLayout->addWidget(_cmbBsxFile, 3, 11, Qt::AlignRight);
     1301    cmbLayout->addWidget(new QLabel("Max Clk Residual"), 4, 10, Qt::AlignLeft);
     1302    cmbLayout->addWidget(_cmbMaxresLineEdit, 4, 11, Qt::AlignRight);
     1303    cmbLayout->addWidget(new QLabel("Max Orb Displacement"), 5, 10, Qt::AlignLeft);
     1304    cmbLayout->addWidget(_cmbMaxdisplacementLineEdit, 5, 11, Qt::AlignRight);
     1305    cmbLayout->addWidget(new QLabel("Logfile directory"), 6, 10, Qt::AlignLeft);
     1306    cmbLayout->addWidget(_cmbLogPath, 6, 11, Qt::AlignRight);
     1307    cmbLayout->addWidget(new QLabel("Sampling"), 7, 10, Qt::AlignLeft);
     1308    cmbLayout->addWidget(_cmbSamplComboBox, 7, 11, Qt::AlignRight);
     1309
     1310
     1311    cmbLayout->addWidget(new QLabel("GNSS"), 0, 14, Qt::AlignLeft);
     1312    cmbLayout->addWidget(new QLabel("GPS (C1W/C2W)"), 1, 14);
     1313    cmbLayout->addWidget(_cmbGpsCheckBox, 1, 15);
     1314
     1315    cmbLayout->addWidget(new QLabel("GLONASS (C1P/C2P)"), 2, 14);
     1316    cmbLayout->addWidget(_cmbGloCheckBox, 2, 15);
     1317
     1318    cmbLayout->addWidget(new QLabel("Galileo (C1C/C5Q)"), 3, 14);
     1319    cmbLayout->addWidget(_cmbGalCheckBox, 3, 15);
     1320
     1321    cmbLayout->addWidget(new QLabel("Beidou (C2I/C6I)"), 4, 14);
     1322    cmbLayout->addWidget(_cmbBdsCheckBox, 4, 15);
     1323
     1324    cmbLayout->addWidget(new QLabel("QZSS (C1C/C2L)"), 5, 14);
     1325    cmbLayout->addWidget(_cmbQzssCheckBox, 5, 15);
     1326
     1327    cmbLayout->addWidget(new QLabel("SBAS (C1C/C5Q)"), 6, 14);
     1328    cmbLayout->addWidget(_cmbSbasCheckBox, 6, 15);
     1329
     1330    cmbLayout->addWidget(new QLabel("NavIC"), 7, 14);
     1331    cmbLayout->addWidget(_cmbNavicCheckBox, 7, 15);
     1332    cmbLayout->setRowStretch(9, 999);
     1333
     1334    connect(addCmbRowButton, SIGNAL(clicked()), this, SLOT(slotAddCmbRow()));
     1335    connect(delCmbRowButton, SIGNAL(clicked()), this, SLOT(slotDelCmbRow()));
     1336
     1337    cmbgroup->setLayout(cmbLayout);
     1338
     1339    // Upload Layout (Clocks)
     1340    // ----------------------
     1341    QGridLayout* uploadHlpLayout = new QGridLayout();
     1342
     1343    connect(addUploadRowButton, SIGNAL(clicked()), this, SLOT(slotAddUploadRow()));
     1344    connect(delUploadRowButton, SIGNAL(clicked()), this, SLOT(slotDelUploadRow()));
     1345    connect(setUploadTrafoButton, SIGNAL(clicked()), this, SLOT(slotSetUploadTrafo()));
     1346
     1347    uploadHlpLayout->addWidget(addUploadRowButton, 0, 0);
     1348    uploadHlpLayout->addWidget(delUploadRowButton, 0, 1);
     1349    uploadHlpLayout->addWidget(new QLabel("Interval"), 0, 2, Qt::AlignRight);
     1350    uploadHlpLayout->addWidget(_uploadIntrComboBox, 0, 3);
     1351    uploadHlpLayout->addWidget(new QLabel("     Sampling:    Orb"), 0, 4, Qt::AlignRight);
     1352    uploadHlpLayout->addWidget(_uploadSamplRtcmEphCorrComboBox, 0, 5);
     1353    uploadHlpLayout->addWidget(new QLabel("SP3"), 0, 6, Qt::AlignRight);
     1354    uploadHlpLayout->addWidget(_uploadSamplSp3ComboBox, 0, 7);
     1355    uploadHlpLayout->addWidget(new QLabel("RNX"), 0, 8, Qt::AlignRight);
     1356    uploadHlpLayout->addWidget(_uploadSamplClkRnxSpinBox, 0, 9);
     1357    uploadHlpLayout->addWidget(new QLabel("BSX"), 0, 10, Qt::AlignRight);
     1358    uploadHlpLayout->addWidget(_uploadSamplBiaSnxSpinBox, 0, 11);
     1359    uploadHlpLayout->addWidget(setUploadTrafoButton, 0, 12);
     1360    uploadHlpLayout->addWidget(new QLabel("ANTEX file"), 1, 0, Qt::AlignLeft);
     1361    uploadHlpLayout->addWidget(_uploadAntexFile, 1, 1, 1, 4);
     1362
     1363    QBoxLayout* uploadLayout = new QBoxLayout(QBoxLayout::TopToBottom);
     1364    populateUploadTable();
     1365
     1366    uploadLayout->addWidget(new QLabel("Upload RTCM Version 3 Broadcast Corrections to caster.<br>"));
     1367    uploadLayout->addWidget(_uploadTable);
     1368    uploadLayout->addLayout(uploadHlpLayout);
     1369
     1370    uploadgroup->setLayout(uploadLayout);
     1371
     1372    // Upload Layout (Ephemeris)
     1373    // -------------------------
     1374    QGridLayout* uploadHlpLayoutEph = new QGridLayout();
     1375
     1376    connect(addUploadEphRowButton, SIGNAL(clicked()), this, SLOT(slotAddUploadEphRow()));
     1377    connect(delUploadEphRowButton, SIGNAL(clicked()), this, SLOT(slotDelUploadEphRow()));
     1378
     1379    uploadHlpLayoutEph->addWidget(addUploadEphRowButton, 0, 0);
     1380    uploadHlpLayoutEph->addWidget(delUploadEphRowButton, 0, 1);
     1381    uploadHlpLayoutEph->addWidget(new QLabel("     Sampling"), 0, 2, Qt::AlignRight);
     1382    uploadHlpLayoutEph->addWidget(_uploadSamplRtcmEphSpinBox, 0, 3);
     1383
     1384    QBoxLayout* uploadLayoutEph = new QBoxLayout(QBoxLayout::TopToBottom);
     1385    populateUploadEphTable();
     1386
     1387    uploadLayoutEph->addWidget(new QLabel("Upload concatenated RTCMv3 Broadcast Ephemeris to caster.<br>"));
     1388    uploadLayoutEph->addWidget(_uploadEphTable);
     1389    uploadLayoutEph->addLayout(uploadHlpLayoutEph);
     1390
     1391    uploadEphgroup->setLayout(uploadLayoutEph);
     1392
     1393
     1394    // Main Layout
     1395    // -----------
     1396    QGridLayout* mLayout = new QGridLayout;
     1397    _aogroup->setCurrentIndex(settings.value("startTab").toInt());
     1398    mLayout->addWidget(_aogroup, 0, 0);
     1399    mLayout->addWidget(_mountPointsTable, 1, 0);
     1400    _loggroup->setCurrentIndex(settings.value("statusTab").toInt());
     1401    mLayout->addWidget(_loggroup, 2, 0);
     1402
     1403    _canvas->setLayout(mLayout);
     1404
     1405    // WhatsThis, Network
     1406    // ------------------
     1407    _proxyHostLineEdit->setWhatsThis(tr("<p>If you are running BNC within a protected Local Area Network (LAN), you may 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. Without any entry, BNC will try to use the system proxies. </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 this is not possible, you may need to run BNC outside your LAN on a network that has unobstructed connection to the Internet. <i>[key: proxyHost]</i></p>"));
     1408    _proxyPortLineEdit->setWhatsThis(tr("<p>Enter your proxy server port number in case a proxy is operated in front of BNC. <i>[key: proxyPort]</i></p>"));
     1409    _sslCaCertPathLineEdit->setWhatsThis(tr("<p>Communication with an Ntrip Broadcaster over SSL requires the exchange of server certificates. Specify the path to a directory where you save CA certificates on your system. </p><p>BNC creates from *.crt and *.pem files a CA certificate database, which is used by the socket during the handshake phase to validate the peer's certificate. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslCaCertPath]</i></p>"));
     1410    _sslClientCertPathLineEdit->setWhatsThis(tr("<p>Two-sided communication with an Ntrip Broadcaster over SSL requires in addition the exchange of client certificates. Specify the full path to the client certificates on your system.</p><p></p><p>The file naming convention for client certificates in BNC is as follows: &lt;hostname&gt;.&lt;port&gt;.crt for the certificate and &lt;hostname&gt;.&lt;port&gt;.key for the private key, where &lt;hostname&gt; is without https://. </p><p> If available, the client or personal authentication certificate is presented to the peer during the SSL handshake process. Password protected key files are not supported. </p><p>Don't try communication via two sided SSL if you are not sure whether this is supported by the involved Ntrip Broadcaster. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslClientCertPath]</i></p>"));
     1411    _sslIgnoreErrorsCheckBox->setWhatsThis(tr("<p>SSL communication may involve queries coming from the Ntrip Broadcaster. Tick 'Ignore SSL authorization errors' if you don't want to be bothered with this. <i>[key: sslIgnoreErrors]</i></p>"));
     1412
     1413    // WhatsThis, General
     1414    // ------------------
     1415    _logFileLineEdit->setWhatsThis(tr("<p>Records of BNC's activities are shown in the 'Log' tab on the bottom of this window. They can be saved into a file when a valid path for that is specified in the 'Logfile (full path)' field.</p><p>The logfile name will automatically be extended by a string '_YYMMDD' carrying the current date. <i>[key: logFile]</i></p>"));
     1416    _rnxAppendCheckBox->setWhatsThis(tr("<p>When BNC is started, new files are created by default and file content already available under the same name will be overwritten. However, users might want to append already existing files following a regular restart or a crash of BNC or its platform.</p><p>Tick 'Append files' to continue with existing files and keep what has been recorded so far. <i>[key: rnxAppend]</i></p>"));
     1417    _onTheFlyComboBox->setWhatsThis(tr("<p>When operating BNC online in 'no window' mode, some configuration parameters can be changed on-the-fly without interrupting the running process. For that BNC rereads parts of its configuration in pre-defined intervals. The default entry is 'no' that means the reread function is switched of. <p></p>Select '1 min', '5 min', '1 hour', or '1 day' to force BNC to reread its configuration every full minute, five minutes, hour, or day and let in between edited configuration options become effective on-the-fly without terminating uninvolved threads.</p><p>Note that when operating BNC in window mode, on-the-fly changeable configuration options become effective immediately via button 'Save & Reread Configuration'. <i>[key: onTheFlyInterval]</i></p>"));
     1418    _autoStartCheckBox->setWhatsThis(tr("<p>Tick 'Auto start' for auto-start of BNC at startup time in window mode with preassigned processing options. <i>[key: autoStart]</i></p>"));
     1419    _rawOutFileLineEdit->setWhatsThis(tr("<p>Save all data coming in through various streams in the received order and format in one file.</p><p>This option is primarily meant for debugging purposes. <i>[key: rawOutFile]</i></p>"));
     1420
     1421    // WhatsThis, RINEX Observations
     1422    // -----------------------------
     1423    _rnxPathLineEdit->setWhatsThis(tr("<p>Here you specify the path to where the RINEX Observation files will be stored.</p><p>If the specified directory does not exist, BNC will not create RINEX Observation files. <i>[key: rnxPath]</i></p>"));
     1424    _rnxIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Observation file. <i>[key: rnxIntr]</i></p>"));
     1425    _rnxSamplComboBox->setWhatsThis(tr("<p>Select the RINEX Observation sampling interval in seconds. <i>[key: rnxSampl]</i></p>"));
     1426    _rnxSkelExtComboBox->setWhatsThis(tr("<p>BNC allows using personal RINEX skeleton files that contain the RINEX header records you would like to include. You can derive a skeleton file from information given in an up to date sitelog.</p><p>A file in the RINEX Observations 'Directory' with a 'Skeleton extension' skl or SKL is interpreted by BNC as a personal RINEX header skeleton file for the corresponding stream. <i>[key: rnxSkel]</i></p>"));
     1427    _rnxSkelPathLineEdit->setWhatsThis(tr("<p>Here you specify the path to where local skeleton files are located.</p><p> If no directory is specified, the path is assumed to where the RINEX Observation files will stored. <i>[key: rnxSkelPath]</i></p>"));
     1428    _rnxFileCheckBox->setWhatsThis(tr("<p>Tick check box 'Skeleton mandatory' in case you want that RINEX files are only produced if skeleton files are available for BNC. If no skeleton file is available for a particular source then no RINEX Observation file will be produced from the affected stream.</p><p>Note that a skeleton file contains RINEX header information such as receiver and antenna types. In case of stream conversion to RINEX Version 3, a skeleton file should also contain information on potentially available observation types. A missing skeleton file will therefore enforce BNC to only save a default set of RINEX 3 observation types. <i>[key: rnxOnlyWithSKL]</i></p>"));
     1429    _rnxScrpLineEdit->setWhatsThis(tr("<p>Whenever a RINEX Observation file is finally saved, you may want to compress, copy or upload it immediately, for example via FTP. BNC allows you to execute a script/batch file to carry out such operation.</p><p>Specify the full path of a script or batch file. BNC will pass the full RINEX Observation file path to the script as command line parameter (%1 on Windows systems, $1 on Unix/Linux/Mac systems). <i>[key: rnxScript]</i></p>"));
     1430    _rnxV2Priority->setWhatsThis(tr("<p>Specify a priority list of characters defining signal attributes as defined in RINEX Version 3. Priorities will be used to map observations with RINEX Version 3 attributes from incoming streams to Version 2. The underscore character '_' stands for undefined attributes. A question mark '?' can be used as wildcard which represents any one character.</p><p>Signal priorities can be specified as equal for all systems, as system specific or as system and freq. specific. For example: </li><ul><li>'CWPX_?' (General signal priorities valid for all GNSS) </li><li>'I:ABCX' (System specific signal priorities for NavIC) </li><li>'G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX' (System and frequency specific signal priorities) </li></ul>Default is the following priority list 'G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX R:46&ABX E:16&BCXZ E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:267&IQX C:18&DPX I:ABCX S:1&C S:5&IQX'. <i>[key: rnxV2Priority]</i></p>"));
     1431    _rnxVersComboBox->setWhatsThis(tr("<p>Select the format for RINEX Observation files. <i>[key: rnxVersion]</i></p>"));
     1432
     1433    // WhatsThis, RINEX Ephemeris
     1434    // --------------------------
     1435    _ephPathLineEdit->setWhatsThis(tr("<p>Specify the path for saving Broadcast Ephemeris data as RINEX Navigation files.</p><p>If the specified directory does not exist, BNC will not create RINEX Navigation files. <i>[key: ephPath]</i></p>"));
     1436    _ephIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Navigation file. <i>[key: ephIntr]</i></p>"));
     1437    _ephOutPortLineEdit->setWhatsThis(tr("<p>BNC can produce ephemeris data in RINEX Navigation ASCII format on your local host through an IP port.</p><p>Specify a port number here to activate this function. <i>[key: ephOutPort]</i></p>"));
     1438    _ephVersComboBox->setWhatsThis(tr("<p>Select the format for RINEX Navigation files. <i>[key: ephVersion]</i></p>"));
     1439    //_ephFilePerStation->setWhatsThis(tr("<p>By default, all received Broadcast Ephemeris data will be stored within one File. Thick 'File per Stations' to get separate files per station/mountpoint. <i>[key: ephFilePerStation]</i></p>"));
     1440
     1441    // WhatsThis, RINEX Editing & QC
     1442    // -----------------------------
     1443    _reqcActionComboBox->setWhatsThis(tr("<p>BNC allows to 'Edit or Concatenate' RINEX Version 2 or 3 files or to perform a Quality Check (QC) and 'Analyze' data following UNAVCO's famous 'teqc' program. <i>[key: reqcAction]</i></p>"));
     1444    _reqcEditOptionButton->setWhatsThis(tr("<p>Specify options for editing RINEX Version 2 or 3 files.</p>"));
     1445    _reqcObsFileChooser->setWhatsThis(tr("<p>Specify the full path to input observation files in RINEX Version 2 or 3 format.</p><p>Note that when in 'Analyze' mode, specifying at least one RINEX observation file is mandatory. <i>[key: reqcObsFile]</i></p>"));
     1446    _reqcNavFileChooser->setWhatsThis(tr("<p>Specify the full path to input navigation files in RINEX Version 2 or 3 format.</p><p>Note that when in 'Analyze' mode, specifying at least one RINEX navigation file is mandatory. <i>[key: reqcNavFile]</i></p>"));
     1447    _reqcOutObsLineEdit->setWhatsThis(tr("<p>Specify the full path to a RINEX Observation output file.</p><p>Default is an empty option field, meaning that no RINEX Observation output file will be produced. <i>[key: reqcOutObsFile]</i></p>"));
     1448    _reqcOutNavLineEdit->setWhatsThis(tr("<p>Specify the full path to a RINEX Navigation output file.</p><p>Default is an empty option field, meaning that no RINEX Navigation output file will be produced. <i>[key: reqcOutNavFile]</i></p>"));
     1449    _reqcOutLogLineEdit->setWhatsThis(tr("<p>Specify the full path to a logfile.</p><p>Default is an empty option field, meaning that no 'RINEX Editing & QC' logfile will be produced. <i>[key: reqcOutLogFile]</i></p>"));
     1450    _reqcLogSummaryOnly->setWhatsThis(tr("<p>By default BNC produces a detailed 'Logfile' providing all information resulting from editing or analyzing RINEX data. If that is too much information, you can limit the logfile content to a short summary.</p><p>Tick 'Summary only' to suppress full logfile output and instead produce a logfile containing only summary information. <i>[key: reqcLogSummaryOnly]</i></p>"));
     1451    _reqcPlotDirLineEdit->setWhatsThis(tr("<p>Specify a directory for saving plots in PNG format.</p><p>Default is an empty option field, meaning that plots will not be saved on disk. <i>[key: reqcPlotDir]</i></p>"));
     1452    _reqcSkyPlotSignals->setWhatsThis(tr("<p>BNC can produce plots for multipath, signal-to-noise ratio, satellite availability, satellite elevation, and PDOP values. The 'Plots for signals' option lets you exactly specify observation signals to be used for that and also enables the plot generation. You can specify the navigation system, the frequency, and the tracking mode or channel as defined in RINEX Version 3. Specifications for frequency and tracking mode or channel must be separated by ampersand character '&'. Specifications for navigation systems must be separated by blank character ' '.</p><p>Examples for 'Plots for signals' option:<ul><li> G:1&2&5 R:1&2&3 E:1&7 C:2&6 J:1&2 I:5&9 S:1&5 <br>(Plots will be based on GPS observations on 1st and 2nd frequency, GLONASS observations on 1st and 2nd frequency, QZSS observations on 1st and 2nd frequency, Galileo observations on 1st and 7th frequency, BeiDou observations on 1st and 6th frequency, SBAS observations on 1st frequency.)</li><li>G:1C&5X<br>(Plots will be based on GPS observations on 1st frequency in C tracking mode and GPS observations on 5th frequency in X tracking mode.)</li><li>C:6I&7I<br>(Plots will be based on BeiDou observations on 6th frequency in I tracking mode and BeiDou observations on 7th frequency in I tracking mode.)<li></ul></p><p>Default is 'G:1&2 R:1&2 E:1&5 C:2&6 J:1&2 I:5&9 S:1&5'. Specifying an empty option string would be overruled by this default. <i>[key: reqcSkyPlotSignals]</i></p>"));
     1453
     1454    // WhatsThis, SP3 Comparison
     1455    // -------------------------
     1456    _sp3CompFileChooser->setWhatsThis(tr("<p>BNC can compare two SP3 files containing GNSS satellite orbit and clock information.</p></p>Specify the full path to two files with orbits and clocks in SP3 format, separate them by comma. <i>[key: sp3CompFile]</i></p>"));
     1457    _sp3CompExclude->setWhatsThis(tr("<p>Specify satellites to exclude them from orbit and clock comparison. Example:<p>G04,G31,R</p><p>This excludes GPS satellites PRN 4 and 31 as well as all GLONASS satellites from the comparison.</p><p>Default is an empty option field, meaning that no satellite is excluded from the comparison. <i>[key: sp3CompExclude]</i></p>"));
     1458    _sp3CompLogLineEdit->setWhatsThis(tr("<p>Specify the full path to a logfile saving comparison results.</p><p>Specifying a logfile is mandatory. Comparing SP3 files and not saving comparison results on disk would be useless. <i>[key: sp3CompOutLogFile]</i></p>"));
     1459    _sp3CompSummaryOnly->setWhatsThis(tr("<p>By default BNC produces a detailed 'Logfile' providing all information resulting from comparing SP3 files. If that is too much information, you can limit the logfile content to a short summary.</p><p>Tick 'Summary only' to suppress full logfile output and instead produce a logfile containing only summary information. <i>[key: sp3CompSummaryOnly]</i></p>"));
     1460
     1461    // WhatsThis, Broadcast Corrections
     1462    // --------------------------------
     1463    _corrPathLineEdit->setWhatsThis(tr("<p>Specify a directory for saving Broadcast Ephemeris Correction files.</p><p>If the specified directory does not exist, BNC will not create the files. <i>[key: corrPath]</i></p>"));
     1464    _corrIntrComboBox->setWhatsThis(tr("<p>Select the length of Broadcast Ephemeris Correction files. <i>[key: corrIntr]</i></p>"));
     1465    _corrPortLineEdit->setWhatsThis(tr("<p>BNC can produce Broadcast Ephemeris Corrections on your local host through an IP port.</p><p>Specify a port number here to activate this function. <i>[key: corrPort]</i></p>"));
     1466
     1467    // WhatsThis, Feed Engine
     1468    // ----------------------
     1469    _outPortLineEdit->setWhatsThis(tr("<p>BNC can produce synchronized observations in a plain ASCII format on your local host via IP port.</p><p>Specify a port number to activate this function. <i>[key: outPort]</i></p>"));
     1470    _outWaitSpinBox->setWhatsThis(tr("<p>When feeding a real-time GNSS network engine waiting for synchronized input epoch by epoch, BNC drops whatever is received later than 'Wait for full obs epoch' seconds.</p><p>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 network engine or product. <i>[key: outWait]</i></p>"));
     1471    _outSamplComboBox->setWhatsThis(tr("<p>Select a synchronized observation sampling interval in seconds. <i>[key: outSampl]</i></p>"));
     1472    _outFileLineEdit->setWhatsThis(tr("<p>Specify the full path to a file where synchronized observations are saved in plain ASCII format.</p><p>Beware that the size of this file can rapidly increase depending on the number of incoming streams. <i>[key: outFile]</i></p>"));
     1473    _outUPortLineEdit->setWhatsThis(tr("<p>BNC can produce unsynchronized observations in a plain ASCII format on your local host via IP port.</p><p>Specify a port number to activate this function. <i>[key: outUPort]</i></p>"));
     1474    _outLockTimeCheckBox->setWhatsThis(tr("<p>Print the lock time in seconds in the feed engine output.<i>[key: outLockTime]</i></p>"));
     1475
     1476    // WhatsThis, Serial Output
     1477    // ------------------------
     1478    _serialMountPointLineEdit->setWhatsThis(tr("<p>Enter a 'Mountpoint' to forward the corresponding stream to a serial connected receiver.</p><p>Depending on the stream content, the receiver may use it for example for Differential GNSS, Precise Point Positioning or any other purpose supported by its firmware. <i>[key: serialMountPoint]</i></p>"));
     1479    _serialPortNameLineEdit->setWhatsThis(tr("<p>Enter the serial 'Port name' selected for communication with your serial connected receiver. Valid port names are</p><pre>Windows:       COM1, COM2<br>Linux:         /dev/ttyS0, /dev/ttyS1<br>FreeBSD:       /dev/ttyd0, /dev/ttyd1<br>Digital Unix:  /dev/tty01, /dev/tty02<br>HP-UX:         /dev/tty1p0, /dev/tty2p0<br>SGI/IRIX:      /dev/ttyf1, /dev/ttyf2<br>SunOS/Solaris: /dev/ttya, /dev/ttyb</pre><p>Note that before you start BNC, you must plug a serial cable in the port defined here. <i>[key: serialPortName]</i></p>"));
     1480    _serialBaudRateComboBox->setWhatsThis(tr("<p>Select a 'Baud rate' for the serial output link.</p><p>Note that your selection must equal the baud rate configured to the serial connected receiver. Using a high baud rate is recommended. <i>[key: serialBaudRate]</i></p>"));
     1481    _serialFlowControlComboBox->setWhatsThis(tr("<p>Select a 'Flow control' for the serial output link.</p><p>Note that your selection must equal the flow control configured to the serial connected receiver. Select 'OFF' if you don't know better. <i>[key: serialFlowControl]</i></p>"));
     1482    _serialDataBitsComboBox->setWhatsThis(tr("<p>Select the number of 'Data bits' for the serial output link.</p><p>Note that your selection must equal the number of data bits configured to the serial connected receiver. Note further that often 8 data bits are used. <i>[key: serialDataBits]</i></p>"));
     1483    _serialParityComboBox->setWhatsThis(tr("<p>Select a 'Parity' for the serial output link.</p><p>Note that your selection must equal the parity selection configured to the serial connected receiver. The parity is often set to 'NONE'. <i>[key: serialParity]</i></p>"));
     1484    _serialStopBitsComboBox->setWhatsThis(tr("<p>Select the number of 'Stop bits' for the serial output link.</p><p>Note that your selection must equal the number of stop bits configured to the serial connected receiver. Note further that often 1 stop bit is used. <i>[key: serialStopBits]</i></p>"));
     1485    _serialAutoNMEAComboBox->setWhatsThis(tr("<p>The 'NMEA' option supports the so-called 'Virtual Reference Station' (VRS) concept which requires the receiver to send approximate position information to the Ntrip Broadcaster. Select 'no' if you don't want BNC to forward or upload any NMEA message to the Ntrip Broadcaster in support of VRS.</p><p>Select 'Auto' to automatically forward NMEA messages of type GGA from your serial connected receiver to the Ntrip Broadcaster and/or save them in a file.</p><p>Select 'Manual GPGGA' or 'Manual GNGGA' if you want BNC to produce and upload GPGGA or GNGGA NMEA messages to the Ntrip Broadcaster because your serial connected receiver doesn't generate these messages. A Talker ID 'GP' preceding the GGA string stands for GPS solutions while a Talker ID 'GN' stands for multi constellation solutions.</p><p>Note that selecting 'Auto' or 'Manual' works only for VRS streams which show up under the 'Streams' canvas on BNC's main window with 'nmea' stream attribute set to 'yes'. This attribute is either extracted from the Ntrip Broadcaster's source-table or introduced by the user via editing the BNC configuration file. <i>[key: serialAutoNMEA]</i></p>"));
     1486    _serialFileNMEALineEdit->setWhatsThis(tr("<p>Specify the full path to a file where NMEA messages coming from your serial connected receiver are saved.</p><p>Default is an empty option field, meaning that NMEA messages will not be saved on disk. <i>[key: serialFileNMEA]</i></p>"));
     1487    _serialHeightNMEALineEdit->setWhatsThis(tr("<p>Specify an approximate 'Height' above mean sea level in meters for the reference station introduced by option 'Mountpoint'. Together with the latitude and longitude from the source-table, the height information is used to build GGA messages to be sent to the Ntrip Broadcaster.</p><p>For adjusting latitude and longitude values of a VRS stream given in the 'Streams' canvas, you can double click the latitude/longitude data fields, specify appropriate values and then hit Enter.</p><p>This option is only relevant when option 'NMEA' is set to 'Manual GPGGA' or 'Manual GNGGA' respectively. <i>[key: serialHeightNMEA]</i></p>"));
     1488    _serialNMEASamplingSpinBox->setWhatsThis(tr("<p>Select a sampling interval in seconds for manual or receiver generated NMEA GGA sentences and their upload.</p><p>A sampling rate of '0' means, a GGA sentence will be send only once to initialize the requested VRS stream. Note that some VRS systems need GGA sentences at regular intervals. <i>[key: serialNMEASampling]</i></p>"));
     1489
     1490    // WhatsThis, Outages
     1491    // ------------------
     1492    _adviseObsRateComboBox->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>Default is an empty option field, meaning that you don't want BNC to report on stream failures or recoveries when exceeding a threshold time span. <i>[key: adviseObsRate]</i></p>"));
     1493    _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. <i>[key: adviseFail]</i></p>"));
     1494    _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. <i>[key: adviseReco]</i></p>"));
     1495    _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 a comment 'Begin_Outage', 'End_Outage', 'Begin_Corrupted', or 'End_Corrupted' are passed on to the script as command line parameters.</p><p>The script may have the task to send the advisory notes by email to BNC's operator and/or to the affected stream provider.</p><p>An empty option field (default) or invalid path means that you don't want to use this option. <i>[key: adviseScript]</i></p>"));
     1496
     1497    // WhatsThis, Miscellaneous
     1498    // ------------------------
     1499    _miscMountLineEdit->setWhatsThis(tr("<p>Specify a mountpoint to apply any of the options shown below. Enter 'ALL' if you want to apply these options to all configured streams.</p><p>An empty option field (default) means that you don't want BNC to apply any of these options. <i>[key: miscMount]</i></p>"));
     1500    _miscIntrComboBox->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' tab at the end of each 'Log latency' interval together with results of a statistical evaluation (approximate number of covered epochs, data gaps).</p><p>Select a 'Log latency' interval or select the empty option field if you do not want BNC to log latencies and statistical information. <i>[key: miscIntr]</i></p>"));
     1501    _miscScanRTCMCheckBox->setWhatsThis(tr("<p>Tick 'Scan RTCM' to log the numbers of incoming message types as well as contained antenna coordinates, antenna height, and antenna descriptor.</p><p>In case of RTCM Version 3 MSM streams, BNC will also log contained RINEX Version 3 observation types. <i>[key: miscScanRTCM]</i></p>"));
     1502    _miscPortLineEdit->setWhatsThis(tr("<p>BNC can output an incoming stream through an IP port of your local host.</p><p>Specify a port number to activate this function. In this case, the stream content remains untouched; BNC does not decode or reformat the data for this output.</p><p> If the decoder string is not an accepted one ('RTCM_2.x', 'RTCM_3.x' and 'RTNET'), please change the decoder string to <ul>"
     1503        "<li> 'ZERO' (forward the raw data) or </li>"
     1504        "<li> 'ZERO2File' (forward and store the raw data)</li> </ul> in addition. <i>[key: miscPort]</i></p>"));
     1505
     1506    // WhatsThis, PPP (1)
     1507    // ------------------
     1508    _pppWidgets._dataSource->setWhatsThis(tr("<p>Select 'Real-time Streams' for real-time PPP from RTCM streams or 'RINEX Files' for post processing PPP from RINEX files.</p><p><ul><li>Real-time PPP requires that you pull a RTCM stream carrying GNSS observations plus a stream providing corrections to Broadcast Ephemeris. If the observations stream does not contain Broadcast Ephemeris then you must in addition pull a Broadcast Ephemeris stream like 'RTCM3EPH' from Ntrip Broadcaster <u>products.igs-ip.net</u>.<br></li><li>Post processing PPP requires RINEX Observation files, RINEX Navigation files and a file with corrections to Broadcast Ephemeris in plain ASCII format as saved beforehand using BNC.</li></ul></p><p>Note that BNC allows to carry out PPP solutions simultaneously for several stations. <i>[key: PPP/dataSource]</i></p>"));
     1509    _pppWidgets._rinexObs->setWhatsThis(tr("<p>Specify the RINEX Observation file. <i>[key: PPP/rinexObs]</i></p>"));
     1510    _pppWidgets._rinexNav->setWhatsThis(tr("<p>Specify the RINEX Navigation file. <i>[key: PPP/rinexNav]</i></p>"));
     1511    _pppWidgets._corrMount->setWhatsThis(tr("<p>Specify a 'mountpoint' from the 'Streams' canvas below which provides corrections to Broadcast Ephemeris.</p><p>If you don't specify a corrections stream via this option, BNC will fall back to Single Point Positioning (SPP, positioning from observations and Broadcast Ephemeris only) instead of doing PPP. <i>[key: PPP/corrMount]</i></p>"));
     1512    _pppWidgets._ionoMount->setWhatsThis(tr("<p>Specify a 'mountpoint' from the 'Streams' canvas below which provides VTEC informations in SSR format.</p><p>If you don't specify a corrections stream via this option, BNC will use VTEC informations from the Corrections stream 'mountpoint', if available. <i>[key: PPP/ionoMount]</i></p>"));
     1513    _pppWidgets._corrFile->setWhatsThis(tr("<p>Specify the Broadcast Ephemeris Corrections file as saved beforehand using BNC.</p><p>If you don't specify corrections by this option, BNC will fall back to Single Point Positioning (SPP, positioning from RINEX Obs and RINEX Nav files only) instead of doing PPP. <i>[key: PPP/corrFile]</i></p>"));
     1514    _pppWidgets._ionoFile->setWhatsThis(tr("<p>Specify the VTEC file as saved beforehand using BNC.</p><p>If you don't specify corrections by this option, BNC will use VTEC informations from the Corrections file, if available. <i>[key: PPP/ionoFile]</i></p>"));
     1515    _pppWidgets._antexFile->setWhatsThis(tr("<p>Observations in RTCM streams or RINEX files should be referred to the receiver's and to the satellite's Antenna Phase Center (APC) and therefore be corrected for<ul><li>Receiver APC offsets and variations</li><li>Satellite APC offsets and variations.</li></ul> Specify the full path to an IGS 'ANTEX file' which contains APC offsets and variations for satellites and receiver.</p> <i>[key: PPP/antexFile]</i></p>"));
     1516    _pppWidgets._crdFile->setWhatsThis(tr("<p>Enter the full path to an ASCII file which specifies the streams or files of those stations you want to process. Specifying a 'Coordinates file' is optional. If it exists, it should contain one record per station with the following parameters separated by blank character:</p><ul><li>Specify the station either by:<ul><li>the 'Mountpoint' of the station's RTCM stream (in real-time PPP mode), or</li><li>the 9-char station ID of the RINEX Version 3 or 4 Observations file (in post processing PPP mode), or </li><li>the 4-char station ID of the RINEX Version 2 Observations file (in post processing PPP mode).</li></ul><li>Approximate X,Y,Z coordinate of station's Antenna Reference Point [m] (ARP, specify '0.0 0.0 0.0' if unknown).</li><li>North, East and Up component of antenna eccentricity [m] (specify '0.0 0.0 0.0' if unknown). </li><li>20 Characters describing the antenna type and radome following the IGS 'ANTEX file' standard (leave blank if unknown).</li><li>Receiver type following the naming conventions for IGS equipment.</li></ul>Records with exclamation mark '!' in the first column or blank records will be interpreted as comment lines and ignored.. <i>[key: PPP/crdFile]</i></p>"));
     1517    _pppWidgets._blqFile->setWhatsThis(tr("<p>Specify the full path to a 'BLQ file' containing the ocean loading coefficients for different stations. These coefficients can be obtained from the ocean loading service under request trough the web site http://holt.oso.chalmers.se/loading/. <i>[key: PPP/blqFile]</i></p>"));
     1518    _pppWidgets._logPath->setWhatsThis(tr("<p>Specify a directory for saving daily PPP logfiles. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no PPP logfiles shall be produced. <i>[key: PPP/logPath]</i></p>"));
     1519    _pppWidgets._nmeaPath->setWhatsThis(tr("<p>Specify a directory for saving coordinates in daily NMEA files. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no NMEA file shall be produced. <i>[key: PPP/nmeaPath]</i></p>"));
     1520    _pppWidgets._snxtroPath->setWhatsThis(tr("<p>Specify a directory for saving SINEX Troposphere files. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no SINEX Troposphere files shall be produced. <i>[key: PPP/snxtroPath]</i></p>"));
     1521    _pppWidgets._snxtroIntr->setWhatsThis(tr("<p>Select a length for SINEX Troposphere files.</p><p>Default 'SNX TRO interval' for saving SINEX Troposphere files on disk is '1 hour'. <i>[key: PPP/snxtroIntr]</i></p>"));
     1522    _pppWidgets._snxtroSampl->setWhatsThis(tr("<p>Select a 'Sampling' rate for saving troposphere parameters. <i>[key: PPP/snxtroSampl]</i></p>"));
     1523    _pppWidgets._snxtroAc->setWhatsThis(tr("<p>Specify a 3-character abbreviation describing you as the generating Analysis Center (AC) in your SINEX troposphere files. <i>[key: PPP/snxtroAc]</i></p>"));
     1524    _pppWidgets._snxtroSolId->setWhatsThis(tr("<p>Specify a 1-character solution ID to allow a distinction between different solutions per AC. <i>[key: PPP/snxtroSolId]</i></p>"));
     1525    _pppWidgets._snxtroSolType->setWhatsThis(tr("<p>Specify a 3-character solution type, e.g. real-time (RTS), unknown (UNK), .. <i>[key: PPP/snxtroSolType]</i></p>"));
     1526    _pppWidgets._snxtroCampId->setWhatsThis(tr("<p>Specify a 3-character campaign ID, e.g. operational (OPS), demonstration (DEM), testing (TST), .. <i>[key: PPP/snxtroCampId]</i></p>"));
     1527
     1528    // WhatsThis, PPP (2)
     1529    // ------------------
     1530    _pppWidgets._lcGPS->setWhatsThis(tr("<p>Specify which kind of GPS observations you want to use and on which kind of linear combination the GPS ambiguity resolutions shall be based:</p><p><ul>"
     1531#ifdef USE_PPP_SSR_I
     1532        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1533        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1534#else
     1535        "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
     1536        "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
     1537        "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
     1538        "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
     1539        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1540        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1541        "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
     1542#endif
     1543        "<li>'no'    means that you don't want BNC to use GPS data.</li></ul></p><p><i>[key: PPP/lcGPS]</i></p>"));
     1544    _pppWidgets._lcGLONASS->setWhatsThis(tr("<p>Specify which kind of GLONASS observations you want to use and on which kind of linear combination the GLONASS ambiguity resolutions shall be based:</p><p><ul>"
     1545#ifdef USE_PPP_SSR_I
     1546        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1547        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1548        "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
     1549#else
     1550        "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
     1551        "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
     1552        "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
     1553        "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
     1554        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1555        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1556        "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
     1557#endif
     1558        "<li>'no'    means that you don't want BNC to use GLONASS data.</li></ul></p><p><i>[key: PPP/lcGLONASS]</i></p>"));
     1559    _pppWidgets._lcGalileo->setWhatsThis(tr("<p>Specify which kind of Galileo observations you want to use and on which kind of linear combination the Galileo ambiguity resolutions shall be based:</p><p><ul>"
     1560#ifdef USE_PPP_SSR_I
     1561        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1562        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1563        "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
     1564#else
     1565        "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
     1566        "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
     1567        "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
     1568        "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
     1569        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1570        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1571        "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
     1572#endif
     1573        "<li>'no'    means that you don't want BNC to use Galileo data.</li></ul></p><p><i>[key: PPP/lcGalileo]</i></p>"));
     1574    _pppWidgets._lcBDS->setWhatsThis(tr("<p>Specify which kind of BDS observations you want to use and on which kind of linear combination the BDS ambiguity resolutions shall be based:</p><p><ul>"
     1575#ifdef USE_PPP_SSR_I
     1576        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1577        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1578        "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
     1579#else
     1580        "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
     1581        "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
     1582        "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
     1583        "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
     1584        "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
     1585        "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
     1586        "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
     1587#endif
     1588        "<li>'no'    means that you don't want BNC to use BDS data.</li></ul></p><p><i>[key: PPP/lcBDS]</i></p>"));
     1589    _pppWidgets._constraints->setWhatsThis(tr("<p>Specify, whether ionospheric constraints in form of pseudo-observations shall be added. Please note, this is only valid, if no ionosphere-free linear-combination is used and only helpful as soon as the ionosphere information is more accurate than the code data accuracy. <i>[key: PPP/constraints]</i></p>"));
     1590    _pppWidgets._sigmaC1->setWhatsThis(tr("<p>Enter a Sigma for GPS C1 code observations in meters.</p><p>The higher the sigma you enter, the less the contribution of GPS C1 code observations to a PPP solution from combined code and phase data. 1.0 is likely to be an appropriate choice.</p><p>Default is an empty option field, meaning<br>'Sigma C1 = 1.0' <i>[key: PPP/sigmaC1]</i></p>"));
     1591    _pppWidgets._sigmaL1->setWhatsThis(tr("<p>Enter a Sigma for GPS L1 phase observations in meters.</p><p>The higher the sigma you enter, the less the contribution of GPS L1 phase observations to a PPP solutions from combined code and phase data. 0.01 is likely to be an appropriate choice.</p><p>Default is an empty option field, meaning<br>'Sigma L1 = 0.01' <i>[key: PPP/sigmaL1]</i></p>"));
     1592#ifdef USE_PPP
     1593    _pppWidgets._sigmaGIM->setWhatsThis(tr("<p>Enter a Sigma for GIM pseudo observations in meters.</p><p>The higher the sigma you enter, the less the contribution of GIM pseudo observations to a PPP solution. 5.0 is likely to be an appropriate choice.</p><p>Default is an empty option field, meaning<br>'Sigma GIM = 1.0' <i>[key: PPP/sigmaGIM]</i></p>"));
     1594#endif
     1595    _pppWidgets._maxResC1->setWhatsThis(tr("<p>Specify a maximum for residuals from GPS C1 code observations in a PPP solution. '2.0' meters may be an appropriate choice for that.</p><p>If the maximum is exceeded, contributions from the corresponding observation will be ignored in the PPP solution.</p><p>Default is an empty option field, meaning<br>'Max Res C1 = 3.0' <i>[key: PPP/maxResC1]</i></p>"));
     1596    _pppWidgets._maxResL1->setWhatsThis(tr("<p>Specify a maximum for residuals from GPS L1 phase observations in a PPP solution. '0.02' meters may be an appropriate choice for that.</p><p>If the maximum is exceeded, contributions from the corresponding observation will be ignored in the PPP solution.</p><p>Default is an empty option field, meaning<br>'Max Res L1 = 0.03' <i>[key: PPP/maxResL1]</i></p>"));
     1597#ifdef USE_PPP
     1598    _pppWidgets._maxResGIM->setWhatsThis(tr("<p>Specify a maximum for residuals from GIM pseudo observations in a PPP solution. '5.0' meters may be an appropriate choice for that.</p><p>If the maximum is exceeded, contributions from the corresponding observation will be ignored in the PPP solution.</p><p>Default is an empty option field, meaning<br>'Max Res GIM = 3.0' <i>[key: PPP/maxResGIM]</i></p>"));
     1599#endif
     1600    _pppWidgets._eleWgtCode->setWhatsThis(tr("<p>Tic 'Ele Wgt Code' to use satellite Elevation depending Weights for Code observations in the PPP solution. <i>[key: PPP/eleWgtCode]</i></p>"));
     1601    _pppWidgets._eleWgtPhase->setWhatsThis(tr("<p>Tic 'Ele Wgt Phase' to use satellite Elevation depending Weights for Phase observations in the PPP solution. <i>[key: PPP/eleWgtPhase]</i></p>"));
     1602    _pppWidgets._minObs->setWhatsThis(tr("<p>Select a Minimum Number of Observations per epoch for a PPP solution.</p><p>BNC will only process epochs with observation numbers reaching or exceeding this minimum. <i>[key: PPP/minObs]</i></p>"));
     1603    _pppWidgets._minEle->setWhatsThis(tr("<p>Select a Minimum satellite Elevation for observations.</p><p>BNC will ignore an observation if the associated satellite Elevation does not reach or exceed this minimum.</p><p>Selecting '10 deg' may be an appropriate choice in order to avoid too noisy observations. <i>[key: PPP/minEle]</i></p>"));
     1604
     1605    // WhatsThis, Combine Corrections
     1606    // ------------------------------
     1607    _cmbTable->setWhatsThis(tr("<p>BNC allows to process several orbit and clock correction streams in real-time to produce, encode, upload and save a combination of correctors coming from different providers. To add a line to the 'Combine Corrections' table hit the 'Add Row' button, double click on the 'Mountpoint' field to specify a Broadcast Ephemeris Correction mountpoint from the 'Streams' section below and hit Enter. Then double click on the 'AC Name' field to enter your choice of an abbreviation for the Analysis Center (AC) providing the stream. Double click on the 'Weight Factor' field to enter a weight factor to be applied for this stream in the combination. A Factor greater than 1 will enlarge the sigma of the clock pseudo-observations and with it down-weight its contribution. Finally, double click on the 'Exclude Satellites' field and specify satellites, to exclude them for an individual AC. An entry 'G04,G31,R' means to excludes GPS satellites PRN 4 and 31 as well as all GLONASS satellites from one individual AC. Default is an empty option field, meaning that no satellite is excluded from this individual AC.</p><p>Note that the orbit information in the resulting combination stream is just copied from one of the incoming streams. The stream used for providing the orbits may vary over time: if the orbit providing stream has an outage then BNC switches to the next remaining stream for getting hold of the orbit information.</p><p>The combination process requires Broadcast Ephemeris. Besides orbit and clock correction streams BNC should therefore pull a stream carrying Broadcast Ephemeris in the form of RTCM Version 3 messages.</p><p>It is possible to specify only one Broadcast Ephemeris Correction stream in the 'Combine Corrections' table. Instead of combining corrections BNC will then add the corrections to the Broadcast Ephemeris with the possibility to save final orbit and clock results in SP3 and/or Clock RINEX format. <i>[key: cmbStreams]</i></p>"));
     1608    addCmbRowButton->setWhatsThis(tr("<p>Hit 'Add Row' button to add another line to the 'Combine Corrections' table.</p>"));
     1609    delCmbRowButton->setWhatsThis(tr("<p>Hit 'Delete' button to delete the highlighted line(s) from the 'Combine Corrections' table.</p>"));
     1610    _cmbMethodComboBox->setWhatsThis(tr("<p>Select a clock combination approach. Options are 'Single-Epoch' and Kalman 'Filter'.</p><p>It is suggested to use the Kalman filter approach for the purpose of Precise Point Positioning. <i>[key: cmbMethod]</i></p>"));
     1611    _cmbMaxresLineEdit->setWhatsThis(tr("<p>BNC combines all incoming clocks according to specified weights. Individual clock estimates that differ by more than 'Maximal Clk Residuum' meters from the average of all clocks will be ignored.<p></p>It is suggested to specify a value of about 0.2 m for the Kalman filter combination approach and a value of about 3.0 meters for the Single-Epoch combination approach.</p><p>Default is a value of '999.0'. <i>[key: cmbMaxres]</i></p>"));
     1612    _cmbMaxdisplacementLineEdit->setWhatsThis(tr("<p>BNC builds mean values for all incoming orbit corrections per satellite. Individual orbit corrections that differ by more than 'Maximal Orb Displacement' meters from the average of all orbit corrections per satellite will be ignored.<p></p>It is suggested to specify a value of about 0.5 m.</p><p>Default is a value of '2.0'. <i>[key: cmbMaxdisplacement]</i></p>"));
     1613    _cmbSamplComboBox->setWhatsThis(tr("<p>Select a combination Sampling interval for the clocks. Clock corrections will be produced following that interval.</p><p>A value of 10 sec may be an appropriate choice. <i>[key: cmbSampl]</i></p>"));
     1614    _cmbLogPath->setWhatsThis(tr("<p>Specify a directory for saving daily Combination logfiles. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no Combination logfiles shall be produced. <i>[key: cmbLogpath]</i></p>"));
     1615    _cmbGpsCheckBox->setWhatsThis(tr("<p>GPS clock corrections shall be combined. GPS Broadcast ephemeris and corrections are required. <i>[key: cmbGps]</i></p>"));
     1616    _cmbGloCheckBox->setWhatsThis(tr("<p>GLONASS clock corrections shall be combined; GLONASS Broadcast ephemeris and corrections are required. <i>[key: cmbGlo]</i></p>"));
     1617    _cmbGalCheckBox->setWhatsThis(tr("<p>Galileo clock corrections shall be combined; Galileo Broadcast ephemeris and corrections are required. <i>[key: cmbGal]</i></p>"));
     1618    _cmbBdsCheckBox->setWhatsThis(tr("<p>Beidou clock corrections shall be combined; BDS Broadcast ephemeris and corrections are required. <i>[key: cmbBds]</i></p>"));
     1619    _cmbQzssCheckBox->setWhatsThis(tr("<p>QZSS clock corrections shall be combined; QZSS Broadcast ephemeris and corrections are required. <i>[key: cmbQzss]</i></p>"));
     1620    _cmbSbasCheckBox->setWhatsThis(tr("<p>SBAS clock corrections shall be combined; SBAS Broadcast ephemeris and corrections are required. <i>[key: cmbSbas]</i></p>"));
     1621    _cmbNavicCheckBox->setWhatsThis(tr("<p>NavIC clock corrections shall be combined; NavIC Broadcast ephemeris and corrections are required. <i>[key: cmbNavic]</i></p>"));
     1622    _cmbBsxFile->setWhatsThis(tr("<p> Specify a Bias SINEX File that will be used to add satellite code biases to the combined clocks. <i>[key: cmbBsxFile]</i></p>"));
     1623
     1624    // WhatsThis, Upload Corrections
     1625    // -----------------------------
     1626    _uploadTable->setWhatsThis(tr("<p>BNC can upload clock and orbit corrections to Broadcast Ephemeris (Broadcast Corrections) as well as Code Biases in different SSR formats. You may have a situation where clocks, orbits and code biases come from an external Real-time Network Engine (1) or a situation where clock and orbit corrections are combined within BNC (2).</p><p>(1) BNC identifies a stream as coming from a Real-time Network Engine if its format is specified as 'RTNET' and hence its decoder string in the 'Streams' canvas is 'RTNET'. It encodes and uploads that stream to the specified Ntrip Broadcaster Host and Port</p><p>(2) BNC understands that it is expected to encode and upload combined Broadcast Ephemeris Corrections if you specify correction streams in the 'Combine Corrections' table.</p><p>To fill the 'Upload Corrections' table, hit the 'Add Row' button, double click on the 'Host' field to enter the IP or URL of an Ntrip Broadcaster and hit Enter. Select the Ntrip Version that shall be used for data upload. Then double click on the 'Port', 'Mount' and 'Password' fields to enter the Ntrip Broadcaster IP port (default is 80), the mountpoint and the stream upload password. If Ntrip Version 2 is chosen, click to the 'User' field to enter a stream upload user name. An empty 'Host' option field means that you don't want to upload corrections.</p><p>Select a target coordinate reference System (e.g. IGS20) for outgoing clock and orbit corrections.</p><p>Select a target SSR format (e.g. IGS-SSR) for outgoing clock and orbit corrections.</p><p>By default orbit and clock corrections refer to Antenna Phase Center (APC). Tick 'CoM' to refer uploaded corrections to Center of Mass instead of APC.</p><p>Specify a path for saving generated Broadcast Corrections plus Broadcast Ephemeris as SP3 orbit files. If the specified directory does not exist, BNC will not create such files. The following is a path example for a Linux system: /home/user/BKG0MGXRTS${V3PROD}.SP3.</p><p>Specify a path for saving generated Broadcast Correction clocks plus Broadcast Ephemeris clocks as Clock RINEX files. If the specified directory does not exist, BNC will not create Clock RINEX files. The following is a path example for a Linux system: /home/user/BKG0MGXRTS${V3PROD}.CLK.</p><p>Specify a path for saving generated Code Biases as SINEX Bias files. If the specified directory does not exist, BNC will not create SINEX Bias files. The following is a path example for a Linux system: /home/user/BKG0MGXRTS${V3PROD}.BIA.</p><p>Note that '${V3PROD}' produces the time stamp in the filename, which is related to the RINEX version 3 filename concept.</p><p>Finally, specify a SSR Provider ID (issued by RTCM), SSR Solution ID, and SSR Issue of Data number.</p><p>In case the 'Combine Corrections' table contains only one Broadcast Correction stream, BNC will add that stream content to the Broadcast Ephemeris to save results in files specified via SP3 and/or Clock RINEX file path. You should then define only the SP3 and Clock RINEX file path and no further option in the 'Upload Corrections' table. <i>[key: uploadMountpointsOut]</i></p>"));
     1627    addUploadRowButton->setWhatsThis(tr("<p>Hit 'Add Row' button to add another line to the 'Upload Corrections' table.</p>"));
     1628    delUploadRowButton->setWhatsThis(tr("<p>Hit 'Del Row' button to delete the highlighted line(s) from the 'Upload Corrections' table.</p>"));
     1629    _uploadIntrComboBox->setWhatsThis(tr("<p>Select the length of the SP3, Clock RINEX and Bias SINEX files. <i>[key: uploadIntr]</i></p>"));
     1630    _uploadSamplRtcmEphCorrComboBox->setWhatsThis(tr("<p>Select a stream's orbit correction sampling interval in seconds.</p><p>A value of zero '0' tells BNC to upload all available orbit and clock correction samples together in combined messages. <i>[key: uploadSamplRtcmEphCorr]</i></p>"));
     1631    _uploadSamplSp3ComboBox->setWhatsThis(tr("<p>Select a SP3 orbit file sampling interval in seconds.</p><p>A value of zero '0' tells BNC to store all available samples into SP3 orbit files. <i>[key: uploadSamplSp3]</i></p>"));
     1632    _uploadSamplClkRnxSpinBox->setWhatsThis(tr("<p>Select a Clock RINEX file sampling interval in seconds.</p><p>A value of zero '0' tells BNC to store all available samples into Clock RINEX files. <i>[key: uploadSamplClkRnx]</i></p>"));
     1633    _uploadSamplBiaSnxSpinBox->setWhatsThis(tr("<p>Select a Bias SINEX file sampling interval in seconds.</p><p>A value of zero '0' tells BNC to store all available samples into Bias SINEX files. <i>[key: uploadSamplBiaSnx]</i></p>"));
     1634    setUploadTrafoButton->setWhatsThis(tr("<p>Hit 'Custom Trafo' to specify your own 14 parameter Helmert Transformation instead of selecting a predefined transformation via option 'System'.</p>"));
     1635    _uploadAntexFile->setWhatsThis(tr("<p>When producing SP3 files or referring orbit and clock corrections to the satellite's Center of Mass (CoM) instead Antenna Phase Center (APC), an offset has to be applied which is available from the IGS 'ANTEX file'. You must therefore specify an 'ANTEX file' path if you want to save the stream content in SP3 format and/or refer correctors to CoM.</p><p>If you don't specify an 'ANTEX file' path, the SP3 file content as well as the orbit and clock correctors will be referred to satellite APCs. <i>[key: uploadAntexFile]</i></p>"));
     1636
     1637    // WhatsThis, Upload Ephemeris
     1638    // ---------------------------
     1639    _uploadEphTable->setWhatsThis(tr("<p>BNC can upload Broadcast Ephemeris streams in RTCM Version 3 format. To fill the 'Upload Ephemeris' table, hit the 'Add Row' button, double click on the 'Host' field to enter the IP or URL of an Ntrip Broadcaster and hit Enter. Select the Ntrip Version that shall be used for data upload. Then double click on the 'Port', 'Mount' and 'Password' fields to enter the Ntrip Broadcaster IP port (default is 80), the mountpoint and the stream upload password. If Ntrip Version 2 is chosen, click to the 'User' field to enter a stream upload user name. Specify the satellite system(s) that shall be part of the uploaded stream (e.g. G for GPS or GRE for GPS+GLONASS+Galileo, or ALL). <i>[key: uploadEphHost]</i></p>"));
     1640    addUploadEphRowButton->setWhatsThis(tr("<p>Hit 'Add Row' button to add another line to the 'Upload Ephemeris' table.</p>"));
     1641    delUploadEphRowButton->setWhatsThis(tr("<p>Hit 'Del Row' button to delete the highlighted line(s) from the 'Upload Ephemeris' table.</p>"));
     1642    _uploadSamplRtcmEphSpinBox->setWhatsThis(tr("<p>Select the Broadcast Ephemeris sampling interval in seconds.</p><p>Default is '5', meaning that a complete set of Broadcast Ephemeris is uploaded every 5 seconds. <i>[key: uploadSamplRtcmEph]</i></p>"));
     1643
     1644    // WhatsThis, Streams Canvas
     1645    // -------------------------
     1646    _mountPointsTable->setWhatsThis(tr("<p>Streams selected for retrieval are listed in the 'Streams' section. "
     1647        "Clicking on 'Add Stream' button opens a window that allows the user to select data streams from an Ntrip Broadcaster "
     1648        "according to their mountpoints. To remove a stream from the 'Streams' list, highlight it by clicking on it "
     1649        "and hit the 'Delete Stream' button. You can also remove multiple streams by highlighting them using +Shift and +Ctrl.</p><p>"
     1650        "BNC automatically allocates one of its internal decoders to a stream based on the stream's 'format' as given in the source-table. "
     1651        "BNC allows users to change this selection by editing the decoder string. "
     1652        "Double click on the 'decoder' field, enter your preferred decoder and then hit Enter. "
     1653        "Accepted decoder strings are 'RTCM_2.x', 'RTCM_3.x' and 'RTNET'.</p><p>"
     1654        "In case you need to log raw data as is, BNC allows to by-pass its decoders and directly save the input in daily log files. "
     1655        "To do this, specify the decoder string as 'ZERO2FILE'.</p><p>"
     1656        "BNC allows as well to forward streams related to the specified 'Mountpoint' on top of the 'Miscellaneous Panel' "
     1657        "through a TCP/IP port of your local host. "
     1658        "In this case, the stream content remains untouched; BNC does not decode or reformat the data for this output. "
     1659        "If the decoder string is not an accepted one, please change the decoder string to 'ZERO' (forward the raw data only) or 'ZERO2FILE' (forward and store the raw data) in addition.</p><p>"
     1660        "BNC can also retrieve streams from virtual reference stations (VRS). VRS streams are indicated by a 'yes' in the 'nmea' column. "
     1661        "To initiate such stream, the approximate latitude/longitude rover position is sent to the Ntrip Broadcaster "
     1662        "together with an approximation for the height. Default values for latitude and longitude can be change according to your requirement. "
     1663        "Double click on 'lat' and 'long' fields, enter the values you wish to send and then hit Enter. <i>[key: mountPoints]</i></p>"));
     1664    _actAddMountPoints->setWhatsThis(tr("<p>Add stream(s) to selection presented in the 'Streams' canvas.</p>"));
     1665    _actDeleteMountPoints->setWhatsThis(tr("<p>Delete stream(s) from selection presented in the 'Streams' canvas.</p>"));
     1666    _actMapMountPoints->setWhatsThis(tr("<p> Draw distribution map of stream selection presented in the 'Streams' canvas. Use mouse to zoom in or out.</p><p>Left button: Draw rectangle to zoom in.<br>Right button: Zoom out.<br>Middle button: Zoom back.</p>"));
     1667    _actStart->setWhatsThis(tr("<p> Start running BNC.</p>"));
     1668    _actStop->setWhatsThis(tr("<p> Stop running BNC.</p>"));
     1669
     1670    // WhatsThis, Log Canvas
     1671    // ---------------------
     1672    _log->setWhatsThis(tr("<p>Records of BNC's activities are shown in the 'Log' tab. The message log covers the communication status between BNC and the Ntrip Broadcaster as well as problems that occur in the communication link, stream availability, stream delay, stream conversion etc.</p>"));
     1673    _bncFigure->setWhatsThis(tr("<p>The bandwith consumption per stream is shown in the 'Throughput' tab in bits per second (bps) or kilobits per second (kbps).</p>"));
     1674    _bncFigureLate->setWhatsThis(tr("<p>The individual latency of observations of incoming streams is shown in the 'Latency' tab. Streams not carrying observations (e.g. those providing only Broadcast Ephemeris) remain unconsidered.</p><p>Note that the calculation of correct latencies requires the clock of the host computer to be properly synchronized.</p>"));
     1675    _bncFigurePPP->setWhatsThis(tr("<p>PPP time series of North (red), East (green) and Up (blue) displacements are shown in the 'PPP Plot' tab when the corresponding option is selected.</p><p>Values are referred to an XYZ a priori coordinate. The sliding PPP time series window covers the period of the latest 5 minutes.</p>"));
     1676
     1677
     1678    // Enable/Disable all Widgets
     1679    // --------------------------
     1680    slotBncTextChanged();
     1681    enableStartStop();
     1682
     1683    // Auto start
     1684    // ----------
     1685    if (Qt::CheckState(settings.value("autoStart").toInt()) == Qt::Checked) {
     1686        slotStart();
     1687    }
     1688}
     1689
     1690// Destructor
     1691////////////////////////////////////////////////////////////////////////////
     1692bncWindow::~bncWindow() {
     1693    if (_caster) {
     1694        delete _caster; BNC_CORE->setCaster(0);
     1695    }
     1696    if (_casterEph) {
     1697        delete _casterEph;
     1698    }
     1699    delete _bncFigureLate;
     1700    delete _bncFigurePPP;
     1701    delete _actHelp;
     1702    delete _actAbout;
     1703    delete _actFlowchart;
     1704    delete _actFontSel;
     1705    delete _actSaveOpt;
     1706    delete _actQuit;
     1707    delete _actAddMountPoints;
     1708    delete _actDeleteMountPoints;
     1709    delete _actMapMountPoints;
     1710    delete _actStart;
     1711    delete _actStop;
     1712    delete _actwhatsthis;
     1713    delete _proxyHostLineEdit;
     1714    delete _proxyPortLineEdit;
     1715    delete _sslCaCertPathLineEdit;
     1716    delete _sslClientCertPathLineEdit;
     1717    delete _sslIgnoreErrorsCheckBox;
     1718    delete _logFileLineEdit;
     1719    delete _rawOutFileLineEdit;
     1720    delete _rnxAppendCheckBox;
     1721    delete _onTheFlyComboBox;
     1722    delete _autoStartCheckBox;
     1723    delete _rnxPathLineEdit;
     1724    delete _rnxIntrComboBox;
     1725    delete _rnxSamplComboBox;
     1726    delete _rnxSkelExtComboBox;
     1727    delete _rnxSkelPathLineEdit;
     1728    delete _rnxFileCheckBox;
     1729    delete _rnxScrpLineEdit;
     1730    delete _rnxVersComboBox;
     1731    delete _rnxV2Priority;
     1732    delete _ephPathLineEdit;
     1733    //delete _ephFilePerStation;
     1734    delete _ephIntrComboBox;
     1735    delete _ephOutPortLineEdit;
     1736    delete _ephVersComboBox;
     1737    delete _corrPathLineEdit;
     1738    delete _corrIntrComboBox;
     1739    delete _corrPortLineEdit;
     1740    delete _outPortLineEdit;
     1741    delete _outWaitSpinBox;
     1742    delete _outSamplComboBox;
     1743    delete _outFileLineEdit;
     1744    delete _outUPortLineEdit;
     1745    delete _outLockTimeCheckBox;
     1746    delete _serialMountPointLineEdit;
     1747    delete _serialPortNameLineEdit;
     1748    delete _serialBaudRateComboBox;
     1749    delete _serialFlowControlComboBox;
     1750    delete _serialDataBitsComboBox;
     1751    delete _serialParityComboBox;
     1752    delete _serialStopBitsComboBox;
     1753    delete _serialAutoNMEAComboBox;
     1754    delete _serialFileNMEALineEdit;
     1755    delete _serialHeightNMEALineEdit;
     1756    delete _serialNMEASamplingSpinBox;
     1757    delete _adviseObsRateComboBox;
     1758    delete _adviseFailSpinBox;
     1759    delete _adviseRecoSpinBox;
     1760    delete _adviseScriptLineEdit;
     1761    delete _miscMountLineEdit;
     1762    delete _miscPortLineEdit;
     1763    delete _miscIntrComboBox;
     1764    delete _miscScanRTCMCheckBox;
     1765    _mountPointsTable->deleteLater();
     1766    delete _log;
     1767    delete _loggroup;
     1768    _cmbTable->deleteLater();
     1769    delete _cmbMaxresLineEdit;
     1770    delete _cmbMaxdisplacementLineEdit;
     1771    delete _cmbSamplComboBox;
     1772    delete _cmbLogPath;
     1773    delete _cmbMethodComboBox;
     1774    delete _cmbGpsCheckBox;
     1775    delete _cmbGloCheckBox;
     1776    delete _cmbGalCheckBox;
     1777    delete _cmbBdsCheckBox;
     1778    delete _cmbQzssCheckBox;
     1779    delete _cmbSbasCheckBox;
     1780    delete _cmbNavicCheckBox;
     1781    delete _cmbBsxFile;
     1782    _uploadEphTable->deleteLater();
     1783    delete _uploadSamplRtcmEphCorrComboBox;
     1784    _uploadTable->deleteLater();
     1785    delete _uploadIntrComboBox;
     1786    delete _uploadAntexFile;
     1787    delete _uploadSamplRtcmEphSpinBox;
     1788    delete _uploadSamplSp3ComboBox;
     1789    delete _uploadSamplClkRnxSpinBox;
     1790    delete _uploadSamplBiaSnxSpinBox;
     1791    delete _reqcActionComboBox;
     1792    delete _reqcObsFileChooser;
     1793    delete _reqcNavFileChooser;
     1794    delete _reqcOutObsLineEdit;
     1795    delete _reqcOutNavLineEdit;
     1796    delete _reqcOutLogLineEdit;
     1797    delete _reqcPlotDirLineEdit;
     1798    delete _reqcSkyPlotSignals;
     1799    delete _reqcLogSummaryOnly;
     1800    delete _reqcEditOptionButton;
     1801    delete _sp3CompFileChooser;
     1802    delete _sp3CompExclude;
     1803    delete _sp3CompLogLineEdit;
     1804    delete _sp3CompSummaryOnly;
     1805    //delete _canvas;
     1806}
     1807
     1808//
     1809////////////////////////////////////////////////////////////////////////////
     1810void bncWindow::populateMountPointsTable() {
     1811
     1812    for (int iRow = _mountPointsTable->rowCount() - 1; iRow >= 0; iRow--) {
     1813        _mountPointsTable->removeRow(iRow);
     1814    }
     1815
     1816    bncSettings settings;
     1817
     1818    QListIterator<QString> it(settings.value("mountPoints").toStringList());
     1819    int iRow = 0;
     1820    while (it.hasNext()) {
     1821        QStringList hlp = it.next().split(" ");
     1822        if (hlp.size() < 7) continue;
     1823        _mountPointsTable->insertRow(iRow);
     1824
     1825        QUrl    url(hlp[0]);
     1826
     1827        QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
     1828        QString format(hlp[1]); QString country(hlp[2]); QString latitude(hlp[3]); QString longitude(hlp[4]);
     1829        QString nmea(hlp[5]);
     1830        if (hlp[6] == "S") {
     1831            fullPath = hlp[0].replace(0, 2, "");
     1832        }
     1833        QString ntripVersion = "2";
     1834        if (hlp.size() >= 7) {
     1835            ntripVersion = (hlp[6]);
     1836        }
     1837
     1838        QTableWidgetItem* it;
     1839        it = new QTableWidgetItem(url.userInfo());
     1840        it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     1841        _mountPointsTable->setItem(iRow, 0, it);
     1842
     1843        it = new QTableWidgetItem(fullPath);
     1844        it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     1845        _mountPointsTable->setItem(iRow, 1, it);
     1846
     1847        it = new QTableWidgetItem(format);
     1848        _mountPointsTable->setItem(iRow, 2, it);
     1849
     1850        it = new QTableWidgetItem(country);
     1851        _mountPointsTable->setItem(iRow, 3, it);
     1852
     1853        if (nmea == "yes") {
     1854            it = new QTableWidgetItem(latitude);
     1855            _mountPointsTable->setItem(iRow, 4, it);
     1856            it = new QTableWidgetItem(longitude);
     1857            _mountPointsTable->setItem(iRow, 5, it);
     1858        }
     1859        else {
     1860            it = new QTableWidgetItem(latitude);
     1861            it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     1862            _mountPointsTable->setItem(iRow, 4, it);
     1863
     1864            it = new QTableWidgetItem(longitude);
     1865            it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     1866            _mountPointsTable->setItem(iRow, 5, it);
     1867        }
     1868
     1869        it = new QTableWidgetItem(nmea);
     1870        it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     1871        _mountPointsTable->setItem(iRow, 6, it);
     1872
     1873        it = new QTableWidgetItem(ntripVersion);
     1874        ////    it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     1875        _mountPointsTable->setItem(iRow, 7, it);
     1876
     1877        bncTableItem* bncIt = new bncTableItem();
     1878        bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
     1879        _mountPointsTable->setItem(iRow, 8, bncIt);
     1880
     1881        iRow++;
     1882    }
     1883
     1884    _mountPointsTable->sortItems(1);
     1885
     1886    enableStartStop();
     1887}
     1888
     1889// Retrieve Table
     1890////////////////////////////////////////////////////////////////////////////
     1891void bncWindow::slotAddMountPoints() {
     1892
     1893    bncSettings settings;
     1894    QString proxyHost = settings.value("proxyHost").toString();
     1895    int     proxyPort = settings.value("proxyPort").toInt();
     1896    if (proxyHost != _proxyHostLineEdit->text() ||
     1897        proxyPort != _proxyPortLineEdit->text().toInt()) {
     1898        int iRet = QMessageBox::question(this, "Question", "Proxy options "
     1899            "changed. Use the new ones?",
     1900            QMessageBox::Yes, QMessageBox::No,
     1901            QMessageBox::NoButton);
     1902        if (iRet == QMessageBox::Yes) {
     1903            settings.setValue("proxyHost", _proxyHostLineEdit->text());
     1904            settings.setValue("proxyPort", _proxyPortLineEdit->text());
     1905        }
     1906    }
     1907
     1908    settings.setValue("sslCaCertPath", _sslCaCertPathLineEdit->text());
     1909    settings.setValue("sslClientCertPath", _sslClientCertPathLineEdit->text());
     1910    settings.setValue("sslIgnoreErrors", _sslIgnoreErrorsCheckBox->checkState());
     1911
     1912    QMessageBox msgBox;
     1913    msgBox.setIcon(QMessageBox::Question);
     1914    msgBox.setWindowTitle("Add Stream");
     1915    msgBox.setText("Add stream(s) coming from:");
     1916
     1917    QPushButton* buttonNtrip = msgBox.addButton(tr("Caster"), QMessageBox::ActionRole);
     1918    QPushButton* buttonIP = msgBox.addButton(tr("TCP/IP port"), QMessageBox::ActionRole);
     1919    QPushButton* buttonUDP = msgBox.addButton(tr("UDP port"), QMessageBox::ActionRole);
     1920    QPushButton* buttonSerial = msgBox.addButton(tr("Serial port"), QMessageBox::ActionRole);
     1921    QPushButton* buttonCancel = msgBox.addButton(tr("Cancel"), QMessageBox::ActionRole);
     1922
     1923    msgBox.exec();
     1924
     1925    if (msgBox.clickedButton() == buttonNtrip) {
     1926        bncTableDlg* dlg = new bncTableDlg(this);
     1927        dlg->move(this->pos().x() + 50, this->pos().y() + 50);
     1928        connect(dlg, SIGNAL(newMountPoints(QStringList*)),
     1929            this, SLOT(slotNewMountPoints(QStringList*)));
     1930        dlg->exec();
     1931        delete dlg;
     1932    }
     1933    else if (msgBox.clickedButton() == buttonIP) {
     1934        bncIpPort* ipp = new bncIpPort(this);
     1935        connect(ipp, SIGNAL(newMountPoints(QStringList*)),
     1936            this, SLOT(slotNewMountPoints(QStringList*)));
     1937        ipp->exec();
     1938        delete ipp;
     1939    }
     1940    else if (msgBox.clickedButton() == buttonUDP) {
     1941        bncUdpPort* udp = new bncUdpPort(this);
     1942        connect(udp, SIGNAL(newMountPoints(QStringList*)),
     1943            this, SLOT(slotNewMountPoints(QStringList*)));
     1944        udp->exec();
     1945        delete udp;
     1946    }
     1947    else if (msgBox.clickedButton() == buttonSerial) {
     1948        bncSerialPort* sep = new bncSerialPort(this);
     1949        connect(sep, SIGNAL(newMountPoints(QStringList*)),
     1950            this, SLOT(slotNewMountPoints(QStringList*)));
     1951        sep->exec();
     1952        delete sep;
     1953    }
     1954    else if (msgBox.clickedButton() == buttonCancel) {
     1955        // Cancel
     1956    }
     1957
     1958    enableStartStop();
     1959}
     1960
     1961// Delete Selected Mount Points
     1962////////////////////////////////////////////////////////////////////////////
     1963void bncWindow::slotDeleteMountPoints() {
     1964
     1965    int nRows = _mountPointsTable->rowCount();
     1966    std::vector <bool> flg(nRows);
     1967    for (int iRow = 0; iRow < nRows; iRow++) {
     1968        if (_mountPointsTable->item(iRow, 1)->isSelected()) {
     1969            flg[iRow] = true;
     1970        }
     1971        else {
     1972            flg[iRow] = false;
     1973        }
     1974    }
     1975    for (int iRow = nRows - 1; iRow >= 0; iRow--) {
     1976        if (flg[iRow]) {
     1977            _mountPointsTable->removeRow(iRow);
     1978        }
     1979    }
     1980    _actDeleteMountPoints->setEnabled(false);
     1981
     1982    enableStartStop();
     1983}
     1984
     1985// New Mount Points Selected
     1986////////////////////////////////////////////////////////////////////////////
     1987void bncWindow::slotNewMountPoints(QStringList* mountPoints) {
     1988    int iRow = 0;
     1989    QListIterator<QString> it(*mountPoints);
     1990    while (it.hasNext()) {
     1991        QStringList hlp = it.next().split(" ");
     1992        QUrl    url(hlp[0]);
     1993        QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
     1994        QString format(hlp[1]); QString country(hlp[2]); QString latitude(hlp[3]); QString longitude(hlp[4]);
     1995        QString nmea(hlp[5]);
     1996        if (hlp[6] == "S") {
     1997            fullPath = hlp[0].replace(0, 2, "");
     1998        }
     1999        QString ntripVersion = "2";
     2000        if (hlp.size() >= 7) {
     2001            ntripVersion = (hlp[6]);
     2002        }
     2003
     2004        _mountPointsTable->insertRow(iRow);
     2005
     2006        QTableWidgetItem* it;
     2007        it = new QTableWidgetItem(url.userInfo());
     2008        it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     2009        _mountPointsTable->setItem(iRow, 0, it);
     2010
     2011        it = new QTableWidgetItem(fullPath);
     2012        it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     2013        _mountPointsTable->setItem(iRow, 1, it);
     2014
     2015        it = new QTableWidgetItem(format);
     2016        _mountPointsTable->setItem(iRow, 2, it);
     2017
     2018        it = new QTableWidgetItem(country);
     2019        _mountPointsTable->setItem(iRow, 3, it);
     2020
     2021        if (nmea == "yes") {
     2022            it = new QTableWidgetItem(latitude);
     2023            _mountPointsTable->setItem(iRow, 4, it);
     2024            it = new QTableWidgetItem(longitude);
     2025            _mountPointsTable->setItem(iRow, 5, it);
     2026        }
     2027        else {
     2028            it = new QTableWidgetItem(latitude);
     2029            it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     2030            _mountPointsTable->setItem(iRow, 4, it);
     2031            it = new QTableWidgetItem(longitude);
     2032            it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     2033            _mountPointsTable->setItem(iRow, 5, it);
     2034        }
     2035
     2036        it = new QTableWidgetItem(nmea);
     2037        it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     2038        _mountPointsTable->setItem(iRow, 6, it);
     2039
     2040        it = new QTableWidgetItem(ntripVersion);
     2041        ////it->setFlags(it->flags() & ~Qt::ItemIsEditable);
     2042        _mountPointsTable->setItem(iRow, 7, it);
     2043
     2044        bncTableItem* bncIt = new bncTableItem();
     2045        _mountPointsTable->setItem(iRow, 8, bncIt);
     2046
     2047        iRow++;
     2048    }
     2049    _mountPointsTable->hideColumn(0);
     2050    _mountPointsTable->hideColumn(3);
     2051    _mountPointsTable->sortItems(1);
     2052    delete mountPoints;
     2053
     2054    enableStartStop();
     2055}
     2056
     2057// Save Options (serialize)
     2058////////////////////////////////////////////////////////////////////////////
     2059void bncWindow::slotSaveOptions() {
     2060    saveOptions();
     2061    bncSettings settings;
     2062    settings.sync();
     2063}
     2064
     2065// Save Options (memory only)
     2066////////////////////////////////////////////////////////////////////////////
     2067void bncWindow::saveOptions() {
     2068
     2069    QStringList mountPoints;
     2070    for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
     2071
     2072        if (_mountPointsTable->item(iRow, 6)->text() != "S") {
     2073            QUrl url("//" + _mountPointsTable->item(iRow, 0)->text() +
     2074                "@" + _mountPointsTable->item(iRow, 1)->text());
     2075
     2076            mountPoints.append(url.toString() + " " +
     2077                _mountPointsTable->item(iRow, 2)->text()
     2078                + " " + _mountPointsTable->item(iRow, 3)->text()
     2079                + " " + _mountPointsTable->item(iRow, 4)->text()
     2080                + " " + _mountPointsTable->item(iRow, 5)->text()
     2081                + " " + _mountPointsTable->item(iRow, 6)->text()
     2082                + " " + _mountPointsTable->item(iRow, 7)->text());
     2083        }
     2084        else {
     2085            mountPoints.append(
     2086                "//" + _mountPointsTable->item(iRow, 1)->text()
     2087                + " " + _mountPointsTable->item(iRow, 2)->text()
     2088                + " " + _mountPointsTable->item(iRow, 3)->text()
     2089                + " " + _mountPointsTable->item(iRow, 4)->text()
     2090                + " " + _mountPointsTable->item(iRow, 5)->text()
     2091                + " " + _mountPointsTable->item(iRow, 6)->text()
     2092                + " " + _mountPointsTable->item(iRow, 7)->text());
     2093        }
     2094    }
     2095
     2096    QStringList cmbStreams;
     2097    for (int iRow = 0; iRow < _cmbTable->rowCount(); iRow++) {
     2098        QString hlp;
     2099        for (int iCol = 0; iCol < _cmbTable->columnCount(); iCol++) {
     2100            if (_cmbTable->item(iRow, iCol)) {
     2101                hlp += _cmbTable->item(iRow, iCol)->text() + " ";
     2102            }
     2103        }
     2104        if (!hlp.isEmpty()) {
     2105            cmbStreams << hlp;
     2106        }
     2107    }
     2108
     2109    QStringList uploadMountpointsOut;
     2110    for (int iRow = 0; iRow < _uploadTable->rowCount(); iRow++) {
     2111        QString hlp;
     2112        for (int iCol = 0; iCol < _uploadTable->columnCount(); iCol++) {
     2113            if (_uploadTable->cellWidget(iRow, iCol) &&
     2114                (iCol == 3 || iCol == 4 || iCol == 5 || iCol == 6 || iCol == 7 || iCol == 8)) {
     2115                if (iCol == 3) {
     2116                    QComboBox* ntripversion = (QComboBox*)(_uploadTable->cellWidget(iRow, iCol));
     2117                    hlp += ntripversion->currentText() + ",";
     2118                }
     2119                else if (iCol == 4) {
     2120                    QLineEdit* user = (QLineEdit*)(_uploadTable->cellWidget(iRow, iCol));
     2121                    hlp += user->text() + ",";
     2122                }
     2123                else if (iCol == 5) {
     2124                    QLineEdit* passwd = (QLineEdit*)(_uploadTable->cellWidget(iRow, iCol));
     2125                    hlp += passwd->text() + ",";
     2126                }
     2127                else if (iCol == 6) {
     2128                    QComboBox* system = (QComboBox*)(_uploadTable->cellWidget(iRow, iCol));
     2129                    hlp += system->currentText() + ",";
     2130                }
     2131                else if (iCol == 7) {
     2132                    QComboBox* format = (QComboBox*)(_uploadTable->cellWidget(iRow, iCol));
     2133                    hlp += format->currentText() + ",";
     2134                }
     2135                else if (iCol == 8) {
     2136                    QCheckBox* com = (QCheckBox*)(_uploadTable->cellWidget(iRow, iCol));
     2137                    QString state; state.setNum(com->checkState());
     2138                    hlp += state + ",";
     2139                }
     2140            }
     2141            else if (_uploadTable->item(iRow, iCol)) {
     2142                hlp += _uploadTable->item(iRow, iCol)->text() + ",";
     2143            }
     2144        }
     2145        if (!hlp.isEmpty()) {
     2146            uploadMountpointsOut << hlp;
     2147        }
     2148    }
     2149
     2150    QStringList uploadEphMountpointsOut;
     2151    for (int iRow = 0; iRow < _uploadEphTable->rowCount(); iRow++) {
     2152        QString hlp;
     2153        for (int iCol = 0; iCol < _uploadEphTable->columnCount(); iCol++) {
     2154            if (_uploadEphTable->cellWidget(iRow, iCol) &&
     2155                (iCol == 3 || iCol == 4 || iCol == 5 || iCol == 6)) {
     2156                if (iCol == 3) {
     2157                    QComboBox* ntripversion = (QComboBox*)(_uploadEphTable->cellWidget(iRow, iCol));
     2158                    hlp += ntripversion->currentText() + ",";
     2159                }
     2160                else if (iCol == 4) {
     2161                    QLineEdit* user = (QLineEdit*)(_uploadEphTable->cellWidget(iRow, iCol));
     2162                    hlp += user->text() + ",";
     2163                }
     2164                else if (iCol == 5) {
     2165                    QLineEdit* passwd = (QLineEdit*)(_uploadEphTable->cellWidget(iRow, iCol));
     2166                    hlp += passwd->text() + ",";
     2167                }
     2168                else if (iCol == 6) {
     2169                    QLineEdit* system = (QLineEdit*)(_uploadEphTable->cellWidget(iRow, iCol));
     2170                    hlp += system->text() + ",";
     2171                }
     2172            }
     2173            else if (_uploadEphTable->item(iRow, iCol)) {
     2174                hlp += _uploadEphTable->item(iRow, iCol)->text() + ",";
     2175            }
     2176        }
     2177        if (!hlp.isEmpty()) {
     2178            uploadEphMountpointsOut << hlp;
     2179        }
     2180    }
     2181
     2182    bncSettings settings;
     2183
     2184    settings.setValue("startTab", _aogroup->currentIndex());
     2185    settings.setValue("statusTab", _loggroup->currentIndex());
     2186    settings.setValue("mountPoints", mountPoints);
     2187    // Network
     2188    settings.setValue("proxyHost", _proxyHostLineEdit->text());
     2189    settings.setValue("proxyPort", _proxyPortLineEdit->text());
     2190    settings.setValue("sslCaCertPath", _sslCaCertPathLineEdit->text());
     2191    settings.setValue("sslClientCertPath", _sslClientCertPathLineEdit->text());
     2192    settings.setValue("sslIgnoreErrors", _sslIgnoreErrorsCheckBox->checkState());
     2193    // General
     2194    settings.setValue("logFile", _logFileLineEdit->text());
     2195    settings.setValue("rnxAppend", _rnxAppendCheckBox->checkState());
     2196    settings.setValue("onTheFlyInterval", _onTheFlyComboBox->currentText());
     2197    settings.setValue("autoStart", _autoStartCheckBox->checkState());
     2198    settings.setValue("rawOutFile", _rawOutFileLineEdit->text());
     2199    // RINEX Observations
     2200    settings.setValue("rnxPath", _rnxPathLineEdit->text());
     2201    settings.setValue("rnxIntr", _rnxIntrComboBox->currentText());
     2202    settings.setValue("rnxSampl", _rnxSamplComboBox->currentText());
     2203    settings.setValue("rnxSkel", _rnxSkelExtComboBox->currentText());
     2204    settings.setValue("rnxSkelPath", _rnxSkelPathLineEdit->text());
     2205    settings.setValue("rnxOnlyWithSKL", _rnxFileCheckBox->checkState());
     2206    settings.setValue("rnxScript", _rnxScrpLineEdit->text());
     2207    settings.setValue("rnxV2Priority", _rnxV2Priority->text());
     2208    settings.setValue("rnxVersion", _rnxVersComboBox->currentText());
     2209    // RINEX Ephemeris
     2210    settings.setValue("ephPath", _ephPathLineEdit->text());
     2211    settings.setValue("ephIntr", _ephIntrComboBox->currentText());
     2212    settings.setValue("ephOutPort", _ephOutPortLineEdit->text());
     2213    settings.setValue("ephVersion", _ephVersComboBox->currentText());
     2214    //settings.setValue("ephFilePerStation", _ephFilePerStation->checkState());
    8572215  // Broadcast Corrections
    858   // ---------------------
    859   QGridLayout* cLayout = new QGridLayout;
    860   cLayout->setColumnMinimumWidth(0,14*ww);
    861   _corrIntrComboBox->setMaximumWidth(9*ww);
    862   _corrPortLineEdit->setMaximumWidth(9*ww);
    863 
    864   cLayout->addWidget(new QLabel("Saving Broadcast Ephemeris correction files and correction output through IP port.<br>"),0,0,1,70);
    865   cLayout->addWidget(new QLabel("Directory, ASCII"),              1, 0);
    866   cLayout->addWidget(_corrPathLineEdit,                           1, 1, 1,30);
    867   cLayout->addWidget(new QLabel("Interval"),                      2, 0);
    868   cLayout->addWidget(_corrIntrComboBox,                           2, 1);
    869   cLayout->addWidget(new QLabel("Port"),                          3, 0);
    870   cLayout->addWidget(_corrPortLineEdit,                           3, 1);
    871   cLayout->addWidget(new QLabel(""),                              4, 1);
    872   cLayout->setRowStretch(7, 999);
    873   cgroup->setLayout(cLayout);
    874 
    875   // Feed Engine
    876   // -----------
    877   QGridLayout* sLayout = new QGridLayout;
    878   sLayout->setColumnMinimumWidth(0,14*ww);
    879   _outPortLineEdit->setMaximumWidth(9*ww);
    880   _outWaitSpinBox->setMaximumWidth(9*ww);
    881   _outSamplComboBox->setMaximumWidth(9*ww);
    882   _outUPortLineEdit->setMaximumWidth(9*ww);
    883 
    884   sLayout->addWidget(new QLabel("Output decoded observations in ASCII format to feed a real-time GNSS network engine.<br>"),0,0,1,50);
    885   sLayout->addWidget(new QLabel("Port"),                            1, 0);
    886   sLayout->addWidget(_outPortLineEdit,                              1, 1);
    887   sLayout->addWidget(new QLabel("       Wait for full obs epoch"),  1, 2, Qt::AlignRight);
    888   sLayout->addWidget(_outWaitSpinBox,                               1, 3, Qt::AlignLeft);
    889   sLayout->addWidget(new QLabel("Sampling"),                        2, 0);
    890   sLayout->addWidget(_outSamplComboBox,                             2, 1, Qt::AlignLeft);
    891   sLayout->addWidget(new QLabel("File (full path)"),                3, 0);
    892   sLayout->addWidget(_outFileLineEdit,                              3, 1, 1, 10);
    893   sLayout->addWidget(new QLabel("Port (unsynchronized)"),           4, 0);
    894   sLayout->addWidget(_outUPortLineEdit,                             4, 1);
    895   sLayout->addWidget(new QLabel("Print lock time"),                 5, 0);
    896   sLayout->addWidget(_outLockTimeCheckBox,                        5, 1);
    897   sLayout->addWidget(new QLabel(""),                                6, 1);
    898   sLayout->setRowStretch(7, 999);
    899 
    900   sgroup->setLayout(sLayout);
    901 
    902   // Serial Output
    903   // -------------
    904   QGridLayout* serLayout = new QGridLayout;
    905   serLayout->setColumnMinimumWidth(0,12*ww);
    906   _serialBaudRateComboBox->setMaximumWidth(9*ww);
    907   _serialFlowControlComboBox->setMaximumWidth(11*ww);
    908   _serialDataBitsComboBox->setMaximumWidth(5*ww);
    909   _serialParityComboBox->setMaximumWidth(9*ww);
    910   _serialStopBitsComboBox->setMaximumWidth(5*ww);
    911   _serialAutoNMEAComboBox->setMaximumWidth(14*ww);
    912   _serialHeightNMEALineEdit->setMaximumWidth(8*ww);
    913   _serialNMEASamplingSpinBox->setMaximumWidth(8*ww);
    914 
    915   serLayout->addWidget(new QLabel("Port settings to feed a serial connected receiver.<br>"),0,0,1,30);
    916   serLayout->addWidget(new QLabel("Mountpoint"),                  1, 0, Qt::AlignLeft);
    917   serLayout->addWidget(_serialMountPointLineEdit,                 1, 1, 1, 2);
    918   serLayout->addWidget(new QLabel("Port name"),                   2, 0, Qt::AlignLeft);
    919   serLayout->addWidget(_serialPortNameLineEdit,                   2, 1, 1, 2);
    920   serLayout->addWidget(new QLabel("Baud rate"),                   3, 0, Qt::AlignLeft);
    921   serLayout->addWidget(_serialBaudRateComboBox,                   3, 1);
    922   serLayout->addWidget(new QLabel("Flow control"),                3, 2, Qt::AlignRight);
    923   serLayout->addWidget(_serialFlowControlComboBox,                3, 3);
    924   serLayout->addWidget(new QLabel("Data bits"),                   4, 0, Qt::AlignLeft);
    925   serLayout->addWidget(_serialDataBitsComboBox,                   4, 1);
    926   serLayout->addWidget(new QLabel("Parity"),                      4, 2, Qt::AlignRight);
    927   serLayout->addWidget(_serialParityComboBox,                     4, 3);
    928   serLayout->addWidget(new QLabel("   Stop bits"),                4, 4, Qt::AlignRight);
    929   serLayout->addWidget(_serialStopBitsComboBox,                   4, 5);
    930   serLayout->addWidget(new QLabel("NMEA"),                        5, 0);
    931   serLayout->addWidget(_serialAutoNMEAComboBox,                   5, 1);
    932   serLayout->addWidget(new QLabel("    File (full path)"),        5, 2, Qt::AlignRight);
    933   serLayout->addWidget(_serialFileNMEALineEdit,                   5, 3, 1,10);
    934   serLayout->addWidget(new QLabel("Height"),                      5,14, Qt::AlignRight);
    935   serLayout->addWidget(_serialHeightNMEALineEdit,                 5,15, 1,11);
    936   serLayout->addWidget(new QLabel("Sampling"),                    5,25, Qt::AlignRight);
    937   serLayout->addWidget(_serialNMEASamplingSpinBox,          5,26, 1,12);
    938   serLayout->addWidget(new QLabel(""),                            6, 1);
    939   serLayout->setRowStretch(7, 999);
    940 
    941   sergroup->setLayout(serLayout);
    942 
    943   // Outages
    944   // -------
    945   QGridLayout* aLayout = new QGridLayout;
    946   aLayout->setColumnMinimumWidth(0,14*ww);
    947   _adviseObsRateComboBox->setMaximumWidth(9*ww);
    948   _adviseFailSpinBox->setMaximumWidth(9*ww);
    949   _adviseRecoSpinBox->setMaximumWidth(9*ww);
    950 
    951   aLayout->addWidget(new QLabel("Failure and recovery reports, advisory notes.<br>"),0,0,1,50,Qt::AlignLeft);
    952   aLayout->addWidget(new QLabel("Observation rate"),              1, 0);
    953   aLayout->addWidget(_adviseObsRateComboBox,                      1, 1);
    954   aLayout->addWidget(new QLabel("Failure threshold"),             2, 0);
    955   aLayout->addWidget(_adviseFailSpinBox,                          2, 1);
    956   aLayout->addWidget(new QLabel("Recovery threshold"),            3, 0);
    957   aLayout->addWidget(_adviseRecoSpinBox,                          3, 1);
    958   aLayout->addWidget(new QLabel("Script (full path)"),            4, 0);
    959   aLayout->addWidget(_adviseScriptLineEdit,                       4, 1, 1,20);
    960   aLayout->addWidget(new QLabel(""),                              5, 1);
    961   aLayout->setRowStretch(6, 999);
    962 
    963   agroup->setLayout(aLayout);
    964 
    965   // Miscellaneous
    966   // -------------
    967   QGridLayout* rLayout = new QGridLayout;
    968   rLayout->setColumnMinimumWidth(0,14*ww);
    969   _miscIntrComboBox->setMaximumWidth(9*ww);
    970   _miscPortLineEdit->setMaximumWidth(9*ww);
    971 
    972   rLayout->addWidget(new QLabel("Log latencies or scan RTCM streams for message types and antenna information or output raw data through TCP/IP port.<br>"),0, 0,1,50);
    973   rLayout->addWidget(new QLabel("Mountpoint"),                    1, 0);
    974   rLayout->addWidget(_miscMountLineEdit,                          1, 1, 1, 7);
    975   rLayout->addWidget(new QLabel("Log latency"),                   2, 0);
    976   rLayout->addWidget(_miscIntrComboBox,                           2, 1);
    977   rLayout->addWidget(new QLabel("Scan RTCM"),                     3, 0);
    978   rLayout->addWidget(_miscScanRTCMCheckBox,                       3, 1);
    979   rLayout->addWidget(new QLabel("Port"),                          4, 0);
    980   rLayout->addWidget(_miscPortLineEdit,                           4, 1);
    981   rLayout->addWidget(new QLabel(""),                              5, 1);
    982   rLayout->setRowStretch(6, 999);
    983 
    984   rgroup->setLayout(rLayout);
    985 
    986   // PPP
    987   // ---
    988   _pppWidgets._dataSource->setMaximumWidth(15*ww);
    989   _pppWidgets._corrMount->setMaximumWidth(15*ww);
    990   _pppWidgets._nmeaPath->setMaximumWidth(35*ww);
    991   _pppWidgets._logPath->setMaximumWidth(35*ww);
    992   _pppWidgets._snxtroPath->setMaximumWidth(35*ww);
    993   _pppWidgets._snxtroIntr->setMaximumWidth(7*ww);
    994   _pppWidgets._snxtroAc->setMaximumWidth(7*ww);
    995   _pppWidgets._snxtroSolId->setMaximumWidth(7*ww);
    996   _pppWidgets._snxtroSolType->setMaximumWidth(7*ww);
    997   _pppWidgets._snxtroCampId->setMaximumWidth(7*ww);
    998     _pppWidgets._ionoMount->setMaximumWidth(15*ww);
    999 
    1000 
    1001   QGridLayout* pppLayout1 = new QGridLayout();
    1002   int ir = 0;
    1003   pppLayout1->addWidget(new QLabel("Precise Point Positioning - Input and Output.<br>"), ir, 0, 1, 7, Qt::AlignLeft);
    1004   ++ir;
    1005   pppLayout1->addWidget(new QLabel("Data source"),           ir, 0);
    1006   pppLayout1->addWidget(_pppWidgets._dataSource,             ir, 1);
    1007   pppLayout1->addWidget(new QLabel("   Logfile directory"),  ir, 4);
    1008   pppLayout1->addWidget(_pppWidgets._logPath,                ir, 5, 1, 3);
    1009   ++ir;
    1010   pppLayout1->addWidget(new QLabel("Corrections stream"),    ir, 0);
    1011   pppLayout1->addWidget(_pppWidgets._corrMount,              ir, 1);
    1012   pppLayout1->addWidget(new QLabel("Corrections file"),      ir, 2);
    1013   pppLayout1->addWidget(_pppWidgets._corrFile,               ir, 3);
    1014   pppLayout1->addWidget(new QLabel("   NMEA directory"),     ir, 4);
    1015   pppLayout1->addWidget(_pppWidgets._nmeaPath,               ir, 5, 1, 3);
    1016   ++ir;
    1017 #ifdef USE_PPP
    1018   pppLayout1->addWidget(new QLabel("Ionosphere stream"),     ir, 0);
    1019   pppLayout1->addWidget(_pppWidgets._ionoMount,              ir, 1);
    1020   pppLayout1->addWidget(new QLabel("Ionosphere file"),       ir, 2);
    1021   pppLayout1->addWidget(_pppWidgets._ionoFile,               ir, 3);
    1022 #endif
    1023   pppLayout1->addWidget(new QLabel("   SNX TRO directory"),  ir, 4);
    1024   pppLayout1->addWidget(_pppWidgets._snxtroPath,             ir, 5, 1, 3);
    1025   ++ir;
    1026   pppLayout1->addWidget(new QLabel("RINEX Obs file"),        ir, 0);
    1027   pppLayout1->addWidget(_pppWidgets._rinexObs,               ir, 1);
    1028   pppLayout1->addWidget(new QLabel("RINEX Nav file"),        ir, 2);
    1029   pppLayout1->addWidget(_pppWidgets._rinexNav,               ir, 3);
    1030   pppLayout1->addWidget(new QLabel("   SNX TRO interval"),   ir, 4);
    1031   pppLayout1->addWidget(_pppWidgets._snxtroIntr,             ir, 5);
    1032   pppLayout1->addWidget(new QLabel("   SNX TRO sampling"),   ir, 6);
    1033   pppLayout1->addWidget(_pppWidgets._snxtroSampl,            ir, 7, Qt::AlignRight);
    1034   ++ir;
    1035   pppLayout1->addWidget(new QLabel("ANTEX file"),            ir, 0);
    1036   pppLayout1->addWidget(_pppWidgets._antexFile,              ir, 1);
    1037   pppLayout1->addWidget(new QLabel("Coordinates file"),      ir, 2);
    1038   pppLayout1->addWidget(_pppWidgets._crdFile,                ir, 3);
    1039   pppLayout1->addWidget(new QLabel("   SNX TRO AC"),         ir, 4);
    1040   pppLayout1->addWidget(_pppWidgets._snxtroAc,               ir, 5);
    1041   pppLayout1->addWidget(new QLabel("   SNX TRO solution ID"),ir, 6);
    1042   pppLayout1->addWidget(_pppWidgets._snxtroSolId,            ir, 7, Qt::AlignRight);
    1043   ++ir;
    1044 #ifdef USE_PPP
    1045   pppLayout1->addWidget(new QLabel("BLQ file"),               ir, 0);
    1046   pppLayout1->addWidget(_pppWidgets._blqFile,                 ir, 1);
    1047   pppLayout1->addWidget(new QLabel("   SNX TRO campaign ID"), ir, 4);
    1048   pppLayout1->addWidget(_pppWidgets._snxtroCampId,            ir, 5);
    1049   pppLayout1->addWidget(new QLabel("   SNX TRO solution type"),ir, 6);
    1050   pppLayout1->addWidget(_pppWidgets._snxtroSolType,            ir, 7, Qt::AlignRight);
    1051 #endif
    1052   pppLayout1->setRowStretch(ir+1, 999);
    1053   pppGroup1->setLayout(pppLayout1);
    1054 
    1055   QGridLayout* pppLayout2 = new QGridLayout();
    1056   ir = 0;
    1057   pppLayout2->addWidget(new QLabel("Precise Point Positioning - Options.<br>"), ir, 0, 1, 2, Qt::AlignLeft);
    1058   ++ir;
    1059   pppLayout2->addWidget(new QLabel("GPS LCs"),              ir, 0, Qt::AlignLeft);
    1060   pppLayout2->addWidget(_pppWidgets._lcGPS,                 ir, 1);
    1061   pppLayout2->addItem(new QSpacerItem(8*ww, 0),             ir, 2);
    1062   pppLayout2->addWidget(new QLabel("Sigma C1"),             ir, 3, Qt::AlignLeft);
    1063   pppLayout2->addWidget(_pppWidgets._sigmaC1,               ir, 4); _pppWidgets._sigmaC1->setMaximumWidth(8*ww);
    1064   pppLayout2->addItem(new QSpacerItem(8*ww, 0),             ir, 5);
    1065   pppLayout2->addWidget(new QLabel("Sigma L1"),             ir, 6, Qt::AlignLeft);
    1066   pppLayout2->addWidget(_pppWidgets._sigmaL1,               ir, 7); _pppWidgets._sigmaL1->setMaximumWidth(8*ww);
    1067   ++ir;
    1068   pppLayout2->addWidget(new QLabel("GLONASS LCs"),          ir, 0, Qt::AlignLeft);
    1069   pppLayout2->addWidget(_pppWidgets._lcGLONASS,             ir, 1);
    1070   pppLayout2->addWidget(new QLabel("Max Res C1"),           ir, 3, Qt::AlignLeft);
    1071   pppLayout2->addWidget(_pppWidgets._maxResC1,              ir, 4); _pppWidgets._maxResC1->setMaximumWidth(8*ww);
    1072   pppLayout2->addWidget(new QLabel("Max Res L1"),           ir, 6, Qt::AlignLeft);
    1073   pppLayout2->addWidget(_pppWidgets._maxResL1,              ir, 7); _pppWidgets._maxResL1->setMaximumWidth(8*ww);
    1074   ++ir;
    1075   pppLayout2->addWidget(new QLabel("Galileo LCs"),          ir, 0, Qt::AlignLeft);
    1076   pppLayout2->addWidget(_pppWidgets._lcGalileo,             ir, 1);
    1077   pppLayout2->addWidget(new QLabel("Ele Wgt Code"),         ir, 3, Qt::AlignLeft);
    1078   pppLayout2->addWidget(_pppWidgets._eleWgtCode,            ir, 4);
    1079   pppLayout2->addWidget(new QLabel("Ele Wgt Phase"),        ir, 6, Qt::AlignLeft);
    1080   pppLayout2->addWidget(_pppWidgets._eleWgtPhase,           ir, 7);
    1081   ++ir;
    1082   pppLayout2->addWidget(new QLabel("BDS LCs"),              ir, 0, Qt::AlignLeft);
    1083   pppLayout2->addWidget(_pppWidgets._lcBDS,                 ir, 1);
    1084   pppLayout2->addWidget(new QLabel("Min # of Obs"),         ir, 3, Qt::AlignLeft);
    1085   pppLayout2->addWidget(_pppWidgets._minObs,                ir, 4);
    1086   pppLayout2->addWidget(new QLabel("Min Elevation"),        ir, 6, Qt::AlignLeft);
    1087   pppLayout2->addWidget(_pppWidgets._minEle,                ir, 7);_pppWidgets._minEle->setMaximumWidth(8*ww);
    1088   ++ir;
    1089 #ifdef USE_PPP
    1090   pppLayout2->addWidget(new QLabel("Constraints"),          ir, 0, Qt::AlignLeft);
    1091   pppLayout2->addWidget(_pppWidgets._constraints,           ir, 1);
    1092   pppLayout2->addWidget(new QLabel("Sigma GIM"),            ir, 3, Qt::AlignLeft);
    1093   pppLayout2->addWidget(_pppWidgets._sigmaGIM,              ir, 4); _pppWidgets._sigmaGIM->setMaximumWidth(8*ww);
    1094 #endif
    1095   pppLayout2->addItem(new QSpacerItem(8*ww, 0),             ir, 5);
    1096   pppLayout2->addWidget(new QLabel("Wait for clock corr."), ir, 6, Qt::AlignLeft);
    1097   pppLayout2->addWidget(_pppWidgets._corrWaitTime,          ir, 7);
    1098   ++ir;
    1099   pppLayout2->addItem(new QSpacerItem(8*ww, 0),             ir, 2);
    1100 #ifdef USE_PPP
    1101   pppLayout2->addWidget(new QLabel("Max Res GIM"),          ir, 3, Qt::AlignLeft);
    1102   pppLayout2->addWidget(_pppWidgets._maxResGIM,             ir, 4); _pppWidgets._maxResGIM->setMaximumWidth(8*ww);
    1103 #endif
    1104   pppLayout2->addWidget(new QLabel("Seeding (sec)"),        ir, 6, Qt::AlignLeft);
    1105   pppLayout2->addWidget(_pppWidgets._seedingTime,           ir, 7);_pppWidgets._seedingTime->setMaximumWidth(8*ww);
    1106   ++ir;
    1107   pppLayout2->addWidget(new QLabel(""),                     ir, 8);
    1108   pppLayout2->setColumnStretch(8, 999);
    1109   ++ir;
    1110   pppLayout2->addWidget(new QLabel(""),                     ir, 1);
    1111   pppLayout2->setRowStretch(ir, 999);
    1112 
    1113   pppGroup2->setLayout(pppLayout2);
    1114 
    1115   QVBoxLayout* pppLayout3 = new QVBoxLayout();
    1116   pppLayout3->addWidget(new QLabel("Precise Point Positioning - Processed Stations.<br>"));
    1117   pppLayout3->addWidget(_pppWidgets._staTable, 99);
    1118   QHBoxLayout* pppLayout3sub = new QHBoxLayout();
    1119   pppLayout3sub->addWidget(_pppWidgets._addStaButton);
    1120   pppLayout3sub->addWidget(_pppWidgets._delStaButton);
    1121   pppLayout3sub->addStretch(99);
    1122 
    1123   pppLayout3->addLayout(pppLayout3sub);
    1124 
    1125   pppGroup3->setLayout(pppLayout3);
    1126 
    1127   // ------------------------
    1128   connect(_pppWidgets._mapWinButton, SIGNAL(clicked()), SLOT(slotMapPPP()));
    1129   _pppWidgets._mapSpeedSlider->setMinimumWidth(33*ww);
    1130   _pppWidgets._audioResponse->setMaximumWidth(8*ww);
    1131 
    1132   QGridLayout* pppLayout4 = new QGridLayout();
    1133   ir = 0;
    1134   pppLayout4->addWidget(new QLabel("Precise Point Positioning - Plots.<br>"), ir, 0, 1, 50, Qt::AlignLeft);
    1135   ++ir;
    1136   pppLayout4->addWidget(new QLabel("PPP Plot"),                          ir, 0, Qt::AlignLeft);
    1137   pppLayout4->addWidget(_pppWidgets._plotCoordinates,                    ir, 1, Qt::AlignLeft);
    1138   pppLayout4->addWidget(new QLabel("Mountpoint"),                        ir, 2, 1, 10, Qt::AlignLeft);
    1139   pppLayout4->addWidget(_pppWidgets._audioResponse,                      ir, 4, Qt::AlignLeft);
    1140   pppLayout4->addWidget(new QLabel("Audio response"),                    ir, 5, Qt::AlignRight);
    1141   ++ir;
    1142   pppLayout4->addWidget(new QLabel("Track map"),                         ir, 0, Qt::AlignLeft);
    1143   pppLayout4->addWidget(_pppWidgets._mapWinButton,                       ir, 1, Qt::AlignLeft);
    1144   ++ir;
    1145   pppLayout4->addWidget(new QLabel("Dot-properties"),                    ir, 0, Qt::AlignLeft);
    1146   pppLayout4->addWidget(_pppWidgets._mapWinDotSize,                      ir, 1, Qt::AlignLeft);
    1147   pppLayout4->addWidget(new QLabel("Size    "),                          ir, 2, Qt::AlignLeft);
    1148   pppLayout4->addWidget(_pppWidgets._mapWinDotColor,                     ir, 3, Qt::AlignLeft);
    1149   pppLayout4->addWidget(new QLabel("Color"),                             ir, 4, Qt::AlignLeft);
    1150   ++ir;
    1151   pppLayout4->addWidget(new QLabel("Post-processing speed"),             ir, 0, Qt::AlignLeft);
    1152   pppLayout4->addWidget(_pppWidgets._mapSpeedSlider,                     ir, 1, 1, 20, Qt::AlignLeft);
    1153   ++ir;
    1154   pppLayout4->addWidget(new QLabel(""),                                  ir, 1);
    1155   pppLayout4->setRowStretch(ir, 999);
    1156 
    1157   pppGroup4->setLayout(pppLayout4);
    1158 
    1159   // Reqc Processing
    1160   // ---------------
    1161   _reqcActionComboBox = new QComboBox();
    1162   _reqcActionComboBox->setEditable(false);
    1163   _reqcActionComboBox->addItems(QString(",Edit/Concatenate,Analyze").split(","));
    1164   int ip = _reqcActionComboBox->findText(settings.value("reqcAction").toString());
    1165   if (ip != -1) {
    1166     _reqcActionComboBox->setCurrentIndex(ip);
    1167   }
    1168   connect(_reqcActionComboBox, SIGNAL(currentIndexChanged(const QString &)),
    1169           this, SLOT(slotBncTextChanged()));
    1170 
    1171   QGridLayout* reqcLayout = new QGridLayout;
    1172   _reqcActionComboBox->setMinimumWidth(15*ww);
    1173   _reqcActionComboBox->setMaximumWidth(20*ww);
    1174 
    1175   _reqcObsFileChooser = new qtFileChooser(0, qtFileChooser::Files);
    1176   _reqcObsFileChooser->setFileName(settings.value("reqcObsFile").toString());
    1177 
    1178   _reqcNavFileChooser = new qtFileChooser(0, qtFileChooser::Files);
    1179   _reqcNavFileChooser->setFileName(settings.value("reqcNavFile").toString());
    1180   _reqcOutObsLineEdit = new QLineEdit(settings.value("reqcOutObsFile").toString());
    1181   _reqcOutNavLineEdit = new QLineEdit(settings.value("reqcOutNavFile").toString());
    1182   _reqcOutLogLineEdit = new QLineEdit(settings.value("reqcOutLogFile").toString());
    1183   _reqcPlotDirLineEdit = new QLineEdit(settings.value("reqcPlotDir").toString());
    1184   _reqcSkyPlotSignals = new QLineEdit(settings.value("reqcSkyPlotSignals").toString());
    1185 
    1186   connect(_reqcSkyPlotSignals, SIGNAL(textChanged(const QString &)),
    1187           this, SLOT(slotBncTextChanged()));
    1188 
    1189   _reqcLogSummaryOnly = new QCheckBox();
    1190   _reqcLogSummaryOnly->setCheckState(Qt::CheckState(settings.value("reqcLogSummaryOnly").toInt()));
    1191 
    1192   ir = 0;
    1193   reqcLayout->addWidget(new QLabel("RINEX file editing, concatenation and quality check.<br>"),ir, 0, 1, 8);
    1194   ++ir;
    1195   reqcLayout->addWidget(new QLabel("Action"),                    ir, 0);
    1196   reqcLayout->addWidget(_reqcActionComboBox,                     ir, 1);
    1197   _reqcEditOptionButton = new QPushButton("Set Edit Options");
    1198   _reqcEditOptionButton->setMinimumWidth(15*ww);
    1199   _reqcEditOptionButton->setMaximumWidth(20*ww);
    1200 
    1201   reqcLayout->addWidget(_reqcEditOptionButton,                   ir, 3);
    1202   ++ir;
    1203   reqcLayout->addWidget(new QLabel("Input files (full path)"),   ir, 0);
    1204   reqcLayout->addWidget(_reqcObsFileChooser,                     ir, 1);
    1205   _reqcObsFileChooser->setMaximumWidth(40*ww);
    1206   reqcLayout->addWidget(new QLabel("  Obs"),                     ir, 2);
    1207   reqcLayout->addWidget(_reqcNavFileChooser,                     ir, 3);
    1208   _reqcNavFileChooser->setMaximumWidth(40*ww);
    1209   reqcLayout->addWidget(new QLabel("  Nav"),                     ir, 4);
    1210   ++ir;
    1211   reqcLayout->addWidget(new QLabel("Output file (full path)"),   ir, 0);
    1212   reqcLayout->addWidget(_reqcOutObsLineEdit,                     ir, 1);
    1213   _reqcOutObsLineEdit->setMaximumWidth(40*ww);
    1214   reqcLayout->addWidget(new QLabel("  Obs"),                     ir, 2);
    1215   reqcLayout->addWidget(_reqcOutNavLineEdit,                     ir, 3);
    1216   _reqcOutNavLineEdit->setMaximumWidth(40*ww);
    1217   reqcLayout->addWidget(new QLabel("  Nav"),                     ir, 4);
    1218   ++ir;
    1219   reqcLayout->addWidget(new QLabel("Logfile"),                   ir, 0);
    1220   reqcLayout->addWidget(_reqcOutLogLineEdit,                     ir, 1);
    1221   _reqcOutLogLineEdit->setMaximumWidth(40*ww);
    1222   reqcLayout->addWidget(new QLabel("  Summary only"),            ir, 2);
    1223   reqcLayout->addWidget(_reqcLogSummaryOnly,                     ir, 3);
    1224   ++ir;
    1225   reqcLayout->addWidget(new QLabel("Plots for signals"),         ir, 0);
    1226   reqcLayout->addWidget(_reqcSkyPlotSignals,                     ir, 1);
    1227   _reqcSkyPlotSignals->setMaximumWidth(40*ww);
    1228   ++ir;
    1229   reqcLayout->addWidget(new QLabel("Directory for plots"),       ir, 0);
    1230   reqcLayout->addWidget(_reqcPlotDirLineEdit,                    ir, 1);
    1231   _reqcPlotDirLineEdit->setMaximumWidth(40*ww);
    1232   ++ir;
    1233   reqcLayout->setRowStretch(ir, 999);
    1234 
    1235   reqcLayout->setColumnMinimumWidth(2, 8*ww);
    1236   reqcLayout->setColumnMinimumWidth(4, 8*ww);
    1237 
    1238   reqcgroup->setLayout(reqcLayout);
    1239 
    1240   connect(_reqcEditOptionButton, SIGNAL(clicked()),
    1241           this, SLOT(slotReqcEditOption()));
    1242 
    1243   QGridLayout* sp3CompLayout = new QGridLayout;
    1244 
    1245   _sp3CompFileChooser = new qtFileChooser(0, qtFileChooser::Files);
    1246   _sp3CompFileChooser->setFileName(settings.value("sp3CompFile").toString());
    1247   _sp3CompFileChooser->setMinimumWidth(15*ww);
    1248   _sp3CompFileChooser->setMaximumWidth(40*ww);
    1249 
    1250   _sp3CompExclude = new QLineEdit(settings.value("sp3CompExclude").toString());
    1251   _sp3CompExclude->setMinimumWidth(18*ww);
    1252   _sp3CompExclude->setMaximumWidth(18*ww);
    1253 
    1254   _sp3CompLogLineEdit = new QLineEdit(settings.value("sp3CompOutLogFile").toString());
    1255   _sp3CompLogLineEdit->setMinimumWidth(18*ww);
    1256   _sp3CompLogLineEdit->setMaximumWidth(18*ww);
    1257 
    1258   _sp3CompSummaryOnly = new QCheckBox();
    1259   _sp3CompSummaryOnly->setCheckState(Qt::CheckState(settings.value("sp3CompSummaryOnly").toInt()));
    1260 
    1261   ir = 0;
    1262   sp3CompLayout->addWidget(new QLabel("Orbit and clock comparison.<br>"),  ir, 0, 1, 40);
    1263   ++ir;
    1264   sp3CompLayout->addWidget(new QLabel("Input SP3 files (full path)"),  ir, 0, Qt::AlignLeft);
    1265   sp3CompLayout->addWidget(_sp3CompFileChooser,                        ir, 1, 1, 20);
    1266   ++ir;
    1267   sp3CompLayout->addWidget(new QLabel("Exclude satellites"),           ir, 0, Qt::AlignLeft);
    1268   sp3CompLayout->addWidget(_sp3CompExclude,                            ir, 1, Qt::AlignRight);
    1269   ++ir;
    1270   sp3CompLayout->addWidget(new QLabel("Logfile"),                      ir, 0, Qt::AlignLeft);
    1271   sp3CompLayout->addWidget(_sp3CompLogLineEdit,                        ir, 1, Qt::AlignRight);
    1272   ++ir;
    1273   sp3CompLayout->addWidget(new QLabel("Summary only"),                 ir, 0);
    1274   sp3CompLayout->addWidget(_sp3CompSummaryOnly,                        ir, 1);
    1275   ++ir;
    1276   sp3CompLayout->addWidget(new QLabel(""),                             ir, 1);
    1277   ++ir;
    1278   sp3CompLayout->setRowStretch(ir, 999);
    1279 
    1280   sp3CompLayout->setColumnMinimumWidth(2, 8*ww);
    1281   sp3CompLayout->setColumnMinimumWidth(4, 8*ww);
    1282 
    1283   sp3CompGroup->setLayout(sp3CompLayout);
    1284 
    1285   connect(_sp3CompFileChooser, SIGNAL(fileNameChanged(const QString &)),
    1286           this, SLOT(slotBncTextChanged()));
    1287 
    1288   // Combine Corrections
    1289   // -------------------
    1290   QGridLayout* cmbLayout = new QGridLayout;
    1291 
    1292   populateCmbTable();
    1293   cmbLayout->addWidget(_cmbTable,                                                0, 0, 8, 10);
    1294   cmbLayout->addWidget(new QLabel(" Combine Broadcast Correction streams"),      0, 10, 1, 10);
    1295   cmbLayout->addWidget(addCmbRowButton,                                          1, 10);
    1296   cmbLayout->addWidget(delCmbRowButton,                                          1, 11);
    1297   cmbLayout->addWidget(new QLabel("Method"),                                     2, 10, Qt::AlignLeft);
    1298   cmbLayout->addWidget(_cmbMethodComboBox,                                       2, 11);
    1299   cmbLayout->addWidget(new QLabel("BSX File"),                                   3, 10, Qt::AlignLeft);
    1300   cmbLayout->addWidget(_cmbBsxFile,                                              3, 11, Qt::AlignRight);
    1301   cmbLayout->addWidget(new QLabel("Max Clk Residual"),                           4, 10, Qt::AlignLeft);
    1302   cmbLayout->addWidget(_cmbMaxresLineEdit,                                       4, 11, Qt::AlignRight);
    1303   cmbLayout->addWidget(new QLabel("Max Orb Displacement"),                       5, 10, Qt::AlignLeft);
    1304   cmbLayout->addWidget(_cmbMaxdisplacementLineEdit,                              5, 11, Qt::AlignRight);
    1305   cmbLayout->addWidget(new QLabel("Logfile directory"),                          6, 10, Qt::AlignLeft);
    1306   cmbLayout->addWidget(_cmbLogPath,                                              6, 11, Qt::AlignRight);
    1307   cmbLayout->addWidget(new QLabel("Sampling"),                                   7, 10, Qt::AlignLeft);
    1308   cmbLayout->addWidget(_cmbSamplSpinBox,                                         7, 11, Qt::AlignRight);
    1309 
    1310 
    1311   cmbLayout->addWidget(new QLabel("GNSS"),                                       0, 14, Qt::AlignLeft);
    1312   cmbLayout->addWidget(new QLabel("GPS (C1W/C2W)"),                              1, 14);
    1313   cmbLayout->addWidget(_cmbGpsCheckBox,                                          1, 15);
    1314 
    1315   cmbLayout->addWidget(new QLabel("GLONASS (C1P/C2P)"),                          2, 14);
    1316   cmbLayout->addWidget(_cmbGloCheckBox,                                          2, 15);
    1317 
    1318   cmbLayout->addWidget(new QLabel("Galileo (C1C/C5Q)"),                          3, 14);
    1319   cmbLayout->addWidget(_cmbGalCheckBox,                                          3, 15);
    1320 
    1321   cmbLayout->addWidget(new QLabel("Beidou (C2I/C6I)"),                           4, 14);
    1322   cmbLayout->addWidget(_cmbBdsCheckBox,                                          4, 15);
    1323 
    1324   cmbLayout->addWidget(new QLabel("QZSS (C1C/C2L)"),                             5, 14);
    1325   cmbLayout->addWidget(_cmbQzssCheckBox,                                         5, 15);
    1326 
    1327   cmbLayout->addWidget(new QLabel("SBAS (C1C/C5Q)"),                             6, 14);
    1328   cmbLayout->addWidget(_cmbSbasCheckBox,                                         6, 15);
    1329 
    1330   cmbLayout->addWidget(new QLabel("NavIC"),                                      7, 14);
    1331   cmbLayout->addWidget(_cmbNavicCheckBox,                                        7, 15);
    1332   cmbLayout->setRowStretch(9, 999);
    1333 
    1334   connect(addCmbRowButton, SIGNAL(clicked()), this, SLOT(slotAddCmbRow()));
    1335   connect(delCmbRowButton, SIGNAL(clicked()), this, SLOT(slotDelCmbRow()));
    1336 
    1337   cmbgroup->setLayout(cmbLayout);
    1338 
    1339   // Upload Layout (Clocks)
    1340   // ----------------------
    1341   QGridLayout* uploadHlpLayout = new QGridLayout();
    1342 
    1343   connect(addUploadRowButton, SIGNAL(clicked()), this, SLOT(slotAddUploadRow()));
    1344   connect(delUploadRowButton, SIGNAL(clicked()), this, SLOT(slotDelUploadRow()));
    1345   connect(setUploadTrafoButton, SIGNAL(clicked()), this, SLOT(slotSetUploadTrafo()));
    1346 
    1347   uploadHlpLayout->addWidget(addUploadRowButton,                  0, 0);
    1348   uploadHlpLayout->addWidget(delUploadRowButton,                  0, 1);
    1349   uploadHlpLayout->addWidget(new QLabel("Interval"),              0, 2, Qt::AlignRight);
    1350   uploadHlpLayout->addWidget(_uploadIntrComboBox,                 0, 3);
    1351   uploadHlpLayout->addWidget(new QLabel("     Sampling:    Orb"), 0, 4, Qt::AlignRight);
    1352   uploadHlpLayout->addWidget(_uploadSamplRtcmEphCorrSpinBox,      0, 5);
    1353   uploadHlpLayout->addWidget(new QLabel("SP3"),                   0, 6, Qt::AlignRight);
    1354   uploadHlpLayout->addWidget(_uploadSamplSp3ComboBox,             0, 7);
    1355   uploadHlpLayout->addWidget(new QLabel("RNX"),                   0, 8, Qt::AlignRight);
    1356   uploadHlpLayout->addWidget(_uploadSamplClkRnxSpinBox,           0, 9);
    1357   uploadHlpLayout->addWidget(new QLabel("BSX"),                   0,10, Qt::AlignRight);
    1358   uploadHlpLayout->addWidget(_uploadSamplBiaSnxSpinBox,           0,11);
    1359   uploadHlpLayout->addWidget(setUploadTrafoButton,                0,12);
    1360   uploadHlpLayout->addWidget(new QLabel("ANTEX file"),            1, 0, Qt::AlignLeft);
    1361   uploadHlpLayout->addWidget(_uploadAntexFile,                    1, 1, 1, 4);
    1362 
    1363   QBoxLayout* uploadLayout = new QBoxLayout(QBoxLayout::TopToBottom);
    1364   populateUploadTable();
    1365 
    1366   uploadLayout->addWidget(new QLabel("Upload RTCM Version 3 Broadcast Corrections to caster.<br>"));
    1367   uploadLayout->addWidget(_uploadTable);
    1368   uploadLayout->addLayout(uploadHlpLayout);
    1369 
    1370   uploadgroup->setLayout(uploadLayout);
    1371 
    1372   // Upload Layout (Ephemeris)
    1373   // -------------------------
    1374   QGridLayout* uploadHlpLayoutEph = new QGridLayout();
    1375 
    1376   connect(addUploadEphRowButton, SIGNAL(clicked()), this, SLOT(slotAddUploadEphRow()));
    1377   connect(delUploadEphRowButton, SIGNAL(clicked()), this, SLOT(slotDelUploadEphRow()));
    1378 
    1379   uploadHlpLayoutEph->addWidget(addUploadEphRowButton,               0, 0);
    1380   uploadHlpLayoutEph->addWidget(delUploadEphRowButton,               0, 1);
    1381   uploadHlpLayoutEph->addWidget(new QLabel("     Sampling"),         0, 2, Qt::AlignRight);
    1382   uploadHlpLayoutEph->addWidget(_uploadSamplRtcmEphSpinBox,          0, 3);
    1383 
    1384   QBoxLayout* uploadLayoutEph = new QBoxLayout(QBoxLayout::TopToBottom);
    1385   populateUploadEphTable();
    1386 
    1387   uploadLayoutEph->addWidget(new QLabel("Upload concatenated RTCMv3 Broadcast Ephemeris to caster.<br>"));
    1388   uploadLayoutEph->addWidget(_uploadEphTable);
    1389   uploadLayoutEph->addLayout(uploadHlpLayoutEph);
    1390 
    1391   uploadEphgroup->setLayout(uploadLayoutEph);
    1392 
    1393 
    1394   // Main Layout
    1395   // -----------
    1396   QGridLayout* mLayout = new QGridLayout;
    1397   _aogroup->setCurrentIndex(settings.value("startTab").toInt());
    1398   mLayout->addWidget(_aogroup,            0,0);
    1399   mLayout->addWidget(_mountPointsTable,   1,0);
    1400   _loggroup->setCurrentIndex(settings.value("statusTab").toInt());
    1401   mLayout->addWidget(_loggroup,           2,0);
    1402 
    1403   _canvas->setLayout(mLayout);
    1404 
    1405   // WhatsThis, Network
    1406   // ------------------
    1407   _proxyHostLineEdit->setWhatsThis(tr("<p>If you are running BNC within a protected Local Area Network (LAN), you may 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. Without any entry, BNC will try to use the system proxies. </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 this is not possible, you may need to run BNC outside your LAN on a network that has unobstructed connection to the Internet. <i>[key: proxyHost]</i></p>"));
    1408   _proxyPortLineEdit->setWhatsThis(tr("<p>Enter your proxy server port number in case a proxy is operated in front of BNC. <i>[key: proxyPort]</i></p>"));
    1409   _sslCaCertPathLineEdit->setWhatsThis(tr("<p>Communication with an Ntrip Broadcaster over SSL requires the exchange of server certificates. Specify the path to a directory where you save CA certificates on your system. </p><p>BNC creates from *.crt and *.pem files a CA certificate database, which is used by the socket during the handshake phase to validate the peer's certificate. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslCaCertPath]</i></p>"));
    1410   _sslClientCertPathLineEdit->setWhatsThis(tr("<p>Two-sided communication with an Ntrip Broadcaster over SSL requires in addition the exchange of client certificates. Specify the full path to the client certificates on your system.</p><p></p><p>The file naming convention for client certificates in BNC is as follows: &lt;hostname&gt;.&lt;port&gt;.crt for the certificate and &lt;hostname&gt;.&lt;port&gt;.key for the private key, where &lt;hostname&gt; is without https://. </p><p> If available, the client or personal authentication certificate is presented to the peer during the SSL handshake process. Password protected key files are not supported. </p><p>Don't try communication via two sided SSL if you are not sure whether this is supported by the involved Ntrip Broadcaster. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslClientCertPath]</i></p>"));
    1411   _sslIgnoreErrorsCheckBox->setWhatsThis(tr("<p>SSL communication may involve queries coming from the Ntrip Broadcaster. Tick 'Ignore SSL authorization errors' if you don't want to be bothered with this. <i>[key: sslIgnoreErrors]</i></p>"));
    1412 
    1413   // WhatsThis, General
    1414   // ------------------
    1415   _logFileLineEdit->setWhatsThis(tr("<p>Records of BNC's activities are shown in the 'Log' tab on the bottom of this window. They can be saved into a file when a valid path for that is specified in the 'Logfile (full path)' field.</p><p>The logfile name will automatically be extended by a string '_YYMMDD' carrying the current date. <i>[key: logFile]</i></p>"));
    1416   _rnxAppendCheckBox->setWhatsThis(tr("<p>When BNC is started, new files are created by default and file content already available under the same name will be overwritten. However, users might want to append already existing files following a regular restart or a crash of BNC or its platform.</p><p>Tick 'Append files' to continue with existing files and keep what has been recorded so far. <i>[key: rnxAppend]</i></p>"));
    1417   _onTheFlyComboBox->setWhatsThis(tr("<p>When operating BNC online in 'no window' mode, some configuration parameters can be changed on-the-fly without interrupting the running process. For that BNC rereads parts of its configuration in pre-defined intervals. The default entry is 'no' that means the reread function is switched of. <p></p>Select '1 min', '5 min', '1 hour', or '1 day' to force BNC to reread its configuration every full minute, five minutes, hour, or day and let in between edited configuration options become effective on-the-fly without terminating uninvolved threads.</p><p>Note that when operating BNC in window mode, on-the-fly changeable configuration options become effective immediately via button 'Save & Reread Configuration'. <i>[key: onTheFlyInterval]</i></p>"));
    1418   _autoStartCheckBox->setWhatsThis(tr("<p>Tick 'Auto start' for auto-start of BNC at startup time in window mode with preassigned processing options. <i>[key: autoStart]</i></p>"));
    1419   _rawOutFileLineEdit->setWhatsThis(tr("<p>Save all data coming in through various streams in the received order and format in one file.</p><p>This option is primarily meant for debugging purposes. <i>[key: rawOutFile]</i></p>"));
    1420 
    1421   // WhatsThis, RINEX Observations
    1422   // -----------------------------
    1423   _rnxPathLineEdit->setWhatsThis(tr("<p>Here you specify the path to where the RINEX Observation files will be stored.</p><p>If the specified directory does not exist, BNC will not create RINEX Observation files. <i>[key: rnxPath]</i></p>"));
    1424   _rnxIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Observation file. <i>[key: rnxIntr]</i></p>"));
    1425   _rnxSamplComboBox->setWhatsThis(tr("<p>Select the RINEX Observation sampling interval in seconds. <i>[key: rnxSampl]</i></p>"));
    1426   _rnxSkelExtComboBox->setWhatsThis(tr("<p>BNC allows using personal RINEX skeleton files that contain the RINEX header records you would like to include. You can derive a skeleton file from information given in an up to date sitelog.</p><p>A file in the RINEX Observations 'Directory' with a 'Skeleton extension' skl or SKL is interpreted by BNC as a personal RINEX header skeleton file for the corresponding stream. <i>[key: rnxSkel]</i></p>"));
    1427   _rnxSkelPathLineEdit->setWhatsThis(tr("<p>Here you specify the path to where local skeleton files are located.</p><p> If no directory is specified, the path is assumed to where the RINEX Observation files will stored. <i>[key: rnxSkelPath]</i></p>"));
    1428   _rnxFileCheckBox->setWhatsThis(tr("<p>Tick check box 'Skeleton mandatory' in case you want that RINEX files are only produced if skeleton files are available for BNC. If no skeleton file is available for a particular source then no RINEX Observation file will be produced from the affected stream.</p><p>Note that a skeleton file contains RINEX header information such as receiver and antenna types. In case of stream conversion to RINEX Version 3, a skeleton file should also contain information on potentially available observation types. A missing skeleton file will therefore enforce BNC to only save a default set of RINEX 3 observation types. <i>[key: rnxOnlyWithSKL]</i></p>"));
    1429   _rnxScrpLineEdit->setWhatsThis(tr("<p>Whenever a RINEX Observation file is finally saved, you may want to compress, copy or upload it immediately, for example via FTP. BNC allows you to execute a script/batch file to carry out such operation.</p><p>Specify the full path of a script or batch file. BNC will pass the full RINEX Observation file path to the script as command line parameter (%1 on Windows systems, $1 on Unix/Linux/Mac systems). <i>[key: rnxScript]</i></p>"));
    1430   _rnxV2Priority->setWhatsThis(tr("<p>Specify a priority list of characters defining signal attributes as defined in RINEX Version 3. Priorities will be used to map observations with RINEX Version 3 attributes from incoming streams to Version 2. The underscore character '_' stands for undefined attributes. A question mark '?' can be used as wildcard which represents any one character.</p><p>Signal priorities can be specified as equal for all systems, as system specific or as system and freq. specific. For example: </li><ul><li>'CWPX_?' (General signal priorities valid for all GNSS) </li><li>'I:ABCX' (System specific signal priorities for NavIC) </li><li>'G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX' (System and frequency specific signal priorities) </li></ul>Default is the following priority list 'G:12&PWCSLX G:5&IQX R:12&PC R:3&IQX R:46&ABX E:16&BCXZ E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:267&IQX C:18&DPX I:ABCX S:1&C S:5&IQX'. <i>[key: rnxV2Priority]</i></p>"));
    1431   _rnxVersComboBox->setWhatsThis(tr("<p>Select the format for RINEX Observation files. <i>[key: rnxVersion]</i></p>"));
    1432 
    1433   // WhatsThis, RINEX Ephemeris
    1434   // --------------------------
    1435   _ephPathLineEdit->setWhatsThis(tr("<p>Specify the path for saving Broadcast Ephemeris data as RINEX Navigation files.</p><p>If the specified directory does not exist, BNC will not create RINEX Navigation files. <i>[key: ephPath]</i></p>"));
    1436   _ephIntrComboBox->setWhatsThis(tr("<p>Select the length of the RINEX Navigation file. <i>[key: ephIntr]</i></p>"));
    1437   _ephOutPortLineEdit->setWhatsThis(tr("<p>BNC can produce ephemeris data in RINEX Navigation ASCII format on your local host through an IP port.</p><p>Specify a port number here to activate this function. <i>[key: ephOutPort]</i></p>"));
    1438   _ephVersComboBox->setWhatsThis(tr("<p>Select the format for RINEX Navigation files. <i>[key: ephVersion]</i></p>"));
    1439   //_ephFilePerStation->setWhatsThis(tr("<p>By default, all received Broadcast Ephemeris data will be stored within one File. Thick 'File per Stations' to get separate files per station/mountpoint. <i>[key: ephFilePerStation]</i></p>"));
    1440 
    1441   // WhatsThis, RINEX Editing & QC
    1442   // -----------------------------
    1443   _reqcActionComboBox->setWhatsThis(tr("<p>BNC allows to 'Edit or Concatenate' RINEX Version 2 or 3 files or to perform a Quality Check (QC) and 'Analyze' data following UNAVCO's famous 'teqc' program. <i>[key: reqcAction]</i></p>"));
    1444   _reqcEditOptionButton->setWhatsThis(tr("<p>Specify options for editing RINEX Version 2 or 3 files.</p>"));
    1445   _reqcObsFileChooser->setWhatsThis(tr("<p>Specify the full path to input observation files in RINEX Version 2 or 3 format.</p><p>Note that when in 'Analyze' mode, specifying at least one RINEX observation file is mandatory. <i>[key: reqcObsFile]</i></p>"));
    1446   _reqcNavFileChooser->setWhatsThis(tr("<p>Specify the full path to input navigation files in RINEX Version 2 or 3 format.</p><p>Note that when in 'Analyze' mode, specifying at least one RINEX navigation file is mandatory. <i>[key: reqcNavFile]</i></p>"));
    1447   _reqcOutObsLineEdit->setWhatsThis(tr("<p>Specify the full path to a RINEX Observation output file.</p><p>Default is an empty option field, meaning that no RINEX Observation output file will be produced. <i>[key: reqcOutObsFile]</i></p>"));
    1448   _reqcOutNavLineEdit->setWhatsThis(tr("<p>Specify the full path to a RINEX Navigation output file.</p><p>Default is an empty option field, meaning that no RINEX Navigation output file will be produced. <i>[key: reqcOutNavFile]</i></p>"));
    1449   _reqcOutLogLineEdit->setWhatsThis(tr("<p>Specify the full path to a logfile.</p><p>Default is an empty option field, meaning that no 'RINEX Editing & QC' logfile will be produced. <i>[key: reqcOutLogFile]</i></p>"));
    1450   _reqcLogSummaryOnly->setWhatsThis(tr("<p>By default BNC produces a detailed 'Logfile' providing all information resulting from editing or analyzing RINEX data. If that is too much information, you can limit the logfile content to a short summary.</p><p>Tick 'Summary only' to suppress full logfile output and instead produce a logfile containing only summary information. <i>[key: reqcLogSummaryOnly]</i></p>"));
    1451   _reqcPlotDirLineEdit->setWhatsThis(tr("<p>Specify a directory for saving plots in PNG format.</p><p>Default is an empty option field, meaning that plots will not be saved on disk. <i>[key: reqcPlotDir]</i></p>"));
    1452   _reqcSkyPlotSignals->setWhatsThis(tr("<p>BNC can produce plots for multipath, signal-to-noise ratio, satellite availability, satellite elevation, and PDOP values. The 'Plots for signals' option lets you exactly specify observation signals to be used for that and also enables the plot generation. You can specify the navigation system, the frequency, and the tracking mode or channel as defined in RINEX Version 3. Specifications for frequency and tracking mode or channel must be separated by ampersand character '&'. Specifications for navigation systems must be separated by blank character ' '.</p><p>Examples for 'Plots for signals' option:<ul><li> G:1&2&5 R:1&2&3 E:1&7 C:2&6 J:1&2 I:5&9 S:1&5 <br>(Plots will be based on GPS observations on 1st and 2nd frequency, GLONASS observations on 1st and 2nd frequency, QZSS observations on 1st and 2nd frequency, Galileo observations on 1st and 7th frequency, BeiDou observations on 1st and 6th frequency, SBAS observations on 1st frequency.)</li><li>G:1C&5X<br>(Plots will be based on GPS observations on 1st frequency in C tracking mode and GPS observations on 5th frequency in X tracking mode.)</li><li>C:6I&7I<br>(Plots will be based on BeiDou observations on 6th frequency in I tracking mode and BeiDou observations on 7th frequency in I tracking mode.)<li></ul></p><p>Default is 'G:1&2 R:1&2 E:1&5 C:2&6 J:1&2 I:5&9 S:1&5'. Specifying an empty option string would be overruled by this default. <i>[key: reqcSkyPlotSignals]</i></p>"));
    1453 
    1454   // WhatsThis, SP3 Comparison
    1455   // -------------------------
    1456   _sp3CompFileChooser->setWhatsThis(tr("<p>BNC can compare two SP3 files containing GNSS satellite orbit and clock information.</p></p>Specify the full path to two files with orbits and clocks in SP3 format, separate them by comma. <i>[key: sp3CompFile]</i></p>"));
    1457   _sp3CompExclude->setWhatsThis(tr("<p>Specify satellites to exclude them from orbit and clock comparison. Example:<p>G04,G31,R</p><p>This excludes GPS satellites PRN 4 and 31 as well as all GLONASS satellites from the comparison.</p><p>Default is an empty option field, meaning that no satellite is excluded from the comparison. <i>[key: sp3CompExclude]</i></p>"));
    1458   _sp3CompLogLineEdit->setWhatsThis(tr("<p>Specify the full path to a logfile saving comparison results.</p><p>Specifying a logfile is mandatory. Comparing SP3 files and not saving comparison results on disk would be useless. <i>[key: sp3CompOutLogFile]</i></p>"));
    1459   _sp3CompSummaryOnly->setWhatsThis(tr("<p>By default BNC produces a detailed 'Logfile' providing all information resulting from comparing SP3 files. If that is too much information, you can limit the logfile content to a short summary.</p><p>Tick 'Summary only' to suppress full logfile output and instead produce a logfile containing only summary information. <i>[key: sp3CompSummaryOnly]</i></p>"));
    1460 
    1461   // WhatsThis, Broadcast Corrections
    1462   // --------------------------------
    1463   _corrPathLineEdit->setWhatsThis(tr("<p>Specify a directory for saving Broadcast Ephemeris Correction files.</p><p>If the specified directory does not exist, BNC will not create the files. <i>[key: corrPath]</i></p>"));
    1464   _corrIntrComboBox->setWhatsThis(tr("<p>Select the length of Broadcast Ephemeris Correction files. <i>[key: corrIntr]</i></p>"));
    1465   _corrPortLineEdit->setWhatsThis(tr("<p>BNC can produce Broadcast Ephemeris Corrections on your local host through an IP port.</p><p>Specify a port number here to activate this function. <i>[key: corrPort]</i></p>"));
    1466 
    1467   // WhatsThis, Feed Engine
    1468   // ----------------------
    1469   _outPortLineEdit->setWhatsThis(tr("<p>BNC can produce synchronized observations in a plain ASCII format on your local host via IP port.</p><p>Specify a port number to activate this function. <i>[key: outPort]</i></p>"));
    1470   _outWaitSpinBox->setWhatsThis(tr("<p>When feeding a real-time GNSS network engine waiting for synchronized input epoch by epoch, BNC drops whatever is received later than 'Wait for full obs epoch' seconds.</p><p>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 network engine or product. <i>[key: outWait]</i></p>"));
    1471   _outSamplComboBox->setWhatsThis(tr("<p>Select a synchronized observation sampling interval in seconds. <i>[key: outSampl]</i></p>"));
    1472   _outFileLineEdit->setWhatsThis(tr("<p>Specify the full path to a file where synchronized observations are saved in plain ASCII format.</p><p>Beware that the size of this file can rapidly increase depending on the number of incoming streams. <i>[key: outFile]</i></p>"));
    1473   _outUPortLineEdit->setWhatsThis(tr("<p>BNC can produce unsynchronized observations in a plain ASCII format on your local host via IP port.</p><p>Specify a port number to activate this function. <i>[key: outUPort]</i></p>"));
    1474   _outLockTimeCheckBox->setWhatsThis(tr("<p>Print the lock time in seconds in the feed engine output.<i>[key: outLockTime]</i></p>"));
    1475 
    1476   // WhatsThis, Serial Output
    1477   // ------------------------
    1478   _serialMountPointLineEdit->setWhatsThis(tr("<p>Enter a 'Mountpoint' to forward the corresponding stream to a serial connected receiver.</p><p>Depending on the stream content, the receiver may use it for example for Differential GNSS, Precise Point Positioning or any other purpose supported by its firmware. <i>[key: serialMountPoint]</i></p>"));
    1479   _serialPortNameLineEdit->setWhatsThis(tr("<p>Enter the serial 'Port name' selected for communication with your serial connected receiver. Valid port names are</p><pre>Windows:       COM1, COM2<br>Linux:         /dev/ttyS0, /dev/ttyS1<br>FreeBSD:       /dev/ttyd0, /dev/ttyd1<br>Digital Unix:  /dev/tty01, /dev/tty02<br>HP-UX:         /dev/tty1p0, /dev/tty2p0<br>SGI/IRIX:      /dev/ttyf1, /dev/ttyf2<br>SunOS/Solaris: /dev/ttya, /dev/ttyb</pre><p>Note that before you start BNC, you must plug a serial cable in the port defined here. <i>[key: serialPortName]</i></p>"));
    1480   _serialBaudRateComboBox->setWhatsThis(tr("<p>Select a 'Baud rate' for the serial output link.</p><p>Note that your selection must equal the baud rate configured to the serial connected receiver. Using a high baud rate is recommended. <i>[key: serialBaudRate]</i></p>"));
    1481   _serialFlowControlComboBox->setWhatsThis(tr("<p>Select a 'Flow control' for the serial output link.</p><p>Note that your selection must equal the flow control configured to the serial connected receiver. Select 'OFF' if you don't know better. <i>[key: serialFlowControl]</i></p>"));
    1482   _serialDataBitsComboBox->setWhatsThis(tr("<p>Select the number of 'Data bits' for the serial output link.</p><p>Note that your selection must equal the number of data bits configured to the serial connected receiver. Note further that often 8 data bits are used. <i>[key: serialDataBits]</i></p>"));
    1483   _serialParityComboBox->setWhatsThis(tr("<p>Select a 'Parity' for the serial output link.</p><p>Note that your selection must equal the parity selection configured to the serial connected receiver. The parity is often set to 'NONE'. <i>[key: serialParity]</i></p>"));
    1484   _serialStopBitsComboBox->setWhatsThis(tr("<p>Select the number of 'Stop bits' for the serial output link.</p><p>Note that your selection must equal the number of stop bits configured to the serial connected receiver. Note further that often 1 stop bit is used. <i>[key: serialStopBits]</i></p>"));
    1485   _serialAutoNMEAComboBox->setWhatsThis(tr("<p>The 'NMEA' option supports the so-called 'Virtual Reference Station' (VRS) concept which requires the receiver to send approximate position information to the Ntrip Broadcaster. Select 'no' if you don't want BNC to forward or upload any NMEA message to the Ntrip Broadcaster in support of VRS.</p><p>Select 'Auto' to automatically forward NMEA messages of type GGA from your serial connected receiver to the Ntrip Broadcaster and/or save them in a file.</p><p>Select 'Manual GPGGA' or 'Manual GNGGA' if you want BNC to produce and upload GPGGA or GNGGA NMEA messages to the Ntrip Broadcaster because your serial connected receiver doesn't generate these messages. A Talker ID 'GP' preceding the GGA string stands for GPS solutions while a Talker ID 'GN' stands for multi constellation solutions.</p><p>Note that selecting 'Auto' or 'Manual' works only for VRS streams which show up under the 'Streams' canvas on BNC's main window with 'nmea' stream attribute set to 'yes'. This attribute is either extracted from the Ntrip Broadcaster's source-table or introduced by the user via editing the BNC configuration file. <i>[key: serialAutoNMEA]</i></p>"));
    1486   _serialFileNMEALineEdit->setWhatsThis(tr("<p>Specify the full path to a file where NMEA messages coming from your serial connected receiver are saved.</p><p>Default is an empty option field, meaning that NMEA messages will not be saved on disk. <i>[key: serialFileNMEA]</i></p>"));
    1487   _serialHeightNMEALineEdit->setWhatsThis(tr("<p>Specify an approximate 'Height' above mean sea level in meters for the reference station introduced by option 'Mountpoint'. Together with the latitude and longitude from the source-table, the height information is used to build GGA messages to be sent to the Ntrip Broadcaster.</p><p>For adjusting latitude and longitude values of a VRS stream given in the 'Streams' canvas, you can double click the latitude/longitude data fields, specify appropriate values and then hit Enter.</p><p>This option is only relevant when option 'NMEA' is set to 'Manual GPGGA' or 'Manual GNGGA' respectively. <i>[key: serialHeightNMEA]</i></p>"));
    1488   _serialNMEASamplingSpinBox->setWhatsThis(tr("<p>Select a sampling interval in seconds for manual or receiver generated NMEA GGA sentences and their upload.</p><p>A sampling rate of '0' means, a GGA sentence will be send only once to initialize the requested VRS stream. Note that some VRS systems need GGA sentences at regular intervals. <i>[key: serialNMEASampling]</i></p>"));
    1489 
    1490   // WhatsThis, Outages
    1491   // ------------------
    1492   _adviseObsRateComboBox->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>Default is an empty option field, meaning that you don't want BNC to report on stream failures or recoveries when exceeding a threshold time span. <i>[key: adviseObsRate]</i></p>"));
    1493   _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. <i>[key: adviseFail]</i></p>"));
    1494   _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. <i>[key: adviseReco]</i></p>"));
    1495   _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 a comment 'Begin_Outage', 'End_Outage', 'Begin_Corrupted', or 'End_Corrupted' are passed on to the script as command line parameters.</p><p>The script may have the task to send the advisory notes by email to BNC's operator and/or to the affected stream provider.</p><p>An empty option field (default) or invalid path means that you don't want to use this option. <i>[key: adviseScript]</i></p>"));
    1496 
    1497   // WhatsThis, Miscellaneous
    1498   // ------------------------
    1499   _miscMountLineEdit->setWhatsThis(tr("<p>Specify a mountpoint to apply any of the options shown below. Enter 'ALL' if you want to apply these options to all configured streams.</p><p>An empty option field (default) means that you don't want BNC to apply any of these options. <i>[key: miscMount]</i></p>"));
    1500   _miscIntrComboBox->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' tab at the end of each 'Log latency' interval together with results of a statistical evaluation (approximate number of covered epochs, data gaps).</p><p>Select a 'Log latency' interval or select the empty option field if you do not want BNC to log latencies and statistical information. <i>[key: miscIntr]</i></p>"));
    1501   _miscScanRTCMCheckBox->setWhatsThis(tr("<p>Tick 'Scan RTCM' to log the numbers of incoming message types as well as contained antenna coordinates, antenna height, and antenna descriptor.</p><p>In case of RTCM Version 3 MSM streams, BNC will also log contained RINEX Version 3 observation types. <i>[key: miscScanRTCM]</i></p>"));
    1502   _miscPortLineEdit->setWhatsThis(tr("<p>BNC can output an incoming stream through an IP port of your local host.</p><p>Specify a port number to activate this function. In this case, the stream content remains untouched; BNC does not decode or reformat the data for this output.</p><p> If the decoder string is not an accepted one ('RTCM_2.x', 'RTCM_3.x' and 'RTNET'), please change the decoder string to <ul>"
    1503       "<li> 'ZERO' (forward the raw data) or </li>"
    1504       "<li> 'ZERO2File' (forward and store the raw data)</li> </ul> in addition. <i>[key: miscPort]</i></p>"));
    1505 
    1506   // WhatsThis, PPP (1)
    1507   // ------------------
    1508   _pppWidgets._dataSource->setWhatsThis(tr("<p>Select 'Real-time Streams' for real-time PPP from RTCM streams or 'RINEX Files' for post processing PPP from RINEX files.</p><p><ul><li>Real-time PPP requires that you pull a RTCM stream carrying GNSS observations plus a stream providing corrections to Broadcast Ephemeris. If the observations stream does not contain Broadcast Ephemeris then you must in addition pull a Broadcast Ephemeris stream like 'RTCM3EPH' from Ntrip Broadcaster <u>products.igs-ip.net</u>.<br></li><li>Post processing PPP requires RINEX Observation files, RINEX Navigation files and a file with corrections to Broadcast Ephemeris in plain ASCII format as saved beforehand using BNC.</li></ul></p><p>Note that BNC allows to carry out PPP solutions simultaneously for several stations. <i>[key: PPP/dataSource]</i></p>"));
    1509   _pppWidgets._rinexObs->setWhatsThis(tr("<p>Specify the RINEX Observation file. <i>[key: PPP/rinexObs]</i></p>"));
    1510   _pppWidgets._rinexNav->setWhatsThis(tr("<p>Specify the RINEX Navigation file. <i>[key: PPP/rinexNav]</i></p>"));
    1511   _pppWidgets._corrMount->setWhatsThis(tr("<p>Specify a 'mountpoint' from the 'Streams' canvas below which provides corrections to Broadcast Ephemeris.</p><p>If you don't specify a corrections stream via this option, BNC will fall back to Single Point Positioning (SPP, positioning from observations and Broadcast Ephemeris only) instead of doing PPP. <i>[key: PPP/corrMount]</i></p>"));
    1512   _pppWidgets._ionoMount->setWhatsThis(tr("<p>Specify a 'mountpoint' from the 'Streams' canvas below which provides VTEC informations in SSR format.</p><p>If you don't specify a corrections stream via this option, BNC will use VTEC informations from the Corrections stream 'mountpoint', if available. <i>[key: PPP/ionoMount]</i></p>"));
    1513   _pppWidgets._corrFile->setWhatsThis(tr("<p>Specify the Broadcast Ephemeris Corrections file as saved beforehand using BNC.</p><p>If you don't specify corrections by this option, BNC will fall back to Single Point Positioning (SPP, positioning from RINEX Obs and RINEX Nav files only) instead of doing PPP. <i>[key: PPP/corrFile]</i></p>"));
    1514   _pppWidgets._ionoFile->setWhatsThis(tr("<p>Specify the VTEC file as saved beforehand using BNC.</p><p>If you don't specify corrections by this option, BNC will use VTEC informations from the Corrections file, if available. <i>[key: PPP/ionoFile]</i></p>"));
    1515   _pppWidgets._antexFile->setWhatsThis(tr("<p>Observations in RTCM streams or RINEX files should be referred to the receiver's and to the satellite's Antenna Phase Center (APC) and therefore be corrected for<ul><li>Receiver APC offsets and variations</li><li>Satellite APC offsets and variations.</li></ul> Specify the full path to an IGS 'ANTEX file' which contains APC offsets and variations for satellites and receiver.</p> <i>[key: PPP/antexFile]</i></p>"));
    1516   _pppWidgets._crdFile->setWhatsThis(tr("<p>Enter the full path to an ASCII file which specifies the streams or files of those stations you want to process. Specifying a 'Coordinates file' is optional. If it exists, it should contain one record per station with the following parameters separated by blank character:</p><ul><li>Specify the station either by:<ul><li>the 'Mountpoint' of the station's RTCM stream (in real-time PPP mode), or</li><li>the 9-char station ID of the RINEX Version 3 or 4 Observations file (in post processing PPP mode), or </li><li>the 4-char station ID of the RINEX Version 2 Observations file (in post processing PPP mode).</li></ul><li>Approximate X,Y,Z coordinate of station's Antenna Reference Point [m] (ARP, specify '0.0 0.0 0.0' if unknown).</li><li>North, East and Up component of antenna eccentricity [m] (specify '0.0 0.0 0.0' if unknown). </li><li>20 Characters describing the antenna type and radome following the IGS 'ANTEX file' standard (leave blank if unknown).</li><li>Receiver type following the naming conventions for IGS equipment.</li></ul>Records with exclamation mark '!' in the first column or blank records will be interpreted as comment lines and ignored.. <i>[key: PPP/crdFile]</i></p>"));
    1517   _pppWidgets._blqFile->setWhatsThis(tr("<p>Specify the full path to a 'BLQ file' containing the ocean loading coefficients for different stations. These coefficients can be obtained from the ocean loading service under request trough the web site http://holt.oso.chalmers.se/loading/. <i>[key: PPP/blqFile]</i></p>"));
    1518   _pppWidgets._logPath->setWhatsThis(tr("<p>Specify a directory for saving daily PPP logfiles. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no PPP logfiles shall be produced. <i>[key: PPP/logPath]</i></p>"));
    1519   _pppWidgets._nmeaPath->setWhatsThis(tr("<p>Specify a directory for saving coordinates in daily NMEA files. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no NMEA file shall be produced. <i>[key: PPP/nmeaPath]</i></p>"));
    1520   _pppWidgets._snxtroPath->setWhatsThis(tr("<p>Specify a directory for saving SINEX Troposphere files. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no SINEX Troposphere files shall be produced. <i>[key: PPP/snxtroPath]</i></p>"));
    1521   _pppWidgets._snxtroIntr->setWhatsThis(tr("<p>Select a length for SINEX Troposphere files.</p><p>Default 'SNX TRO interval' for saving SINEX Troposphere files on disk is '1 hour'. <i>[key: PPP/snxtroIntr]</i></p>"));
    1522   _pppWidgets._snxtroSampl->setWhatsThis(tr("<p>Select a 'Sampling' rate for saving troposphere parameters. <i>[key: PPP/snxtroSampl]</i></p>"));
    1523   _pppWidgets._snxtroAc->setWhatsThis(tr("<p>Specify a 3-character abbreviation describing you as the generating Analysis Center (AC) in your SINEX troposphere files. <i>[key: PPP/snxtroAc]</i></p>"));
    1524   _pppWidgets._snxtroSolId->setWhatsThis(tr("<p>Specify a 1-character solution ID to allow a distinction between different solutions per AC. <i>[key: PPP/snxtroSolId]</i></p>"));
    1525   _pppWidgets._snxtroSolType->setWhatsThis(tr("<p>Specify a 3-character solution type, e.g. real-time (RTS), unknown (UNK), .. <i>[key: PPP/snxtroSolType]</i></p>"));
    1526   _pppWidgets._snxtroCampId->setWhatsThis(tr("<p>Specify a 3-character campaign ID, e.g. operational (OPS), demonstration (DEM), testing (TST), .. <i>[key: PPP/snxtroCampId]</i></p>"));
    1527 
    1528   // WhatsThis, PPP (2)
    1529   // ------------------
    1530   _pppWidgets._lcGPS->setWhatsThis(tr("<p>Specify which kind of GPS observations you want to use and on which kind of linear combination the GPS ambiguity resolutions shall be based:</p><p><ul>"
    1531 #ifdef USE_PPP_SSR_I
    1532       "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1533       "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1534 #else
    1535       "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
    1536       "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
    1537       "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
    1538       "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
    1539       "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1540       "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1541       "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
    1542 #endif
    1543       "<li>'no'    means that you don't want BNC to use GPS data.</li></ul></p><p><i>[key: PPP/lcGPS]</i></p>"));
    1544   _pppWidgets._lcGLONASS->setWhatsThis(tr("<p>Specify which kind of GLONASS observations you want to use and on which kind of linear combination the GLONASS ambiguity resolutions shall be based:</p><p><ul>"
    1545 #ifdef USE_PPP_SSR_I
    1546       "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1547       "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1548       "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
    1549 #else
    1550       "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
    1551       "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
    1552       "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
    1553       "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
    1554       "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1555       "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1556       "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
    1557 #endif
    1558       "<li>'no'    means that you don't want BNC to use GLONASS data.</li></ul></p><p><i>[key: PPP/lcGLONASS]</i></p>"));
    1559   _pppWidgets._lcGalileo->setWhatsThis(tr("<p>Specify which kind of Galileo observations you want to use and on which kind of linear combination the Galileo ambiguity resolutions shall be based:</p><p><ul>"
    1560 #ifdef USE_PPP_SSR_I
    1561           "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1562           "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1563           "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
    1564 #else
    1565       "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
    1566       "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
    1567       "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
    1568       "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
    1569       "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1570       "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1571       "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
    1572 #endif
    1573       "<li>'no'    means that you don't want BNC to use Galileo data.</li></ul></p><p><i>[key: PPP/lcGalileo]</i></p>"));
    1574   _pppWidgets._lcBDS->setWhatsThis(tr("<p>Specify which kind of BDS observations you want to use and on which kind of linear combination the BDS ambiguity resolutions shall be based:</p><p><ul>"
    1575 #ifdef USE_PPP_SSR_I
    1576       "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1577       "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1578       "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
    1579 #else
    1580       "<li>'Pi&Li' means that uncombined code and phase data of two frequencies shall be used.</li>"
    1581       "<li>'Pi'    means that uncombined code data of two frequencies shall be used.</li>"
    1582       "<li>'P1&L1' means that uncombined code and phase data of one frequency shall be used.</li>"
    1583       "<li>'P1'    means that uncombined code data of one frequency shall be used.</li>"
    1584       "<li>'P3&L3' means that the inonosphere-free linear combination of code and phase data shall be used.</li>"
    1585       "<li>'P3'    means that the inonosphere-free linear combination of code data shall be used.</li>"
    1586       "<li>'L3'    means that the inonosphere-free linear combination of phase data shall be used.</li> "
    1587 #endif
    1588       "<li>'no'    means that you don't want BNC to use BDS data.</li></ul></p><p><i>[key: PPP/lcBDS]</i></p>"));
    1589   _pppWidgets._constraints->setWhatsThis(tr("<p>Specify, whether ionospheric constraints in form of pseudo-observations shall be added. Please note, this is only valid, if no ionosphere-free linear-combination is used and only helpful as soon as the ionosphere information is more accurate than the code data accuracy. <i>[key: PPP/constraints]</i></p>"));
    1590   _pppWidgets._sigmaC1->setWhatsThis(tr("<p>Enter a Sigma for GPS C1 code observations in meters.</p><p>The higher the sigma you enter, the less the contribution of GPS C1 code observations to a PPP solution from combined code and phase data. 1.0 is likely to be an appropriate choice.</p><p>Default is an empty option field, meaning<br>'Sigma C1 = 1.0' <i>[key: PPP/sigmaC1]</i></p>"));
    1591   _pppWidgets._sigmaL1->setWhatsThis(tr("<p>Enter a Sigma for GPS L1 phase observations in meters.</p><p>The higher the sigma you enter, the less the contribution of GPS L1 phase observations to a PPP solutions from combined code and phase data. 0.01 is likely to be an appropriate choice.</p><p>Default is an empty option field, meaning<br>'Sigma L1 = 0.01' <i>[key: PPP/sigmaL1]</i></p>"));
    1592 #ifdef USE_PPP
    1593   _pppWidgets._sigmaGIM->setWhatsThis(tr("<p>Enter a Sigma for GIM pseudo observations in meters.</p><p>The higher the sigma you enter, the less the contribution of GIM pseudo observations to a PPP solution. 5.0 is likely to be an appropriate choice.</p><p>Default is an empty option field, meaning<br>'Sigma GIM = 1.0' <i>[key: PPP/sigmaGIM]</i></p>"));
    1594 #endif
    1595   _pppWidgets._maxResC1->setWhatsThis(tr("<p>Specify a maximum for residuals from GPS C1 code observations in a PPP solution. '2.0' meters may be an appropriate choice for that.</p><p>If the maximum is exceeded, contributions from the corresponding observation will be ignored in the PPP solution.</p><p>Default is an empty option field, meaning<br>'Max Res C1 = 3.0' <i>[key: PPP/maxResC1]</i></p>"));
    1596   _pppWidgets._maxResL1->setWhatsThis(tr("<p>Specify a maximum for residuals from GPS L1 phase observations in a PPP solution. '0.02' meters may be an appropriate choice for that.</p><p>If the maximum is exceeded, contributions from the corresponding observation will be ignored in the PPP solution.</p><p>Default is an empty option field, meaning<br>'Max Res L1 = 0.03' <i>[key: PPP/maxResL1]</i></p>"));
    1597 #ifdef USE_PPP
    1598   _pppWidgets._maxResGIM->setWhatsThis(tr("<p>Specify a maximum for residuals from GIM pseudo observations in a PPP solution. '5.0' meters may be an appropriate choice for that.</p><p>If the maximum is exceeded, contributions from the corresponding observation will be ignored in the PPP solution.</p><p>Default is an empty option field, meaning<br>'Max Res GIM = 3.0' <i>[key: PPP/maxResGIM]</i></p>"));
    1599 #endif
    1600   _pppWidgets._eleWgtCode->setWhatsThis(tr("<p>Tic 'Ele Wgt Code' to use satellite Elevation depending Weights for Code observations in the PPP solution. <i>[key: PPP/eleWgtCode]</i></p>"));
    1601   _pppWidgets._eleWgtPhase->setWhatsThis(tr("<p>Tic 'Ele Wgt Phase' to use satellite Elevation depending Weights for Phase observations in the PPP solution. <i>[key: PPP/eleWgtPhase]</i></p>"));
    1602   _pppWidgets._minObs->setWhatsThis(tr("<p>Select a Minimum Number of Observations per epoch for a PPP solution.</p><p>BNC will only process epochs with observation numbers reaching or exceeding this minimum. <i>[key: PPP/minObs]</i></p>"));
    1603   _pppWidgets._minEle->setWhatsThis(tr("<p>Select a Minimum satellite Elevation for observations.</p><p>BNC will ignore an observation if the associated satellite Elevation does not reach or exceed this minimum.</p><p>Selecting '10 deg' may be an appropriate choice in order to avoid too noisy observations. <i>[key: PPP/minEle]</i></p>"));
    1604 
    1605   // WhatsThis, Combine Corrections
    1606   // ------------------------------
    1607   _cmbTable->setWhatsThis(tr("<p>BNC allows to process several orbit and clock correction streams in real-time to produce, encode, upload and save a combination of correctors coming from different providers. To add a line to the 'Combine Corrections' table hit the 'Add Row' button, double click on the 'Mountpoint' field to specify a Broadcast Ephemeris Correction mountpoint from the 'Streams' section below and hit Enter. Then double click on the 'AC Name' field to enter your choice of an abbreviation for the Analysis Center (AC) providing the stream. Double click on the 'Weight Factor' field to enter a weight factor to be applied for this stream in the combination. A Factor greater than 1 will enlarge the sigma of the clock pseudo-observations and with it down-weight its contribution. Finally, double click on the 'Exclude Satellites' field and specify satellites, to exclude them for an individual AC. An entry 'G04,G31,R' means to excludes GPS satellites PRN 4 and 31 as well as all GLONASS satellites from one individual AC. Default is an empty option field, meaning that no satellite is excluded from this individual AC.</p><p>Note that the orbit information in the resulting combination stream is just copied from one of the incoming streams. The stream used for providing the orbits may vary over time: if the orbit providing stream has an outage then BNC switches to the next remaining stream for getting hold of the orbit information.</p><p>The combination process requires Broadcast Ephemeris. Besides orbit and clock correction streams BNC should therefore pull a stream carrying Broadcast Ephemeris in the form of RTCM Version 3 messages.</p><p>It is possible to specify only one Broadcast Ephemeris Correction stream in the 'Combine Corrections' table. Instead of combining corrections BNC will then add the corrections to the Broadcast Ephemeris with the possibility to save final orbit and clock results in SP3 and/or Clock RINEX format. <i>[key: cmbStreams]</i></p>"));
    1608   addCmbRowButton->setWhatsThis(tr("<p>Hit 'Add Row' button to add another line to the 'Combine Corrections' table.</p>"));
    1609   delCmbRowButton->setWhatsThis(tr("<p>Hit 'Delete' button to delete the highlighted line(s) from the 'Combine Corrections' table.</p>"));
    1610   _cmbMethodComboBox->setWhatsThis(tr("<p>Select a clock combination approach. Options are 'Single-Epoch' and Kalman 'Filter'.</p><p>It is suggested to use the Kalman filter approach for the purpose of Precise Point Positioning. <i>[key: cmbMethod]</i></p>"));
    1611   _cmbMaxresLineEdit->setWhatsThis(tr("<p>BNC combines all incoming clocks according to specified weights. Individual clock estimates that differ by more than 'Maximal Clk Residuum' meters from the average of all clocks will be ignored.<p></p>It is suggested to specify a value of about 0.2 m for the Kalman filter combination approach and a value of about 3.0 meters for the Single-Epoch combination approach.</p><p>Default is a value of '999.0'. <i>[key: cmbMaxres]</i></p>"));
    1612   _cmbMaxdisplacementLineEdit->setWhatsThis(tr("<p>BNC builds mean values for all incoming orbit corrections per satellite. Individual orbit corrections that differ by more than 'Maximal Orb Displacement' meters from the average of all orbit corrections per satellite will be ignored.<p></p>It is suggested to specify a value of about 0.5 m.</p><p>Default is a value of '2.0'. <i>[key: cmbMaxdisplacement]</i></p>"));
    1613   _cmbSamplSpinBox->setWhatsThis(tr("<p>Select a combination Sampling interval for the clocks. Clock corrections will be produced following that interval.</p><p>A value of 10 sec may be an appropriate choice. A value of zero '0' tells BNC to use all available samples. <i>[key: cmbSampl]</i></p>"));
    1614   _cmbLogPath->setWhatsThis(tr("<p>Specify a directory for saving daily Combination logfiles. If the specified directory does not exist, BNC will not create such files.</p><p>Default is an empty option field, meaning that no Combination logfiles shall be produced. <i>[key: cmbLogpath]</i></p>"));
    1615   _cmbGpsCheckBox->setWhatsThis(tr("<p>GPS clock corrections shall be combined. GPS Broadcast ephemeris and corrections are required. <i>[key: cmbGps]</i></p>"));
    1616   _cmbGloCheckBox->setWhatsThis(tr("<p>GLONASS clock corrections shall be combined; GLONASS Broadcast ephemeris and corrections are required. <i>[key: cmbGlo]</i></p>"));
    1617   _cmbGalCheckBox->setWhatsThis(tr("<p>Galileo clock corrections shall be combined; Galileo Broadcast ephemeris and corrections are required. <i>[key: cmbGal]</i></p>"));
    1618   _cmbBdsCheckBox->setWhatsThis(tr("<p>Beidou clock corrections shall be combined; BDS Broadcast ephemeris and corrections are required. <i>[key: cmbBds]</i></p>"));
    1619   _cmbQzssCheckBox->setWhatsThis(tr("<p>QZSS clock corrections shall be combined; QZSS Broadcast ephemeris and corrections are required. <i>[key: cmbQzss]</i></p>"));
    1620   _cmbSbasCheckBox->setWhatsThis(tr("<p>SBAS clock corrections shall be combined; SBAS Broadcast ephemeris and corrections are required. <i>[key: cmbSbas]</i></p>"));
    1621   _cmbNavicCheckBox->setWhatsThis(tr("<p>NavIC clock corrections shall be combined; NavIC Broadcast ephemeris and corrections are required. <i>[key: cmbNavic]</i></p>"));
    1622   _cmbBsxFile->setWhatsThis(tr("<p> Specify a Bias SINEX File that will be used to add satellite code biases to the combined clocks. <i>[key: cmbBsxFile]</i></p>"));
    1623 
    1624   // WhatsThis, Upload Corrections
    1625   // -----------------------------
    1626   _uploadTable->setWhatsThis(tr("<p>BNC can upload clock and orbit corrections to Broadcast Ephemeris (Broadcast Corrections) as well as Code Biases in different SSR formats. You may have a situation where clocks, orbits and code biases come from an external Real-time Network Engine (1) or a situation where clock and orbit corrections are combined within BNC (2).</p><p>(1) BNC identifies a stream as coming from a Real-time Network Engine if its format is specified as 'RTNET' and hence its decoder string in the 'Streams' canvas is 'RTNET'. It encodes and uploads that stream to the specified Ntrip Broadcaster Host and Port</p><p>(2) BNC understands that it is expected to encode and upload combined Broadcast Ephemeris Corrections if you specify correction streams in the 'Combine Corrections' table.</p><p>To fill the 'Upload Corrections' table, hit the 'Add Row' button, double click on the 'Host' field to enter the IP or URL of an Ntrip Broadcaster and hit Enter. Select the Ntrip Version that shall be used for data upload. Then double click on the 'Port', 'Mount' and 'Password' fields to enter the Ntrip Broadcaster IP port (default is 80), the mountpoint and the stream upload password. If Ntrip Version 2 is chosen, click to the 'User' field to enter a stream upload user name. An empty 'Host' option field means that you don't want to upload corrections.</p><p>Select a target coordinate reference System (e.g. IGS20) for outgoing clock and orbit corrections.</p><p>Select a target SSR format (e.g. IGS-SSR) for outgoing clock and orbit corrections.</p><p>By default orbit and clock corrections refer to Antenna Phase Center (APC). Tick 'CoM' to refer uploaded corrections to Center of Mass instead of APC.</p><p>Specify a path for saving generated Broadcast Corrections plus Broadcast Ephemeris as SP3 orbit files. If the specified directory does not exist, BNC will not create such files. The following is a path example for a Linux system: /home/user/BKG0MGXRTS${V3PROD}.SP3.</p><p>Specify a path for saving generated Broadcast Correction clocks plus Broadcast Ephemeris clocks as Clock RINEX files. If the specified directory does not exist, BNC will not create Clock RINEX files. The following is a path example for a Linux system: /home/user/BKG0MGXRTS${V3PROD}.CLK.</p><p>Specify a path for saving generated Code Biases as SINEX Bias files. If the specified directory does not exist, BNC will not create SINEX Bias files. The following is a path example for a Linux system: /home/user/BKG0MGXRTS${V3PROD}.BIA.</p><p>Note that '${V3PROD}' produces the time stamp in the filename, which is related to the RINEX version 3 filename concept.</p><p>Finally, specify a SSR Provider ID (issued by RTCM), SSR Solution ID, and SSR Issue of Data number.</p><p>In case the 'Combine Corrections' table contains only one Broadcast Correction stream, BNC will add that stream content to the Broadcast Ephemeris to save results in files specified via SP3 and/or Clock RINEX file path. You should then define only the SP3 and Clock RINEX file path and no further option in the 'Upload Corrections' table. <i>[key: uploadMountpointsOut]</i></p>"));
    1627   addUploadRowButton->setWhatsThis(tr("<p>Hit 'Add Row' button to add another line to the 'Upload Corrections' table.</p>"));
    1628   delUploadRowButton->setWhatsThis(tr("<p>Hit 'Del Row' button to delete the highlighted line(s) from the 'Upload Corrections' table.</p>"));
    1629   _uploadIntrComboBox->setWhatsThis(tr("<p>Select the length of the SP3, Clock RINEX and Bias SINEX files. <i>[key: uploadIntr]</i></p>"));
    1630   _uploadSamplRtcmEphCorrSpinBox->setWhatsThis(tr("<p>Select a stream's orbit correction sampling interval in seconds.</p><p>A value of zero '0' tells BNC to upload all available orbit and clock correction samples together in combined messages. <i>[key: uploadSamplRtcmEphCorr]</i></p>"));
    1631   _uploadSamplSp3ComboBox->setWhatsThis(tr("<p>Select a SP3 orbit file sampling interval in seconds.</p><p>A value of zero '0' tells BNC to store all available samples into SP3 orbit files. <i>[key: uploadSamplSp3]</i></p>"));
    1632   _uploadSamplClkRnxSpinBox->setWhatsThis(tr("<p>Select a Clock RINEX file sampling interval in seconds.</p><p>A value of zero '0' tells BNC to store all available samples into Clock RINEX files. <i>[key: uploadSamplClkRnx]</i></p>"));
    1633   _uploadSamplBiaSnxSpinBox->setWhatsThis(tr("<p>Select a Bias SINEX file sampling interval in seconds.</p><p>A value of zero '0' tells BNC to store all available samples into Bias SINEX files. <i>[key: uploadSamplBiaSnx]</i></p>"));
    1634   setUploadTrafoButton->setWhatsThis(tr("<p>Hit 'Custom Trafo' to specify your own 14 parameter Helmert Transformation instead of selecting a predefined transformation via option 'System'.</p>"));
    1635   _uploadAntexFile->setWhatsThis(tr("<p>When producing SP3 files or referring orbit and clock corrections to the satellite's Center of Mass (CoM) instead Antenna Phase Center (APC), an offset has to be applied which is available from the IGS 'ANTEX file'. You must therefore specify an 'ANTEX file' path if you want to save the stream content in SP3 format and/or refer correctors to CoM.</p><p>If you don't specify an 'ANTEX file' path, the SP3 file content as well as the orbit and clock correctors will be referred to satellite APCs. <i>[key: uploadAntexFile]</i></p>"));
    1636 
    1637   // WhatsThis, Upload Ephemeris
    1638   // ---------------------------
    1639   _uploadEphTable->setWhatsThis(tr("<p>BNC can upload Broadcast Ephemeris streams in RTCM Version 3 format. To fill the 'Upload Ephemeris' table, hit the 'Add Row' button, double click on the 'Host' field to enter the IP or URL of an Ntrip Broadcaster and hit Enter. Select the Ntrip Version that shall be used for data upload. Then double click on the 'Port', 'Mount' and 'Password' fields to enter the Ntrip Broadcaster IP port (default is 80), the mountpoint and the stream upload password. If Ntrip Version 2 is chosen, click to the 'User' field to enter a stream upload user name. Specify the satellite system(s) that shall be part of the uploaded stream (e.g. G for GPS or GRE for GPS+GLONASS+Galileo, or ALL). <i>[key: uploadEphHost]</i></p>"));
    1640   addUploadEphRowButton->setWhatsThis(tr("<p>Hit 'Add Row' button to add another line to the 'Upload Ephemeris' table.</p>"));
    1641   delUploadEphRowButton->setWhatsThis(tr("<p>Hit 'Del Row' button to delete the highlighted line(s) from the 'Upload Ephemeris' table.</p>"));
    1642   _uploadSamplRtcmEphSpinBox->setWhatsThis(tr("<p>Select the Broadcast Ephemeris sampling interval in seconds.</p><p>Default is '5', meaning that a complete set of Broadcast Ephemeris is uploaded every 5 seconds. <i>[key: uploadSamplRtcmEph]</i></p>"));
    1643 
    1644   // WhatsThis, Streams Canvas
    1645   // -------------------------
    1646   _mountPointsTable->setWhatsThis(tr("<p>Streams selected for retrieval are listed in the 'Streams' section. "
    1647       "Clicking on 'Add Stream' button opens a window that allows the user to select data streams from an Ntrip Broadcaster "
    1648       "according to their mountpoints. To remove a stream from the 'Streams' list, highlight it by clicking on it "
    1649       "and hit the 'Delete Stream' button. You can also remove multiple streams by highlighting them using +Shift and +Ctrl.</p><p>"
    1650       "BNC automatically allocates one of its internal decoders to a stream based on the stream's 'format' as given in the source-table. "
    1651       "BNC allows users to change this selection by editing the decoder string. "
    1652       "Double click on the 'decoder' field, enter your preferred decoder and then hit Enter. "
    1653       "Accepted decoder strings are 'RTCM_2.x', 'RTCM_3.x' and 'RTNET'.</p><p>"
    1654       "In case you need to log raw data as is, BNC allows to by-pass its decoders and directly save the input in daily log files. "
    1655       "To do this, specify the decoder string as 'ZERO2FILE'.</p><p>"
    1656       "BNC allows as well to forward streams related to the specified 'Mountpoint' on top of the 'Miscellaneous Panel' "
    1657       "through a TCP/IP port of your local host. "
    1658       "In this case, the stream content remains untouched; BNC does not decode or reformat the data for this output. "
    1659       "If the decoder string is not an accepted one, please change the decoder string to 'ZERO' (forward the raw data only) or 'ZERO2FILE' (forward and store the raw data) in addition.</p><p>"
    1660       "BNC can also retrieve streams from virtual reference stations (VRS). VRS streams are indicated by a 'yes' in the 'nmea' column. "
    1661       "To initiate such stream, the approximate latitude/longitude rover position is sent to the Ntrip Broadcaster "
    1662       "together with an approximation for the height. Default values for latitude and longitude can be change according to your requirement. "
    1663       "Double click on 'lat' and 'long' fields, enter the values you wish to send and then hit Enter. <i>[key: mountPoints]</i></p>"));
    1664   _actAddMountPoints->setWhatsThis(tr("<p>Add stream(s) to selection presented in the 'Streams' canvas.</p>"));
    1665   _actDeleteMountPoints->setWhatsThis(tr("<p>Delete stream(s) from selection presented in the 'Streams' canvas.</p>"));
    1666   _actMapMountPoints->setWhatsThis(tr("<p> Draw distribution map of stream selection presented in the 'Streams' canvas. Use mouse to zoom in or out.</p><p>Left button: Draw rectangle to zoom in.<br>Right button: Zoom out.<br>Middle button: Zoom back.</p>"));
    1667   _actStart->setWhatsThis(tr("<p> Start running BNC.</p>"));
    1668   _actStop->setWhatsThis(tr("<p> Stop running BNC.</p>"));
    1669 
    1670   // WhatsThis, Log Canvas
    1671   // ---------------------
    1672   _log->setWhatsThis(tr("<p>Records of BNC's activities are shown in the 'Log' tab. The message log covers the communication status between BNC and the Ntrip Broadcaster as well as problems that occur in the communication link, stream availability, stream delay, stream conversion etc.</p>"));
    1673   _bncFigure->setWhatsThis(tr("<p>The bandwith consumption per stream is shown in the 'Throughput' tab in bits per second (bps) or kilobits per second (kbps).</p>"));
    1674   _bncFigureLate->setWhatsThis(tr("<p>The individual latency of observations of incoming streams is shown in the 'Latency' tab. Streams not carrying observations (e.g. those providing only Broadcast Ephemeris) remain unconsidered.</p><p>Note that the calculation of correct latencies requires the clock of the host computer to be properly synchronized.</p>"));
    1675   _bncFigurePPP->setWhatsThis(tr("<p>PPP time series of North (red), East (green) and Up (blue) displacements are shown in the 'PPP Plot' tab when the corresponding option is selected.</p><p>Values are referred to an XYZ a priori coordinate. The sliding PPP time series window covers the period of the latest 5 minutes.</p>"));
    1676 
    1677 
    1678   // Enable/Disable all Widgets
    1679   // --------------------------
    1680   slotBncTextChanged();
    1681   enableStartStop();
    1682 
    1683   // Auto start
    1684   // ----------
    1685   if ( Qt::CheckState(settings.value("autoStart").toInt()) == Qt::Checked) {
    1686     slotStart();
    1687   }
    1688 }
    1689 
    1690 // Destructor
    1691 ////////////////////////////////////////////////////////////////////////////
    1692 bncWindow::~bncWindow() {
    1693   if (_caster) {
    1694     delete _caster; BNC_CORE->setCaster(0);
    1695   }
    1696   if (_casterEph) {
    1697     delete _casterEph;
    1698   }
    1699   delete _bncFigureLate;
    1700   delete _bncFigurePPP;
    1701   delete _actHelp;
    1702   delete _actAbout;
    1703   delete _actFlowchart;
    1704   delete _actFontSel;
    1705   delete _actSaveOpt;
    1706   delete _actQuit;
    1707   delete _actAddMountPoints;
    1708   delete _actDeleteMountPoints;
    1709   delete _actMapMountPoints;
    1710   delete _actStart;
    1711   delete _actStop;
    1712   delete _actwhatsthis;
    1713   delete _proxyHostLineEdit;
    1714   delete _proxyPortLineEdit;
    1715   delete _sslCaCertPathLineEdit;
    1716   delete _sslClientCertPathLineEdit;
    1717   delete _sslIgnoreErrorsCheckBox;
    1718   delete _logFileLineEdit;
    1719   delete _rawOutFileLineEdit;
    1720   delete _rnxAppendCheckBox;
    1721   delete _onTheFlyComboBox;
    1722   delete _autoStartCheckBox;
    1723   delete _rnxPathLineEdit;
    1724   delete _rnxIntrComboBox;
    1725   delete _rnxSamplComboBox;
    1726   delete _rnxSkelExtComboBox;
    1727   delete _rnxSkelPathLineEdit;
    1728   delete _rnxFileCheckBox;
    1729   delete _rnxScrpLineEdit;
    1730   delete _rnxVersComboBox;
    1731   delete _rnxV2Priority;
    1732   delete _ephPathLineEdit;
    1733   //delete _ephFilePerStation;
    1734   delete _ephIntrComboBox;
    1735   delete _ephOutPortLineEdit;
    1736   delete _ephVersComboBox;
    1737   delete _corrPathLineEdit;
    1738   delete _corrIntrComboBox;
    1739   delete _corrPortLineEdit;
    1740   delete _outPortLineEdit;
    1741   delete _outWaitSpinBox;
    1742   delete _outSamplComboBox;
    1743   delete _outFileLineEdit;
    1744   delete _outUPortLineEdit;
    1745   delete _outLockTimeCheckBox;
    1746   delete _serialMountPointLineEdit;
    1747   delete _serialPortNameLineEdit;
    1748   delete _serialBaudRateComboBox;
    1749   delete _serialFlowControlComboBox;
    1750   delete _serialDataBitsComboBox;
    1751   delete _serialParityComboBox;
    1752   delete _serialStopBitsComboBox;
    1753   delete _serialAutoNMEAComboBox;
    1754   delete _serialFileNMEALineEdit;
    1755   delete _serialHeightNMEALineEdit;
    1756   delete _serialNMEASamplingSpinBox;
    1757   delete _adviseObsRateComboBox;
    1758   delete _adviseFailSpinBox;
    1759   delete _adviseRecoSpinBox;
    1760   delete _adviseScriptLineEdit;
    1761   delete _miscMountLineEdit;
    1762   delete _miscPortLineEdit;
    1763   delete _miscIntrComboBox;
    1764   delete _miscScanRTCMCheckBox;
    1765   _mountPointsTable->deleteLater();
    1766   delete _log;
    1767   delete _loggroup;
    1768   _cmbTable->deleteLater();
    1769   delete _cmbMaxresLineEdit;
    1770   delete _cmbMaxdisplacementLineEdit;
    1771   delete _cmbSamplSpinBox;
    1772   delete _cmbLogPath;
    1773   delete _cmbMethodComboBox;
    1774   delete _cmbGpsCheckBox;
    1775   delete _cmbGloCheckBox;
    1776   delete _cmbGalCheckBox;
    1777   delete _cmbBdsCheckBox;
    1778   delete _cmbQzssCheckBox;
    1779   delete _cmbSbasCheckBox;
    1780   delete _cmbNavicCheckBox;
    1781   delete _cmbBsxFile;
    1782   _uploadEphTable->deleteLater();
    1783   delete _uploadSamplRtcmEphCorrSpinBox;
    1784   _uploadTable->deleteLater();
    1785   delete _uploadIntrComboBox;
    1786   delete _uploadAntexFile;
    1787   delete _uploadSamplRtcmEphSpinBox;
    1788   delete _uploadSamplSp3ComboBox;
    1789   delete _uploadSamplClkRnxSpinBox;
    1790   delete _uploadSamplBiaSnxSpinBox;
    1791   delete _reqcActionComboBox;
    1792   delete _reqcObsFileChooser;
    1793   delete _reqcNavFileChooser;
    1794   delete _reqcOutObsLineEdit;
    1795   delete _reqcOutNavLineEdit;
    1796   delete _reqcOutLogLineEdit;
    1797   delete _reqcPlotDirLineEdit;
    1798   delete _reqcSkyPlotSignals;
    1799   delete _reqcLogSummaryOnly;
    1800   delete _reqcEditOptionButton;
    1801   delete _sp3CompFileChooser;
    1802   delete _sp3CompExclude;
    1803   delete _sp3CompLogLineEdit;
    1804   delete _sp3CompSummaryOnly;
    1805   //delete _canvas;
     2216    settings.setValue("corrPath", _corrPathLineEdit->text());
     2217    settings.setValue("corrIntr", _corrIntrComboBox->currentText());
     2218    settings.setValue("corrPort", _corrPortLineEdit->text());
     2219    // Feed Engine
     2220    settings.setValue("outPort", _outPortLineEdit->text());
     2221    settings.setValue("outWait", _outWaitSpinBox->value());
     2222    settings.setValue("outSampl", _outSamplComboBox->currentText());
     2223    settings.setValue("outFile", _outFileLineEdit->text());
     2224    settings.setValue("outLockTime", _outLockTimeCheckBox->checkState());    settings.setValue("outUPort", _outUPortLineEdit->text());
     2225    // Serial Output
     2226    settings.setValue("serialMountPoint", _serialMountPointLineEdit->text());
     2227    settings.setValue("serialPortName", _serialPortNameLineEdit->text());
     2228    settings.setValue("serialBaudRate", _serialBaudRateComboBox->currentText());
     2229    settings.setValue("serialFlowControl", _serialFlowControlComboBox->currentText());
     2230    settings.setValue("serialDataBits", _serialDataBitsComboBox->currentText());
     2231    settings.setValue("serialParity", _serialParityComboBox->currentText());
     2232    settings.setValue("serialStopBits", _serialStopBitsComboBox->currentText());
     2233    settings.setValue("serialAutoNMEA", _serialAutoNMEAComboBox->currentText());
     2234    settings.setValue("serialFileNMEA", _serialFileNMEALineEdit->text());
     2235    settings.setValue("serialHeightNMEA", _serialHeightNMEALineEdit->text());
     2236    settings.setValue("serialNMEASampling", _serialNMEASamplingSpinBox->value());
     2237    // Outages
     2238    settings.setValue("adviseObsRate", _adviseObsRateComboBox->currentText());
     2239    settings.setValue("adviseFail", _adviseFailSpinBox->value());
     2240    settings.setValue("adviseReco", _adviseRecoSpinBox->value());
     2241    settings.setValue("adviseScript", _adviseScriptLineEdit->text());
     2242    // Miscellaneous
     2243    settings.setValue("miscMount", _miscMountLineEdit->text());
     2244    settings.setValue("miscPort", _miscPortLineEdit->text());
     2245    settings.setValue("miscIntr", _miscIntrComboBox->currentText());
     2246    settings.setValue("miscScanRTCM", _miscScanRTCMCheckBox->checkState());
     2247    // Reqc
     2248    settings.setValue("reqcAction", _reqcActionComboBox->currentText());
     2249    settings.setValue("reqcObsFile", _reqcObsFileChooser->fileName());
     2250    settings.setValue("reqcNavFile", _reqcNavFileChooser->fileName());
     2251    settings.setValue("reqcOutObsFile", _reqcOutObsLineEdit->text());
     2252    settings.setValue("reqcOutNavFile", _reqcOutNavLineEdit->text());
     2253    settings.setValue("reqcOutLogFile", _reqcOutLogLineEdit->text());
     2254    settings.setValue("reqcPlotDir", _reqcPlotDirLineEdit->text());
     2255    settings.setValue("reqcSkyPlotSignals", _reqcSkyPlotSignals->text());
     2256    settings.setValue("reqcLogSummaryOnly", _reqcLogSummaryOnly->checkState());
     2257    // SP3 Comparison
     2258    settings.setValue("sp3CompFile", _sp3CompFileChooser->fileName());
     2259    settings.setValue("sp3CompExclude", _sp3CompExclude->text());
     2260    settings.setValue("sp3CompOutLogFile", _sp3CompLogLineEdit->text());
     2261    settings.setValue("sp3CompSummaryOnly", _sp3CompSummaryOnly->checkState());
     2262    // Combine Corrections
     2263    if (!cmbStreams.isEmpty()) {
     2264        settings.setValue("cmbStreams", cmbStreams);
     2265    }
     2266    else {
     2267        settings.setValue("cmbStreams", "");
     2268    }
     2269    settings.setValue("cmbMethod", _cmbMethodComboBox->currentText());
     2270    settings.setValue("cmbMaxres", _cmbMaxresLineEdit->text());
     2271    settings.setValue("cmbMaxdisplacement", _cmbMaxdisplacementLineEdit->text());
     2272    settings.setValue("cmbSampl", _cmbSamplComboBox->currentText());
     2273    settings.setValue("cmbLogpath", _cmbLogPath->text());
     2274    settings.setValue("cmbGps", _cmbGpsCheckBox->checkState());
     2275    settings.setValue("cmbGlo", _cmbGloCheckBox->checkState());
     2276    settings.setValue("cmbGal", _cmbGalCheckBox->checkState());
     2277    settings.setValue("cmbBds", _cmbBdsCheckBox->checkState());
     2278    settings.setValue("cmbQzss", _cmbQzssCheckBox->checkState());
     2279    settings.setValue("cmbSbas", _cmbSbasCheckBox->checkState());
     2280    settings.setValue("cmbNavic", _cmbNavicCheckBox->checkState());
     2281    settings.setValue("cmbBsxFile", _cmbBsxFile->fileName());
     2282
     2283    // Upload Corrections
     2284    if (!uploadMountpointsOut.isEmpty()) {
     2285        settings.setValue("uploadMountpointsOut", uploadMountpointsOut);
     2286    }
     2287    else {
     2288        settings.setValue("uploadMountpointsOut", "");
     2289    }
     2290    settings.setValue("uploadIntr", _uploadIntrComboBox->currentText());
     2291    settings.setValue("uploadSamplRtcmEphCorr", _uploadSamplRtcmEphCorrComboBox->currentText());
     2292    settings.setValue("uploadSamplSp3", _uploadSamplSp3ComboBox->currentText());
     2293    settings.setValue("uploadSamplClkRnx", _uploadSamplClkRnxSpinBox->value());
     2294    settings.setValue("uploadSamplBiaSnx", _uploadSamplBiaSnxSpinBox->value());
     2295    settings.setValue("uploadAntexFile", _uploadAntexFile->fileName());
     2296    // Upload Ephemeris
     2297    if (!uploadEphMountpointsOut.isEmpty()) {
     2298        settings.setValue("uploadEphMountpointsOut", uploadEphMountpointsOut);
     2299    }
     2300    else {
     2301        settings.setValue("uploadEphMountpointsOut", "");
     2302    }
     2303    settings.setValue("uploadSamplRtcmEph", _uploadSamplRtcmEphSpinBox->value());
     2304
     2305    if (_caster) {
     2306        _caster->readMountPoints();
     2307    }
     2308
     2309    _pppWidgets.saveOptions();
     2310}
     2311
     2312// All get slots terminated
     2313////////////////////////////////////////////////////////////////////////////
     2314void bncWindow::slotGetThreadsFinished() {
     2315    BNC_CORE->slotMessage("All Get Threads Terminated", true);
     2316    delete _caster;    _caster = 0; BNC_CORE->setCaster(0);
     2317    delete _casterEph; _casterEph = 0;
     2318    _runningRealTime = false;
     2319    enableStartStop();
     2320}
     2321
     2322// Start It!
     2323////////////////////////////////////////////////////////////////////////////
     2324void bncWindow::slotStart() {
     2325    saveOptions();
     2326    if (_pppWidgets._dataSource->currentText() == "RINEX Files") {
     2327        _runningPPP = true;
     2328        enableStartStop();
     2329        _caster = new bncCaster(); BNC_CORE->setCaster(_caster);
     2330        BNC_CORE->startPPP();
     2331        _bncFigurePPP->reset();
     2332    }
     2333    else if (!_reqcActionComboBox->currentText().isEmpty()) {
     2334        if (_reqcActionComboBox->currentText() == "Analyze") {
     2335            _runningQC = true;
     2336            t_reqcAnalyze* reqcAnalyze = new t_reqcAnalyze(this);
     2337            connect(reqcAnalyze, SIGNAL(finished()), this, SLOT(slotPostProcessingFinished()));
     2338            reqcAnalyze->start();
     2339        }
     2340        else {
     2341            _runningEdit = true;
     2342            t_reqcEdit* reqcEdit = new t_reqcEdit(this);
     2343            connect(reqcEdit, SIGNAL(finished()), this, SLOT(slotPostProcessingFinished()));
     2344            reqcEdit->start();
     2345        }
     2346        enableStartStop();
     2347    }
     2348    else if (!_sp3CompFileChooser->fileName().isEmpty()) {
     2349        _runningSp3Comp = true;
     2350        t_sp3Comp* sp3Comp = new t_sp3Comp(this);
     2351        connect(sp3Comp, SIGNAL(finished()), this, SLOT(slotPostProcessingFinished()));
     2352        sp3Comp->start();
     2353        enableStartStop();
     2354    }
     2355    else {
     2356        startRealTime();
     2357        BNC_CORE->startPPP();
     2358    }
     2359}
     2360
     2361// Start Real-Time (Retrieve Data etc.)
     2362////////////////////////////////////////////////////////////////////////////
     2363void bncWindow::startRealTime() {
     2364
     2365    _runningRealTime = true;
     2366
     2367    _bncFigurePPP->reset();
     2368
     2369    _actDeleteMountPoints->setEnabled(false);
     2370
     2371    enableStartStop();
     2372
     2373    _caster = new bncCaster();
     2374
     2375    BNC_CORE->setCaster(_caster);
     2376    BNC_CORE->setPortEph(_ephOutPortLineEdit->text().toInt());
     2377    BNC_CORE->setPortCorr(_corrPortLineEdit->text().toInt());
     2378    BNC_CORE->initCombination();
     2379
     2380    connect(_caster, SIGNAL(getThreadsFinished()), this, SLOT(slotGetThreadsFinished()));
     2381
     2382    connect(_caster, SIGNAL(mountPointsRead(QList<bncGetThread*>)), this, SLOT(slotMountPointsRead(QList<bncGetThread*>)));
     2383
     2384    BNC_CORE->slotMessage("========== Start BNC v" BNCVERSION " (" BNC_OS ") ==========", true);
     2385
     2386    bncSettings settings;
     2387
     2388    // Active panels
     2389    // -------------
     2390    if (!_rnxPathLineEdit->text().isEmpty())
     2391        BNC_CORE->slotMessage("Panel 'RINEX Observations' active", true);
     2392    if (!_ephPathLineEdit->text().isEmpty())
     2393        BNC_CORE->slotMessage("Panel 'RINEX Ephemeris' active", true);
     2394    if (!_corrPathLineEdit->text().isEmpty())
     2395        BNC_CORE->slotMessage("Panel 'Broadcast Corrections' active", true);
     2396    if (!_outPortLineEdit->text().isEmpty())
     2397        BNC_CORE->slotMessage("Panel 'Feed Engine' active", true);
     2398    if (!_serialMountPointLineEdit->text().isEmpty())
     2399        BNC_CORE->slotMessage("Panel 'Serial Output' active", true);
     2400    if (!_adviseObsRateComboBox->currentText().isEmpty())
     2401        BNC_CORE->slotMessage("Panel 'Outages' active", true);
     2402    if (!_miscMountLineEdit->text().isEmpty())
     2403        BNC_CORE->slotMessage("Panel 'Miscellaneous' active", true);
     2404    if (_pppWidgets._dataSource->currentText() == "Real-Time Streams")
     2405        BNC_CORE->slotMessage("Panel 'PPP' active", true);
     2406    if (_cmbTable->rowCount() > 0)
     2407        BNC_CORE->slotMessage("Panel 'Combine Corrections' active", true);
     2408    if (_uploadTable->rowCount() > 0)
     2409        BNC_CORE->slotMessage("Panel 'Upload Corrections' active", true);
     2410    if (_uploadEphTable->rowCount() > 0)
     2411        BNC_CORE->slotMessage("Panel 'UploadEphemeris' active", true);
     2412
     2413    QDir rnxdir(settings.value("rnxPath").toString());
     2414    if (!rnxdir.exists()) BNC_CORE->slotMessage("Cannot find RINEX Observations directory", true);
     2415
     2416    QString rnx_file = settings.value("rnxScript").toString();
     2417    if (!rnx_file.isEmpty()) {
     2418        QFile rnxfile(settings.value("rnxScript").toString());
     2419        if (!rnxfile.exists()) BNC_CORE->slotMessage("Cannot find RINEX Observations script", true);
     2420    }
     2421
     2422    QDir ephdir(settings.value("ephPath").toString());
     2423    if (!ephdir.exists()) BNC_CORE->slotMessage("Cannot find RINEX Ephemeris directory", true);
     2424
     2425    QDir corrdir(settings.value("corrPath").toString());
     2426    if (!corrdir.exists()) BNC_CORE->slotMessage("Cannot find Broadcast Corrections directory", true);
     2427
     2428    QString advise_file = settings.value("adviseScript").toString();
     2429    if (!advise_file.isEmpty()) {
     2430        QFile advisefile(settings.value("adviseScript").toString());
     2431        if (!advisefile.exists()) BNC_CORE->slotMessage("Cannot find Outages script", true);
     2432    }
     2433
     2434    _caster->readMountPoints();
     2435
     2436    _casterEph = new bncEphUploadCaster();
     2437}
     2438
     2439// Retrieve Data
     2440////////////////////////////////////////////////////////////////////////////
     2441void bncWindow::slotStop() {
     2442    int iRet = QMessageBox::question(this, "Stop", "Stop retrieving/processing data?",
     2443        QMessageBox::Yes, QMessageBox::No,
     2444        QMessageBox::NoButton);
     2445    if (iRet == QMessageBox::Yes) {
     2446        BNC_CORE->stopPPP();
     2447        BNC_CORE->stopCombination();
     2448        delete _caster;    _caster = 0; BNC_CORE->setCaster(0);
     2449        delete _casterEph; _casterEph = 0;
     2450        _runningRealTime = false;
     2451        _runningPPP = false;
     2452        enableStartStop();
     2453    }
     2454}
     2455
     2456// Close Application gracefully
     2457////////////////////////////////////////////////////////////////////////////
     2458void bncWindow::closeEvent(QCloseEvent* event) {
     2459
     2460    int iRet = QMessageBox::question(this, "Close", "Save Options?",
     2461        QMessageBox::Yes, QMessageBox::No,
     2462        QMessageBox::Cancel);
     2463
     2464    if (iRet == QMessageBox::Cancel) {
     2465        event->ignore();
     2466        return;
     2467    }
     2468    else if (iRet == QMessageBox::Yes) {
     2469        slotSaveOptions();
     2470    }
     2471
     2472    BNC_CORE->stopPPP();
     2473
     2474    QMainWindow::closeEvent(event);
     2475}
     2476
     2477// User changed the selection of mountPoints
     2478////////////////////////////////////////////////////////////////////////////
     2479void bncWindow::slotSelectionChanged() {
     2480    if (_mountPointsTable->selectedItems().isEmpty()) {
     2481        _actDeleteMountPoints->setEnabled(false);
     2482    }
     2483    else {
     2484        _actDeleteMountPoints->setEnabled(true);
     2485    }
     2486}
     2487
     2488// Display Program Messages
     2489////////////////////////////////////////////////////////////////////////////
     2490void bncWindow::slotWindowMessage(const QByteArray msg, bool showOnScreen) {
     2491    if (showOnScreen) {
     2492        _log->append(QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ") + msg);
     2493    }
     2494}
     2495
     2496// About Message
     2497////////////////////////////////////////////////////////////////////////////
     2498void bncWindow::slotAbout() {
     2499    new bncAboutDlg(0);
     2500}
     2501
     2502//Flowchart
     2503////////////////////////////////////////////////////////////////////////////
     2504void bncWindow::slotFlowchart() {
     2505    new bncFlowchartDlg(0);
     2506}
     2507
     2508// Help Window
     2509////////////////////////////////////////////////////////////////////////////
     2510void bncWindow::slotHelp() {
     2511    QUrl url = QUrl::fromLocalFile(":/bnchelp.html");
     2512    new bncHlpDlg(0, url);
     2513}
     2514
     2515// Select Fonts
     2516////////////////////////////////////////////////////////////////////////////
     2517void bncWindow::slotFontSel() {
     2518    bool ok;
     2519    QFont newFont = QFontDialog::getFont(&ok, this->font(), this);
     2520    if (ok) {
     2521        bncSettings settings;
     2522        settings.setValue("font", newFont.toString());
     2523        QApplication::setFont(newFont);
     2524        int ww = QFontMetrics(newFont).horizontalAdvance('w');
     2525        setMinimumSize(60 * ww, 80 * ww);
     2526        resize(60 * ww, 80 * ww);
     2527    }
     2528}
     2529
     2530// Whats This Help
     2531void bncWindow::slotWhatsThis() {
     2532    QWhatsThis::enterWhatsThisMode();
    18062533}
    18072534
    18082535//
    18092536////////////////////////////////////////////////////////////////////////////
    1810 void bncWindow::populateMountPointsTable() {
    1811 
    1812   for (int iRow = _mountPointsTable->rowCount()-1; iRow >=0; iRow--) {
    1813     _mountPointsTable->removeRow(iRow);
    1814   }
    1815 
    1816   bncSettings settings;
    1817 
    1818   QListIterator<QString> it(settings.value("mountPoints").toStringList());
    1819   int iRow = 0;
    1820   while (it.hasNext()) {
    1821     QStringList hlp = it.next().split(" ");
    1822     if (hlp.size() < 7) continue;
    1823     _mountPointsTable->insertRow(iRow);
    1824 
    1825     QUrl    url(hlp[0]);
    1826 
    1827     QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
    1828     QString format(hlp[1]); QString country(hlp[2]); QString latitude(hlp[3]); QString longitude(hlp[4]);
    1829     QString nmea(hlp[5]);
    1830     if (hlp[6] == "S") {
    1831       fullPath = hlp[0].replace(0,2,"");
    1832     }
    1833     QString ntripVersion = "2";
    1834     if (hlp.size() >= 7) {
    1835       ntripVersion = (hlp[6]);
    1836     }
    1837 
    1838     QTableWidgetItem* it;
    1839     it = new QTableWidgetItem(url.userInfo());
    1840     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    1841     _mountPointsTable->setItem(iRow, 0, it);
    1842 
    1843     it = new QTableWidgetItem(fullPath);
    1844     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    1845     _mountPointsTable->setItem(iRow, 1, it);
    1846 
    1847     it = new QTableWidgetItem(format);
    1848     _mountPointsTable->setItem(iRow, 2, it);
    1849 
    1850     it = new QTableWidgetItem(country);
    1851     _mountPointsTable->setItem(iRow, 3, it);
    1852 
    1853     if      (nmea == "yes") {
    1854       it = new QTableWidgetItem(latitude);
    1855       _mountPointsTable->setItem(iRow, 4, it);
    1856       it = new QTableWidgetItem(longitude);
    1857       _mountPointsTable->setItem(iRow, 5, it);
    1858     } else {
    1859       it = new QTableWidgetItem(latitude);
    1860       it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    1861       _mountPointsTable->setItem(iRow, 4, it);
    1862 
    1863       it = new QTableWidgetItem(longitude);
    1864       it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    1865       _mountPointsTable->setItem(iRow, 5, it);
    1866     }
    1867 
    1868     it = new QTableWidgetItem(nmea);
    1869     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    1870     _mountPointsTable->setItem(iRow, 6, it);
    1871 
    1872     it = new QTableWidgetItem(ntripVersion);
    1873     ////    it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    1874     _mountPointsTable->setItem(iRow, 7, it);
    1875 
    1876     bncTableItem* bncIt = new bncTableItem();
    1877     bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
    1878     _mountPointsTable->setItem(iRow, 8, bncIt);
    1879 
    1880     iRow++;
    1881   }
    1882 
    1883   _mountPointsTable->sortItems(1);
    1884 
    1885   enableStartStop();
    1886 }
    1887 
    1888 // Retrieve Table
    1889 ////////////////////////////////////////////////////////////////////////////
    1890 void bncWindow::slotAddMountPoints() {
    1891 
    1892   bncSettings settings;
    1893   QString proxyHost = settings.value("proxyHost").toString();
    1894   int     proxyPort = settings.value("proxyPort").toInt();
    1895   if (proxyHost != _proxyHostLineEdit->text()         ||
    1896       proxyPort != _proxyPortLineEdit->text().toInt()) {
    1897     int iRet = QMessageBox::question(this, "Question", "Proxy options "
    1898                                      "changed. Use the new ones?",
    1899                                      QMessageBox::Yes, QMessageBox::No,
    1900                                      QMessageBox::NoButton);
    1901     if      (iRet == QMessageBox::Yes) {
    1902       settings.setValue("proxyHost",   _proxyHostLineEdit->text());
    1903       settings.setValue("proxyPort",   _proxyPortLineEdit->text());
    1904     }
    1905   }
    1906 
    1907   settings.setValue("sslCaCertPath",   _sslCaCertPathLineEdit->text());
    1908   settings.setValue("sslClientCertPath",   _sslClientCertPathLineEdit->text());
    1909   settings.setValue("sslIgnoreErrors", _sslIgnoreErrorsCheckBox->checkState());
    1910 
    1911   QMessageBox msgBox;
    1912   msgBox.setIcon(QMessageBox::Question);
    1913   msgBox.setWindowTitle("Add Stream");
    1914   msgBox.setText("Add stream(s) coming from:");
    1915 
    1916   QPushButton* buttonNtrip  = msgBox.addButton(tr("Caster"), QMessageBox::ActionRole);
    1917   QPushButton* buttonIP     = msgBox.addButton(tr("TCP/IP port"), QMessageBox::ActionRole);
    1918   QPushButton* buttonUDP    = msgBox.addButton(tr("UDP port"), QMessageBox::ActionRole);
    1919   QPushButton* buttonSerial = msgBox.addButton(tr("Serial port"), QMessageBox::ActionRole);
    1920   QPushButton* buttonCancel = msgBox.addButton(tr("Cancel"), QMessageBox::ActionRole);
    1921 
    1922   msgBox.exec();
    1923 
    1924   if (msgBox.clickedButton() == buttonNtrip) {
    1925     bncTableDlg* dlg = new bncTableDlg(this);
    1926     dlg->move(this->pos().x()+50, this->pos().y()+50);
    1927     connect(dlg, SIGNAL(newMountPoints(QStringList*)),
    1928           this, SLOT(slotNewMountPoints(QStringList*)));
     2537void bncWindow::slotMountPointsRead(QList<bncGetThread*> threads) {
     2538    _threads = threads;
     2539
     2540    _bncFigure->updateMountPoints();
     2541    _bncFigureLate->updateMountPoints();
     2542
     2543    populateMountPointsTable();
     2544    bncSettings settings;
     2545    _outSamplComboBox->findText(settings.value("outSampl").toString());
     2546    _outWaitSpinBox->setValue(settings.value("outWait").toInt());
     2547    QListIterator<bncGetThread*> iTh(threads);
     2548    while (iTh.hasNext()) {
     2549        bncGetThread* thread = iTh.next();
     2550        for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
     2551            QUrl url("//" + _mountPointsTable->item(iRow, 0)->text() +
     2552                "@" + _mountPointsTable->item(iRow, 1)->text());
     2553            if (url == thread->mountPoint() &&
     2554                _mountPointsTable->item(iRow, 4)->text() == thread->latitude() &&
     2555                _mountPointsTable->item(iRow, 5)->text() == thread->longitude()) {
     2556                ((bncTableItem*)_mountPointsTable->item(iRow, 8))->setGetThread(thread);
     2557                disconnect(thread, SIGNAL(newBytes(QByteArray, double)), _bncFigure, SLOT(slotNewData(QByteArray, double)));
     2558                connect(thread, SIGNAL(newBytes(QByteArray, double)), _bncFigure, SLOT(slotNewData(QByteArray, double)));
     2559                disconnect(thread, SIGNAL(newLatency(QByteArray, double)), _bncFigureLate, SLOT(slotNewLatency(QByteArray, double)));
     2560                connect(thread, SIGNAL(newLatency(QByteArray, double)), _bncFigureLate, SLOT(slotNewLatency(QByteArray, double)));
     2561                break;
     2562            }
     2563        }
     2564    }
     2565}
     2566
     2567//
     2568////////////////////////////////////////////////////////////////////////////
     2569void bncWindow::CreateMenu() {
     2570    // Create Menus
     2571    // ------------
     2572    _menuFile = menuBar()->addMenu(tr("&File"));
     2573    _menuFile->addAction(_actFontSel);
     2574    _menuFile->addSeparator();
     2575    _menuFile->addAction(_actSaveOpt);
     2576    _menuFile->addSeparator();
     2577    _menuFile->addAction(_actQuit);
     2578
     2579    _menuHlp = menuBar()->addMenu(tr("&Help"));
     2580    _menuHlp->addAction(_actHelp);
     2581    _menuHlp->addAction(_actFlowchart);
     2582    _menuHlp->addAction(_actAbout);
     2583}
     2584
     2585// Toolbar
     2586////////////////////////////////////////////////////////////////////////////
     2587void bncWindow::AddToolbar() {
     2588    QToolBar* toolBar = new QToolBar;
     2589    addToolBar(Qt::BottomToolBarArea, toolBar);
     2590    toolBar->setMovable(false);
     2591    toolBar->addAction(_actAddMountPoints);
     2592    toolBar->addAction(_actDeleteMountPoints);
     2593    toolBar->addAction(_actMapMountPoints);
     2594    toolBar->addAction(_actStart);
     2595    toolBar->addAction(_actStop);
     2596    toolBar->addWidget(new QLabel("                                           "));
     2597    toolBar->addAction(_actwhatsthis);
     2598}
     2599
     2600// About
     2601////////////////////////////////////////////////////////////////////////////
     2602bncAboutDlg::bncAboutDlg(QWidget* parent) :
     2603    QDialog(parent) {
     2604
     2605    QTextBrowser* tb = new QTextBrowser;
     2606    QUrl url = QUrl::fromLocalFile(":/bncabout.html");
     2607    tb->setSource(url);
     2608    tb->setReadOnly(true);
     2609
     2610    int ww = QFontMetrics(font()).horizontalAdvance('w');
     2611    QPushButton* _closeButton = new QPushButton("Close");
     2612    _closeButton->setMaximumWidth(10 * ww);
     2613    connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
     2614
     2615    QGridLayout* dlgLayout = new QGridLayout();
     2616    QLabel* img = new QLabel();
     2617    img->setPixmap(QPixmap(":ntrip-logo.png"));
     2618    dlgLayout->addWidget(img, 0, 0);
     2619    dlgLayout->addWidget(new QLabel("BKG Ntrip Client (BNC) Version " BNCVERSION), 0, 1);
     2620    dlgLayout->addWidget(tb, 1, 0, 1, 2);
     2621    dlgLayout->addWidget(_closeButton, 2, 1, Qt::AlignRight);
     2622
     2623    setLayout(dlgLayout);
     2624    resize(60 * ww, 60 * ww);
     2625    setWindowTitle("About BNC");
     2626    show();
     2627}
     2628
     2629//
     2630////////////////////////////////////////////////////////////////////////////
     2631bncAboutDlg::~bncAboutDlg() {
     2632
     2633};
     2634
     2635// Flowchart
     2636////////////////////////////////////////////////////////////////////////////
     2637bncFlowchartDlg::bncFlowchartDlg(QWidget* parent) :
     2638    QDialog(parent) {
     2639
     2640    int ww = QFontMetrics(font()).horizontalAdvance('w');
     2641    QPushButton* _closeButton = new QPushButton("Close");
     2642    _closeButton->setMaximumWidth(10 * ww);
     2643    connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
     2644
     2645    QGridLayout* dlgLayout = new QGridLayout();
     2646    QLabel* img = new QLabel();
     2647    img->setPixmap(QPixmap(":bncflowchart.png"));
     2648    dlgLayout->addWidget(img, 0, 0);
     2649    dlgLayout->addWidget(_closeButton, 1, 0, Qt::AlignLeft);
     2650
     2651    setLayout(dlgLayout);
     2652    setWindowTitle("Flow Chart");
     2653    show();
     2654}
     2655
     2656//
     2657////////////////////////////////////////////////////////////////////////////
     2658bncFlowchartDlg::~bncFlowchartDlg() {
     2659};
     2660
     2661// Enable/Disable Widget (and change its color)
     2662////////////////////////////////////////////////////////////////////////////
     2663void bncWindow::enableWidget(bool enable, QWidget* widget) {
     2664
     2665    const static QPalette paletteWhite(QColor(255, 255, 255));
     2666    const static QPalette paletteGray(QColor(230, 230, 230));
     2667
     2668    widget->setEnabled(enable);
     2669    if (enable) {
     2670        widget->setPalette(paletteWhite);
     2671    }
     2672    else {
     2673        widget->setPalette(paletteGray);
     2674    }
     2675}
     2676
     2677//  Bnc Text
     2678////////////////////////////////////////////////////////////////////////////
     2679void bncWindow::slotBncTextChanged() {
     2680
     2681    const static QPalette paletteWhite(QColor(255, 255, 255));
     2682    const static QPalette paletteGray(QColor(230, 230, 230));
     2683
     2684    bool enable = true;
     2685
     2686    // Proxy
     2687    //------
     2688    if (sender() == 0 || sender() == _proxyHostLineEdit) {
     2689        enable = !_proxyHostLineEdit->text().isEmpty();
     2690        enableWidget(enable, _proxyPortLineEdit);
     2691    }
     2692
     2693    // RINEX Observations
     2694    // ------------------
     2695    if (sender() == 0 || sender() == _rnxPathLineEdit) {
     2696        enable = !_rnxPathLineEdit->text().isEmpty();
     2697        enableWidget(enable, _rnxIntrComboBox);
     2698        enableWidget(enable, _rnxSamplComboBox);
     2699        enableWidget(enable, _rnxSkelExtComboBox);
     2700        enableWidget(enable, _rnxSkelPathLineEdit);
     2701        enableWidget(enable, _rnxFileCheckBox);
     2702        enableWidget(enable, _rnxScrpLineEdit);
     2703        enableWidget(enable, _rnxV2Priority);
     2704        enableWidget(enable, _rnxVersComboBox);
     2705
     2706        bool enable1 = true;
     2707        enable1 = _rnxVersComboBox->currentText() == "2";
     2708        if (enable && enable1) {
     2709            enableWidget(true, _rnxV2Priority);
     2710        }
     2711        if (enable && !enable1) {
     2712            enableWidget(false, _rnxV2Priority);
     2713        }
     2714    }
     2715
     2716    // RINEX Observations, Signal Priority
     2717    // -----------------------------------
     2718    if (sender() == 0 || sender() == _rnxVersComboBox) {
     2719        if (!_rnxPathLineEdit->text().isEmpty()) {
     2720            enableWidget(enable, _rnxIntrComboBox);
     2721            enable = _rnxVersComboBox->currentText() == "2";
     2722            enableWidget(enable, _rnxV2Priority);
     2723        }
     2724    }
     2725
     2726    // RINEX Ephemeris
     2727    // ---------------
     2728    if (sender() == 0 || sender() == _ephPathLineEdit || sender() == _ephOutPortLineEdit) {
     2729        enable = !_ephPathLineEdit->text().isEmpty() || !_ephOutPortLineEdit->text().isEmpty();
     2730        enableWidget(enable, _ephIntrComboBox);
     2731        enableWidget(enable, _ephVersComboBox);
     2732        //enableWidget(enable, _ephVersComboBox);
     2733        //enableWidget(enable, _ephFilePerStation);
     2734    }
     2735
     2736    // Broadcast Corrections
     2737    // ---------------------
     2738    if (sender() == 0 || sender() == _corrPathLineEdit || sender() == _corrPortLineEdit) {
     2739        enable = !_corrPathLineEdit->text().isEmpty() || !_corrPortLineEdit->text().isEmpty();
     2740        enableWidget(enable, _corrIntrComboBox);
     2741    }
     2742
     2743    // Feed Engine
     2744    // -----------
     2745    if (sender() == 0 || sender() == _outPortLineEdit || sender() == _outFileLineEdit) {
     2746        enable = !_outPortLineEdit->text().isEmpty() || !_outFileLineEdit->text().isEmpty();
     2747        enableWidget(enable, _outWaitSpinBox);
     2748        enableWidget(enable, _outSamplComboBox);
     2749    }
     2750
     2751    // Serial Output
     2752    // -------------
     2753    if (sender() == 0 ||
     2754        sender() == _serialMountPointLineEdit ||
     2755        sender() == _serialAutoNMEAComboBox) {
     2756        enable = !_serialMountPointLineEdit->text().isEmpty();
     2757        enableWidget(enable, _serialPortNameLineEdit);
     2758        enableWidget(enable, _serialBaudRateComboBox);
     2759        enableWidget(enable, _serialParityComboBox);
     2760        enableWidget(enable, _serialDataBitsComboBox);
     2761        enableWidget(enable, _serialStopBitsComboBox);
     2762        enableWidget(enable, _serialFlowControlComboBox);
     2763        enableWidget(enable, _serialAutoNMEAComboBox);
     2764        if (enable && _serialAutoNMEAComboBox->currentText() == "Auto") {
     2765            enableWidget(true, _serialFileNMEALineEdit);
     2766            enableWidget(false, _serialHeightNMEALineEdit);
     2767            enableWidget(true, _serialNMEASamplingSpinBox);
     2768        }
     2769        else if (enable && _serialAutoNMEAComboBox->currentText().contains("Manual")) {
     2770            enableWidget(false, _serialFileNMEALineEdit);
     2771            enableWidget(true, _serialHeightNMEALineEdit);
     2772            enableWidget(true, _serialNMEASamplingSpinBox);
     2773        }
     2774        else {
     2775            enableWidget(false, _serialFileNMEALineEdit);
     2776            enableWidget(false, _serialHeightNMEALineEdit);
     2777            enableWidget(false, _serialNMEASamplingSpinBox);
     2778        }
     2779    }
     2780
     2781    // Outages
     2782    // -------
     2783    if (sender() == 0 || sender() == _adviseObsRateComboBox) {
     2784        enable = !_adviseObsRateComboBox->currentText().isEmpty();
     2785        enableWidget(enable, _adviseFailSpinBox);
     2786        enableWidget(enable, _adviseRecoSpinBox);
     2787        enableWidget(enable, _adviseScriptLineEdit);
     2788    }
     2789
     2790    // Miscellaneous
     2791    // -------------
     2792    if (sender() == 0 || sender() == _miscMountLineEdit) {
     2793        enable = !_miscMountLineEdit->text().isEmpty();
     2794        enableWidget(enable, _miscIntrComboBox);
     2795        enableWidget(enable, _miscScanRTCMCheckBox);
     2796        enableWidget(enable, _miscPortLineEdit);
     2797    }
     2798
     2799    // Combine Corrections
     2800    // -------------------
     2801    if (sender() == 0 || sender() == _cmbTable) {
     2802        int iRow = _cmbTable->rowCount();
     2803        if (iRow > 0) {
     2804            enableWidget(true, _cmbMethodComboBox);
     2805            enableWidget(true, _cmbMaxresLineEdit);
     2806            enableWidget(true, _cmbMaxdisplacementLineEdit);
     2807            enableWidget(true, _cmbSamplComboBox);
     2808            enableWidget(true, _cmbLogPath);
     2809            enableWidget(true, _cmbGpsCheckBox);
     2810            enableWidget(true, _cmbGloCheckBox);
     2811            enableWidget(true, _cmbGalCheckBox);
     2812            enableWidget(true, _cmbBdsCheckBox);
     2813            enableWidget(true, _cmbQzssCheckBox);
     2814            enableWidget(true, _cmbSbasCheckBox);
     2815            enableWidget(true, _cmbNavicCheckBox);
     2816            enableWidget(true, _cmbBsxFile);
     2817        }
     2818        else {
     2819            enableWidget(false, _cmbMethodComboBox);
     2820            enableWidget(false, _cmbMaxresLineEdit);
     2821            enableWidget(false, _cmbMaxdisplacementLineEdit);
     2822            enableWidget(false, _cmbSamplComboBox);
     2823            enableWidget(false, _cmbLogPath);
     2824            enableWidget(false, _cmbGpsCheckBox);
     2825            enableWidget(false, _cmbGloCheckBox);
     2826            enableWidget(false, _cmbGalCheckBox);
     2827            enableWidget(false, _cmbBdsCheckBox);
     2828            enableWidget(false, _cmbQzssCheckBox);
     2829            enableWidget(false, _cmbSbasCheckBox);
     2830            enableWidget(false, _cmbNavicCheckBox);
     2831            enableWidget(false, _cmbBsxFile);
     2832        }
     2833    }
     2834
     2835    // Upload(clk)
     2836    // -----------
     2837    int iRow = _uploadTable->rowCount();
     2838    if (iRow > 0) {
     2839        enableWidget(true, _uploadIntrComboBox);
     2840        enableWidget(true, _uploadSamplRtcmEphCorrComboBox);
     2841        enableWidget(true, _uploadSamplClkRnxSpinBox);
     2842        enableWidget(true, _uploadSamplBiaSnxSpinBox);
     2843        enableWidget(true, _uploadSamplSp3ComboBox);
     2844        enableWidget(true, _uploadAntexFile);
     2845    }
     2846    else {
     2847        enableWidget(false, _uploadIntrComboBox);
     2848        enableWidget(false, _uploadSamplRtcmEphCorrComboBox);
     2849        enableWidget(false, _uploadSamplClkRnxSpinBox);
     2850        enableWidget(false, _uploadSamplBiaSnxSpinBox);
     2851        enableWidget(false, _uploadSamplSp3ComboBox);
     2852        enableWidget(false, _uploadAntexFile);
     2853    }
     2854
     2855    // Upload(eph)
     2856    // -----------
     2857    iRow = _uploadEphTable->rowCount();
     2858    if (iRow > 0) {
     2859        enableWidget(true, _uploadSamplRtcmEphSpinBox);
     2860    }
     2861    else {
     2862        enableWidget(false, _uploadSamplRtcmEphSpinBox);
     2863    }
     2864
     2865    // QC
     2866    // --
     2867    if (sender() == 0 || sender() == _reqcActionComboBox || sender() == _reqcSkyPlotSignals) {
     2868        enable = !_reqcActionComboBox->currentText().isEmpty();
     2869        bool enable10 = _reqcActionComboBox->currentText() == "Edit/Concatenate";
     2870        //  bool enablePlot = !_reqcSkyPlotSignals->text().isEmpty();
     2871        enableWidget(enable, _reqcObsFileChooser);
     2872        enableWidget(enable, _reqcNavFileChooser);
     2873        enableWidget(enable, _reqcOutLogLineEdit);
     2874        enableWidget(enable && enable10, _reqcEditOptionButton);
     2875        enableWidget(enable && enable10, _reqcOutObsLineEdit);
     2876        enableWidget(enable && enable10, _reqcOutNavLineEdit);
     2877        enableWidget(enable && !enable10, _reqcLogSummaryOnly);
     2878        enableWidget(enable && !enable10, _reqcSkyPlotSignals);
     2879        //  enableWidget(enable && !enable10 && enablePlot, _reqcPlotDirLineEdit);
     2880        enableWidget(enable && !enable10, _reqcPlotDirLineEdit);
     2881    }
     2882
     2883    // SP3 File Comparison
     2884    // -------------------
     2885    if (sender() == 0 || sender() == _sp3CompFileChooser) {
     2886        enable = !_sp3CompFileChooser->fileName().isEmpty();
     2887        enableWidget(enable, _sp3CompLogLineEdit);
     2888        enableWidget(enable, _sp3CompExclude);
     2889        enableWidget(enable, _sp3CompSummaryOnly);
     2890    }
     2891
     2892    enableStartStop();
     2893}
     2894
     2895//
     2896////////////////////////////////////////////////////////////////////////////
     2897void bncWindow::slotAddCmbRow() {
     2898    int iRow = _cmbTable->rowCount();
     2899    _cmbTable->insertRow(iRow);
     2900    for (int iCol = 0; iCol < _cmbTable->columnCount(); iCol++) {
     2901        _cmbTable->setItem(iRow, iCol, new QTableWidgetItem(""));
     2902    }
     2903}
     2904
     2905//
     2906////////////////////////////////////////////////////////////////////////////
     2907void bncWindow::slotDelCmbRow() {
     2908
     2909    const static QPalette paletteWhite(QColor(255, 255, 255));
     2910    const static QPalette paletteGray(QColor(230, 230, 230));
     2911
     2912    int nRows = _cmbTable->rowCount();
     2913    std::vector <bool> flg(nRows);
     2914    for (int iRow = 0; iRow < nRows; iRow++) {
     2915        if (_cmbTable->item(iRow, 1)->isSelected()) {
     2916            flg[iRow] = true;
     2917        }
     2918        else {
     2919            flg[iRow] = false;
     2920        }
     2921    }
     2922    for (int iRow = nRows - 1; iRow >= 0; iRow--) {
     2923        if (flg[iRow]) {
     2924            _cmbTable->removeRow(iRow);
     2925        }
     2926    }
     2927    nRows = _cmbTable->rowCount();
     2928    if (nRows < 1) {
     2929        enableWidget(false, _cmbMethodComboBox);
     2930        enableWidget(false, _cmbMaxresLineEdit);
     2931        enableWidget(false, _cmbMaxdisplacementLineEdit);
     2932        enableWidget(false, _cmbSamplComboBox);
     2933        enableWidget(false, _cmbLogPath);
     2934    }
     2935}
     2936
     2937//
     2938////////////////////////////////////////////////////////////////////////////
     2939void bncWindow::populateCmbTable() {
     2940
     2941    for (int iRow = _cmbTable->rowCount() - 1; iRow >= 0; iRow--) {
     2942        _cmbTable->removeRow(iRow);
     2943    }
     2944
     2945    bncSettings settings;
     2946
     2947    int iRow = -1;
     2948    QListIterator<QString> it(settings.value("cmbStreams").toStringList());
     2949    while (it.hasNext()) {
     2950        QStringList hlp = it.next().split(" ");
     2951        if (hlp.size() > 2) {
     2952            ++iRow;
     2953            _cmbTable->insertRow(iRow);
     2954        }
     2955        for (int iCol = 0; iCol < hlp.size(); iCol++) {
     2956            _cmbTable->setItem(iRow, iCol, new QTableWidgetItem(hlp[iCol]));
     2957        }
     2958    }
     2959}
     2960
     2961//
     2962////////////////////////////////////////////////////////////////////////////
     2963void bncWindow::slotAddUploadRow() {
     2964    int iRow = _uploadTable->rowCount();
     2965    _uploadTable->insertRow(iRow);
     2966    for (int iCol = 0; iCol < _uploadTable->columnCount(); iCol++) {
     2967        if (iCol == 3) {
     2968            QComboBox* ntripversion = new QComboBox();
     2969            ntripversion->setEditable(false);
     2970            ntripversion->addItems(QString("1,2,2s").split(","));
     2971            ntripversion->setFrame(false);
     2972            _uploadTable->setCellWidget(iRow, iCol, ntripversion);
     2973
     2974        }
     2975        else if (iCol == 4) {
     2976            QLineEdit* user = new QLineEdit();
     2977            user->setFrame(false);
     2978            _uploadTable->setCellWidget(iRow, iCol, user);
     2979        }
     2980        else if (iCol == 5) {
     2981            QLineEdit* passwd = new QLineEdit();
     2982            passwd->setFrame(false);
     2983            passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
     2984            _uploadTable->setCellWidget(iRow, iCol, passwd);
     2985        }
     2986        else if (iCol == 6) {
     2987            QComboBox* system = new QComboBox();
     2988            system->setEditable(false);
     2989            system->addItems(QString("IGS20,ETRF2000,GDA2020,SIRGAS2000,DREF91,Custom").split(","));
     2990            system->setFrame(false);
     2991            _uploadTable->setCellWidget(iRow, iCol, system);
     2992        }
     2993        else if (iCol == 7) {
     2994            QComboBox* format = new QComboBox();
     2995            format->setEditable(false);
     2996            format->addItems(QString("IGS-SSR,RTCM-SSR").split(","));
     2997            format->setFrame(false);
     2998            _uploadTable->setCellWidget(iRow, iCol, format);
     2999        }
     3000        else if (iCol == 8) {
     3001            QCheckBox* com = new QCheckBox();
     3002            _uploadTable->setCellWidget(iRow, iCol, com);
     3003        }
     3004        else if (iCol == 15) {
     3005            bncTableItem* bncIt = new bncTableItem();
     3006            bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
     3007            _uploadTable->setItem(iRow, iCol, bncIt);
     3008            BNC_CORE->_uploadTableItems[iRow] = bncIt;
     3009        }
     3010        else {
     3011            _uploadTable->setItem(iRow, iCol, new QTableWidgetItem(""));
     3012        }
     3013    }
     3014}
     3015
     3016//
     3017////////////////////////////////////////////////////////////////////////////
     3018void bncWindow::slotDelUploadRow() {
     3019    BNC_CORE->_uploadTableItems.clear();
     3020    int nRows = _uploadTable->rowCount();
     3021    std::vector <bool> flg(nRows);
     3022    for (int iRow = 0; iRow < nRows; iRow++) {
     3023        if (_uploadTable->item(iRow, 1)->isSelected()) {
     3024            flg[iRow] = true;
     3025        }
     3026        else {
     3027            flg[iRow] = false;
     3028        }
     3029    }
     3030    for (int iRow = nRows - 1; iRow >= 0; iRow--) {
     3031        if (flg[iRow]) {
     3032            _uploadTable->removeRow(iRow);
     3033        }
     3034    }
     3035    for (int iRow = 0; iRow < _uploadTable->rowCount(); iRow++) {
     3036        BNC_CORE->_uploadTableItems[iRow] =
     3037            (bncTableItem*)_uploadTable->item(iRow, 14);
     3038    }
     3039    nRows = _uploadTable->rowCount();
     3040    if (nRows < 1) {
     3041        enableWidget(false, _uploadIntrComboBox);
     3042        enableWidget(false, _uploadSamplRtcmEphCorrComboBox);
     3043        enableWidget(false, _uploadSamplSp3ComboBox);
     3044        enableWidget(false, _uploadSamplClkRnxSpinBox);
     3045        enableWidget(false, _uploadAntexFile);
     3046    }
     3047}
     3048
     3049//
     3050////////////////////////////////////////////////////////////////////////////
     3051void bncWindow::populateUploadTable() {
     3052    for (int iRow = _uploadTable->rowCount() - 1; iRow >= 0; iRow--) {
     3053        _uploadTable->removeRow(iRow);
     3054    }
     3055
     3056    bncSettings settings;
     3057
     3058    int iRow = -1;
     3059    QListIterator<QString> it(settings.value("uploadMountpointsOut").toStringList());
     3060
     3061    while (it.hasNext()) {
     3062        QStringList hlp = it.next().split(",");
     3063        if (hlp.size() > 6) {
     3064            ++iRow;
     3065            _uploadTable->insertRow(iRow);
     3066        }
     3067        for (int iCol = 0; iCol < hlp.size(); iCol++) {
     3068            if (iCol == 3) {
     3069                QComboBox* ntripversion = new QComboBox();
     3070                ntripversion->setEditable(false);
     3071                ntripversion->addItems(QString("1,2,2s").split(","));
     3072                ntripversion->setFrame(false);
     3073                ntripversion->setCurrentIndex(ntripversion->findText(hlp[iCol]));
     3074                _uploadTable->setCellWidget(iRow, iCol, ntripversion);
     3075            }
     3076            else if (iCol == 4) {
     3077                QLineEdit* user = new QLineEdit();
     3078                user->setFrame(false);
     3079                user->setText(hlp[iCol]);
     3080                _uploadTable->setCellWidget(iRow, iCol, user);
     3081            }
     3082            else if (iCol == 5) {
     3083                QLineEdit* passwd = new QLineEdit();
     3084                passwd->setFrame(false);
     3085                passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
     3086                passwd->setText(hlp[iCol]);
     3087                _uploadTable->setCellWidget(iRow, iCol, passwd);
     3088            }
     3089            else if (iCol == 6) {
     3090                QComboBox* system = new QComboBox();
     3091                system->setEditable(false);
     3092                system->addItems(QString("IGS20,ETRF2000,GDA2020,SIRGAS2000,DREF91,Custom").split(","));
     3093                system->setFrame(false);
     3094                system->setCurrentIndex(system->findText(hlp[iCol]));
     3095                _uploadTable->setCellWidget(iRow, iCol, system);
     3096            }
     3097            else if (iCol == 7) {
     3098                QComboBox* format = new QComboBox();
     3099                format->setEditable(false);
     3100                format->addItems(QString("IGS-SSR,RTCM-SSR").split(","));
     3101                format->setFrame(false);
     3102                format->setCurrentIndex(format->findText(hlp[iCol]));
     3103                _uploadTable->setCellWidget(iRow, iCol, format);
     3104            }
     3105            else if (iCol == 8) {
     3106                QCheckBox* com = new QCheckBox();
     3107                if (hlp[iCol].toInt() == Qt::Checked) {
     3108                    com->setCheckState(Qt::Checked);
     3109                }
     3110                _uploadTable->setCellWidget(iRow, iCol, com);
     3111            }
     3112            else if (iCol == 15) {
     3113                bncTableItem* bncIt = new bncTableItem();
     3114                bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
     3115                _uploadTable->setItem(iRow, iCol, bncIt);
     3116                BNC_CORE->_uploadTableItems[iRow] = bncIt;
     3117            }
     3118            else {
     3119                _uploadTable->setItem(iRow, iCol, new QTableWidgetItem(hlp[iCol]));
     3120            }
     3121        }
     3122    }
     3123}
     3124
     3125//
     3126////////////////////////////////////////////////////////////////////////////
     3127void bncWindow::slotSetUploadTrafo() {
     3128    bncCustomTrafo* dlg = new bncCustomTrafo(this);
    19293129    dlg->exec();
    19303130    delete dlg;
    1931   } else if (msgBox.clickedButton() == buttonIP) {
    1932     bncIpPort* ipp = new bncIpPort(this);
    1933     connect(ipp, SIGNAL(newMountPoints(QStringList*)),
    1934           this, SLOT(slotNewMountPoints(QStringList*)));
    1935     ipp->exec();
    1936     delete ipp;
    1937   } else if (msgBox.clickedButton() == buttonUDP) {
    1938     bncUdpPort* udp = new bncUdpPort(this);
    1939     connect(udp, SIGNAL(newMountPoints(QStringList*)),
    1940           this, SLOT(slotNewMountPoints(QStringList*)));
    1941     udp->exec();
    1942     delete udp;
    1943   } else if (msgBox.clickedButton() == buttonSerial) {
    1944     bncSerialPort* sep = new bncSerialPort(this);
    1945     connect(sep, SIGNAL(newMountPoints(QStringList*)),
    1946           this, SLOT(slotNewMountPoints(QStringList*)));
    1947     sep->exec();
    1948     delete sep;
    1949   } else if (msgBox.clickedButton() == buttonCancel) {
    1950     // Cancel
    1951   }
    1952 
    1953   enableStartStop();
    1954 }
    1955 
    1956 // Delete Selected Mount Points
    1957 ////////////////////////////////////////////////////////////////////////////
    1958 void bncWindow::slotDeleteMountPoints() {
    1959 
    1960   int nRows = _mountPointsTable->rowCount();
    1961   std::vector <bool> flg(nRows);
    1962   for (int iRow = 0; iRow < nRows; iRow++) {
    1963     if (_mountPointsTable->item(iRow,1)->isSelected()) {
    1964       flg[iRow] = true;
     3131}
     3132
     3133//
     3134////////////////////////////////////////////////////////////////////////////
     3135void bncWindow::slotAddUploadEphRow() {
     3136    int iRow = _uploadEphTable->rowCount();
     3137    _uploadEphTable->insertRow(iRow);
     3138    for (int iCol = 0; iCol < _uploadEphTable->columnCount(); iCol++) {
     3139        if (iCol == 3) {
     3140            QComboBox* ntripversion = new QComboBox();
     3141            ntripversion->setEditable(false);
     3142            ntripversion->addItems(QString("1,2,2s").split(","));
     3143            ntripversion->setFrame(false);
     3144            _uploadEphTable->setCellWidget(iRow, iCol, ntripversion);
     3145
     3146        }
     3147        else if (iCol == 4) {
     3148            QLineEdit* user = new QLineEdit();
     3149            user->setFrame(false);
     3150            _uploadEphTable->setCellWidget(iRow, iCol, user);
     3151        }
     3152        else if (iCol == 5) {
     3153            QLineEdit* passwd = new QLineEdit();
     3154            passwd->setFrame(false);
     3155            passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
     3156            _uploadEphTable->setCellWidget(iRow, iCol, passwd);
     3157        }
     3158        else if (iCol == 6) {
     3159            QLineEdit* system = new QLineEdit("GREC");
     3160            system->setFrame(false);
     3161            _uploadEphTable->setCellWidget(iRow, iCol, system);
     3162        }
     3163        else if (iCol == 7) {
     3164            bncTableItem* bncIt = new bncTableItem();
     3165            bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
     3166            _uploadEphTable->setItem(iRow, iCol, bncIt);
     3167            BNC_CORE->_uploadEphTableItems[iRow] = bncIt;
     3168        }
     3169        else {
     3170            _uploadEphTable->setItem(iRow, iCol, new QTableWidgetItem(""));
     3171        }
     3172    }
     3173}
     3174
     3175//
     3176////////////////////////////////////////////////////////////////////////////
     3177void bncWindow::slotDelUploadEphRow() {
     3178    BNC_CORE->_uploadTableItems.clear();
     3179    int nRows = _uploadEphTable->rowCount();
     3180    std::vector <bool> flg(nRows);
     3181    for (int iRow = 0; iRow < nRows; iRow++) {
     3182        if (_uploadEphTable->item(iRow, 1)->isSelected()) {
     3183            flg[iRow] = true;
     3184        }
     3185        else {
     3186            flg[iRow] = false;
     3187        }
     3188    }
     3189    for (int iRow = nRows - 1; iRow >= 0; iRow--) {
     3190        if (flg[iRow]) {
     3191            _uploadEphTable->removeRow(iRow);
     3192        }
     3193    }
     3194    for (int iRow = 0; iRow < _uploadTable->rowCount(); iRow++) {
     3195        BNC_CORE->_uploadTableItems[iRow] =
     3196            (bncTableItem*)_uploadEphTable->item(iRow, 7);
     3197    }
     3198    nRows = _uploadEphTable->rowCount();
     3199    if (nRows < 1) {
     3200        enableWidget(false, _uploadSamplRtcmEphSpinBox);
     3201    }
     3202}
     3203
     3204//
     3205////////////////////////////////////////////////////////////////////////////
     3206void bncWindow::populateUploadEphTable() {
     3207    for (int iRow = _uploadEphTable->rowCount() - 1; iRow >= 0; iRow--) {
     3208        _uploadEphTable->removeRow(iRow);
     3209    }
     3210
     3211    bncSettings settings;
     3212
     3213    int iRow = -1;
     3214    QListIterator<QString> it(settings.value("uploadEphMountpointsOut").toStringList());
     3215    while (it.hasNext()) {
     3216        QStringList hlp = it.next().split(",");
     3217        if (hlp.size() > 6) {
     3218            ++iRow;
     3219            _uploadEphTable->insertRow(iRow);
     3220        }
     3221        for (int iCol = 0; iCol < hlp.size(); iCol++) {
     3222            if (iCol == 3) {
     3223                QComboBox* ntripversion = new QComboBox();
     3224                ntripversion->setEditable(false);
     3225                ntripversion->addItems(QString("1,2,2s").split(","));
     3226                ntripversion->setFrame(false);
     3227                ntripversion->setCurrentIndex(ntripversion->findText(hlp[iCol]));
     3228                _uploadEphTable->setCellWidget(iRow, iCol, ntripversion);
     3229            }
     3230            else if (iCol == 4) {
     3231                QLineEdit* user = new QLineEdit();
     3232                user->setFrame(false);
     3233                user->setText(hlp[iCol]);
     3234                _uploadEphTable->setCellWidget(iRow, iCol, user);
     3235            }
     3236            else if (iCol == 5) {
     3237                QLineEdit* passwd = new QLineEdit();
     3238                passwd->setFrame(false);
     3239                passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
     3240                passwd->setText(hlp[iCol]);
     3241                _uploadEphTable->setCellWidget(iRow, iCol, passwd);
     3242            }
     3243            else if (iCol == 6) {
     3244                QLineEdit* system = new QLineEdit();
     3245                system->setFrame(false);
     3246                system->setText(hlp[iCol]);
     3247                _uploadEphTable->setCellWidget(iRow, iCol, system);
     3248            }
     3249            else if (iCol == 7) {
     3250                bncTableItem* bncIt = new bncTableItem();
     3251                bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
     3252                _uploadEphTable->setItem(iRow, iCol, bncIt);
     3253                BNC_CORE->_uploadEphTableItems[iRow] = bncIt;
     3254            }
     3255            else {
     3256                _uploadEphTable->setItem(iRow, iCol, new QTableWidgetItem(hlp[iCol]));
     3257            }
     3258        }
     3259    }
     3260}
     3261
     3262
     3263// Progress Bar Change
     3264////////////////////////////////////////////////////////////////////////////
     3265void bncWindow::slotPostProcessingProgress(int nEpo) {
     3266    _actStart->setText(QString("%1 Epochs").arg(nEpo));
     3267}
     3268
     3269// Post-Processing Reqc Finished
     3270////////////////////////////////////////////////////////////////////////////
     3271void bncWindow::slotPostProcessingFinished() {
     3272    delete _caster; _caster = 0; BNC_CORE->setCaster(0);
     3273    _runningPPP = false;
     3274    _runningEdit = false;
     3275    _runningQC = false;
     3276    _runningSp3Comp = false;
     3277    _actStart->setText(tr("Sta&rt"));
     3278    enableStartStop();
     3279}
     3280
     3281// Edit teqc-like editing options
     3282////////////////////////////////////////////////////////////////////////////
     3283void bncWindow::slotReqcEditOption() {
     3284    saveOptions();
     3285    reqcDlg* dlg = new reqcDlg(this);
     3286    dlg->move(this->pos().x() + 50, this->pos().y() + 50);
     3287    dlg->exec();
     3288    delete dlg;
     3289}
     3290
     3291// Enable/Disable Start and Stop Buttons
     3292////////////////////////////////////////////////////////////////////////////
     3293void bncWindow::enableStartStop() {
     3294
     3295    if (running()) {
     3296        _actStart->setEnabled(false);
     3297        if (_runningRealTime || _runningPPP) {
     3298            _actStop->setEnabled(true);
     3299        }
    19653300    }
    19663301    else {
    1967       flg[iRow] = false;
    1968     }
    1969   }
    1970   for (int iRow = nRows-1; iRow >= 0; iRow--) {
    1971     if (flg[iRow]) {
    1972       _mountPointsTable->removeRow(iRow);
    1973     }
    1974   }
    1975   _actDeleteMountPoints->setEnabled(false);
    1976 
    1977   enableStartStop();
    1978 }
    1979 
    1980 // New Mount Points Selected
    1981 ////////////////////////////////////////////////////////////////////////////
    1982 void bncWindow::slotNewMountPoints(QStringList* mountPoints) {
    1983   int iRow = 0;
    1984   QListIterator<QString> it(*mountPoints);
    1985   while (it.hasNext()) {
    1986     QStringList hlp = it.next().split(" ");
    1987     QUrl    url(hlp[0]);
    1988     QString fullPath = url.host() + QString(":%1").arg(url.port()) + url.path();
    1989     QString format(hlp[1]); QString country(hlp[2]); QString latitude(hlp[3]); QString longitude(hlp[4]);
    1990     QString nmea(hlp[5]);
    1991     if (hlp[6] == "S") {
    1992       fullPath = hlp[0].replace(0,2,"");
    1993     }
    1994     QString ntripVersion = "2";
    1995     if (hlp.size() >= 7) {
    1996       ntripVersion = (hlp[6]);
    1997     }
    1998 
    1999     _mountPointsTable->insertRow(iRow);
    2000 
    2001     QTableWidgetItem* it;
    2002     it = new QTableWidgetItem(url.userInfo());
    2003     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    2004     _mountPointsTable->setItem(iRow, 0, it);
    2005 
    2006     it = new QTableWidgetItem(fullPath);
    2007     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    2008     _mountPointsTable->setItem(iRow, 1, it);
    2009 
    2010     it = new QTableWidgetItem(format);
    2011     _mountPointsTable->setItem(iRow, 2, it);
    2012 
    2013     it = new QTableWidgetItem(country);
    2014     _mountPointsTable->setItem(iRow, 3, it);
    2015 
    2016     if      (nmea == "yes") {
    2017     it = new QTableWidgetItem(latitude);
    2018     _mountPointsTable->setItem(iRow, 4, it);
    2019     it = new QTableWidgetItem(longitude);
    2020     _mountPointsTable->setItem(iRow, 5, it);
    2021     } else {
    2022     it = new QTableWidgetItem(latitude);
    2023     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    2024     _mountPointsTable->setItem(iRow, 4, it);
    2025     it = new QTableWidgetItem(longitude);
    2026     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    2027     _mountPointsTable->setItem(iRow, 5, it);
    2028     }
    2029 
    2030     it = new QTableWidgetItem(nmea);
    2031     it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    2032     _mountPointsTable->setItem(iRow, 6, it);
    2033 
    2034     it = new QTableWidgetItem(ntripVersion);
    2035     ////it->setFlags(it->flags() & ~Qt::ItemIsEditable);
    2036     _mountPointsTable->setItem(iRow, 7, it);
    2037 
    2038     bncTableItem* bncIt = new bncTableItem();
    2039     _mountPointsTable->setItem(iRow, 8, bncIt);
    2040 
    2041     iRow++;
    2042   }
    2043   _mountPointsTable->hideColumn(0);
    2044   _mountPointsTable->hideColumn(3);
    2045   _mountPointsTable->sortItems(1);
    2046   delete mountPoints;
    2047 
    2048   enableStartStop();
    2049 }
    2050 
    2051 // Save Options (serialize)
    2052 ////////////////////////////////////////////////////////////////////////////
    2053 void bncWindow::slotSaveOptions() {
    2054   saveOptions();
    2055   bncSettings settings;
    2056   settings.sync();
    2057 }
    2058 
    2059 // Save Options (memory only)
    2060 ////////////////////////////////////////////////////////////////////////////
    2061 void bncWindow::saveOptions() {
    2062 
    2063   QStringList mountPoints;
    2064   for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
    2065 
    2066     if (_mountPointsTable->item(iRow, 6)->text() != "S") {
    2067       QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
    2068                 "@"  + _mountPointsTable->item(iRow, 1)->text() );
    2069 
    2070       mountPoints.append(url.toString() + " " +
    2071                          _mountPointsTable->item(iRow, 2)->text()
    2072                  + " " + _mountPointsTable->item(iRow, 3)->text()
    2073                  + " " + _mountPointsTable->item(iRow, 4)->text()
    2074                  + " " + _mountPointsTable->item(iRow, 5)->text()
    2075                  + " " + _mountPointsTable->item(iRow, 6)->text()
    2076                  + " " + _mountPointsTable->item(iRow, 7)->text());
    2077     } else {
    2078       mountPoints.append(
    2079                   "//" + _mountPointsTable->item(iRow, 1)->text()
    2080                  + " " + _mountPointsTable->item(iRow, 2)->text()
    2081                  + " " + _mountPointsTable->item(iRow, 3)->text()
    2082                  + " " + _mountPointsTable->item(iRow, 4)->text()
    2083                  + " " + _mountPointsTable->item(iRow, 5)->text()
    2084                  + " " + _mountPointsTable->item(iRow, 6)->text()
    2085                  + " " + _mountPointsTable->item(iRow, 7)->text());
    2086     }
    2087   }
    2088 
    2089   QStringList cmbStreams;
    2090   for (int iRow = 0; iRow < _cmbTable->rowCount(); iRow++) {
    2091     QString hlp;
    2092     for (int iCol = 0; iCol < _cmbTable->columnCount(); iCol++) {
    2093       if (_cmbTable->item(iRow, iCol)) {
    2094         hlp += _cmbTable->item(iRow, iCol)->text() + " ";
    2095       }
    2096     }
    2097     if (!hlp.isEmpty()) {
    2098       cmbStreams << hlp;
    2099     }
    2100   }
    2101 
    2102   QStringList uploadMountpointsOut;
    2103   for (int iRow = 0; iRow < _uploadTable->rowCount(); iRow++) {
    2104     QString hlp;
    2105     for (int iCol = 0; iCol < _uploadTable->columnCount(); iCol++) {
    2106       if (_uploadTable->cellWidget(iRow, iCol) &&
    2107           (iCol == 3 || iCol == 4 || iCol == 5 || iCol == 6 || iCol == 7 || iCol == 8)) {
    2108         if       (iCol == 3) {
    2109           QComboBox* ntripversion = (QComboBox*)(_uploadTable->cellWidget(iRow, iCol));
    2110           hlp += ntripversion->currentText() + ",";
    2111         }
    2112         else if (iCol == 4 ) {
    2113           QLineEdit* user = (QLineEdit*)(_uploadTable->cellWidget(iRow, iCol));
    2114           hlp += user->text() + ",";
    2115         }
    2116         else if (iCol == 5) {
    2117           QLineEdit* passwd = (QLineEdit*)(_uploadTable->cellWidget(iRow, iCol));
    2118           hlp += passwd->text() + ",";
    2119         }
    2120         else if (iCol == 6) {
    2121           QComboBox* system = (QComboBox*)(_uploadTable->cellWidget(iRow, iCol));
    2122           hlp += system->currentText() + ",";
    2123         }
    2124         else if (iCol == 7) {
    2125           QComboBox* format = (QComboBox*)(_uploadTable->cellWidget(iRow, iCol));
    2126           hlp += format->currentText() + ",";
    2127         }
    2128         else if (iCol == 8) {
    2129           QCheckBox* com    = (QCheckBox*)(_uploadTable->cellWidget(iRow, iCol));
    2130           QString state; state.setNum(com->checkState());
    2131           hlp +=  state + ",";
    2132         }
    2133       }
    2134       else if (_uploadTable->item(iRow, iCol)) {
    2135         hlp += _uploadTable->item(iRow, iCol)->text() + ",";
    2136       }
    2137     }
    2138     if (!hlp.isEmpty()) {
    2139       uploadMountpointsOut << hlp;
    2140     }
    2141   }
    2142 
    2143   QStringList uploadEphMountpointsOut;
    2144   for (int iRow = 0; iRow < _uploadEphTable->rowCount(); iRow++) {
    2145     QString hlp;
    2146     for (int iCol = 0; iCol < _uploadEphTable->columnCount(); iCol++) {
    2147       if (_uploadEphTable->cellWidget(iRow, iCol) &&
    2148           (iCol == 3 || iCol == 4 || iCol == 5 || iCol == 6)) {
    2149         if       (iCol == 3) {
    2150           QComboBox* ntripversion = (QComboBox*)(_uploadEphTable->cellWidget(iRow, iCol));
    2151           hlp += ntripversion->currentText() + ",";
    2152         }
    2153         else if (iCol == 4 ) {
    2154           QLineEdit* user = (QLineEdit*)(_uploadEphTable->cellWidget(iRow, iCol));
    2155           hlp += user->text() + ",";
    2156         }
    2157         else if (iCol == 5) {
    2158           QLineEdit* passwd = (QLineEdit*)(_uploadEphTable->cellWidget(iRow, iCol));
    2159           hlp += passwd->text() + ",";
    2160         }
    2161         else if (iCol == 6) {
    2162           QLineEdit* system = (QLineEdit*)(_uploadEphTable->cellWidget(iRow, iCol));
    2163           hlp += system->text() + ",";
    2164         }
    2165       }
    2166       else if (_uploadEphTable->item(iRow, iCol)) {
    2167         hlp += _uploadEphTable->item(iRow, iCol)->text() + ",";
    2168       }
    2169     }
    2170     if (!hlp.isEmpty()) {
    2171       uploadEphMountpointsOut << hlp;
    2172     }
    2173   }
    2174 
    2175   bncSettings settings;
    2176 
    2177   settings.setValue("startTab",    _aogroup->currentIndex());
    2178   settings.setValue("statusTab",   _loggroup->currentIndex());
    2179   settings.setValue("mountPoints", mountPoints);
    2180 // Network
    2181   settings.setValue("proxyHost",   _proxyHostLineEdit->text());
    2182   settings.setValue("proxyPort",   _proxyPortLineEdit->text());
    2183   settings.setValue("sslCaCertPath",   _sslCaCertPathLineEdit->text());
    2184   settings.setValue("sslClientCertPath", _sslClientCertPathLineEdit->text());
    2185   settings.setValue("sslIgnoreErrors", _sslIgnoreErrorsCheckBox->checkState());
    2186 // General
    2187   settings.setValue("logFile",     _logFileLineEdit->text());
    2188   settings.setValue("rnxAppend",   _rnxAppendCheckBox->checkState());
    2189   settings.setValue("onTheFlyInterval", _onTheFlyComboBox->currentText());
    2190   settings.setValue("autoStart",   _autoStartCheckBox->checkState());
    2191   settings.setValue("rawOutFile",  _rawOutFileLineEdit->text());
    2192 // RINEX Observations
    2193   settings.setValue("rnxPath",      _rnxPathLineEdit->text());
    2194   settings.setValue("rnxIntr",      _rnxIntrComboBox->currentText());
    2195   settings.setValue("rnxSampl",     _rnxSamplComboBox->currentText());
    2196   settings.setValue("rnxSkel",      _rnxSkelExtComboBox->currentText());
    2197   settings.setValue("rnxSkelPath",  _rnxSkelPathLineEdit->text());
    2198   settings.setValue("rnxOnlyWithSKL",_rnxFileCheckBox->checkState());
    2199   settings.setValue("rnxScript",    _rnxScrpLineEdit->text());
    2200   settings.setValue("rnxV2Priority",_rnxV2Priority->text());
    2201   settings.setValue("rnxVersion",   _rnxVersComboBox->currentText());
    2202 // RINEX Ephemeris
    2203   settings.setValue("ephPath",       _ephPathLineEdit->text());
    2204   settings.setValue("ephIntr",       _ephIntrComboBox->currentText());
    2205   settings.setValue("ephOutPort",    _ephOutPortLineEdit->text());
    2206   settings.setValue("ephVersion",    _ephVersComboBox->currentText());
    2207   //settings.setValue("ephFilePerStation", _ephFilePerStation->checkState());
    2208 // Broadcast Corrections
    2209   settings.setValue("corrPath",    _corrPathLineEdit->text());
    2210   settings.setValue("corrIntr",    _corrIntrComboBox->currentText());
    2211   settings.setValue("corrPort",    _corrPortLineEdit->text());
    2212 // Feed Engine
    2213   settings.setValue("outPort",     _outPortLineEdit->text());
    2214   settings.setValue("outWait",     _outWaitSpinBox->value());
    2215   settings.setValue("outSampl",    _outSamplComboBox->currentText());
    2216   settings.setValue("outFile",     _outFileLineEdit->text());
    2217   settings.setValue("outLockTime",_outLockTimeCheckBox->checkState());    settings.setValue("outUPort",    _outUPortLineEdit->text());
    2218 // Serial Output
    2219   settings.setValue("serialMountPoint",_serialMountPointLineEdit->text());
    2220   settings.setValue("serialPortName",  _serialPortNameLineEdit->text());
    2221   settings.setValue("serialBaudRate",  _serialBaudRateComboBox->currentText());
    2222   settings.setValue("serialFlowControl",_serialFlowControlComboBox->currentText());
    2223   settings.setValue("serialDataBits",  _serialDataBitsComboBox->currentText());
    2224   settings.setValue("serialParity",    _serialParityComboBox->currentText());
    2225   settings.setValue("serialStopBits",  _serialStopBitsComboBox->currentText());
    2226   settings.setValue("serialAutoNMEA",  _serialAutoNMEAComboBox->currentText());
    2227   settings.setValue("serialFileNMEA",    _serialFileNMEALineEdit->text());
    2228   settings.setValue("serialHeightNMEA",  _serialHeightNMEALineEdit->text());
    2229   settings.setValue("serialNMEASampling", _serialNMEASamplingSpinBox->value());
    2230 // Outages
    2231   settings.setValue("adviseObsRate", _adviseObsRateComboBox->currentText());
    2232   settings.setValue("adviseFail",    _adviseFailSpinBox->value());
    2233   settings.setValue("adviseReco",    _adviseRecoSpinBox->value());
    2234   settings.setValue("adviseScript",  _adviseScriptLineEdit->text());
    2235 // Miscellaneous
    2236   settings.setValue("miscMount",   _miscMountLineEdit->text());
    2237   settings.setValue("miscPort",    _miscPortLineEdit->text());
    2238   settings.setValue("miscIntr",    _miscIntrComboBox->currentText());
    2239   settings.setValue("miscScanRTCM", _miscScanRTCMCheckBox->checkState());
    2240 // Reqc
    2241   settings.setValue("reqcAction",     _reqcActionComboBox->currentText());
    2242   settings.setValue("reqcObsFile",    _reqcObsFileChooser->fileName());
    2243   settings.setValue("reqcNavFile",    _reqcNavFileChooser->fileName());
    2244   settings.setValue("reqcOutObsFile", _reqcOutObsLineEdit->text());
    2245   settings.setValue("reqcOutNavFile", _reqcOutNavLineEdit->text());
    2246   settings.setValue("reqcOutLogFile", _reqcOutLogLineEdit->text());
    2247   settings.setValue("reqcPlotDir",    _reqcPlotDirLineEdit->text());
    2248   settings.setValue("reqcSkyPlotSignals", _reqcSkyPlotSignals->text());
    2249   settings.setValue("reqcLogSummaryOnly", _reqcLogSummaryOnly->checkState());
    2250 // SP3 Comparison
    2251   settings.setValue("sp3CompFile",       _sp3CompFileChooser->fileName());
    2252   settings.setValue("sp3CompExclude",    _sp3CompExclude->text());
    2253   settings.setValue("sp3CompOutLogFile", _sp3CompLogLineEdit->text());
    2254   settings.setValue("sp3CompSummaryOnly",_sp3CompSummaryOnly->checkState());
    2255 // Combine Corrections
    2256   if (!cmbStreams.isEmpty()) {
    2257     settings.setValue("cmbStreams", cmbStreams);
    2258   }
    2259   else {
    2260     settings.setValue("cmbStreams", "");
    2261   }
    2262   settings.setValue("cmbMethod",          _cmbMethodComboBox->currentText());
    2263   settings.setValue("cmbMaxres",          _cmbMaxresLineEdit->text());
    2264   settings.setValue("cmbMaxdisplacement", _cmbMaxdisplacementLineEdit->text());
    2265   settings.setValue("cmbSampl",           _cmbSamplSpinBox->value());
    2266   settings.setValue("cmbLogpath",         _cmbLogPath->text());
    2267   settings.setValue("cmbGps",             _cmbGpsCheckBox->checkState());
    2268   settings.setValue("cmbGlo",             _cmbGloCheckBox->checkState());
    2269   settings.setValue("cmbGal",             _cmbGalCheckBox->checkState());
    2270   settings.setValue("cmbBds",             _cmbBdsCheckBox->checkState());
    2271   settings.setValue("cmbQzss",            _cmbQzssCheckBox->checkState());
    2272   settings.setValue("cmbSbas",            _cmbSbasCheckBox->checkState());
    2273   settings.setValue("cmbNavic",           _cmbNavicCheckBox->checkState());
    2274   settings.setValue("cmbBsxFile",         _cmbBsxFile->fileName());
    2275 
    2276 // Upload Corrections
    2277   if (!uploadMountpointsOut.isEmpty()) {
    2278     settings.setValue("uploadMountpointsOut", uploadMountpointsOut);
    2279   }
    2280   else {
    2281     settings.setValue("uploadMountpointsOut", "");
    2282   }
    2283   settings.setValue("uploadIntr",             _uploadIntrComboBox->currentText());
    2284   settings.setValue("uploadSamplRtcmEphCorr", _uploadSamplRtcmEphCorrSpinBox->value());
    2285   settings.setValue("uploadSamplSp3",         _uploadSamplSp3ComboBox->currentText());
    2286   settings.setValue("uploadSamplClkRnx",      _uploadSamplClkRnxSpinBox->value());
    2287   settings.setValue("uploadSamplBiaSnx",      _uploadSamplBiaSnxSpinBox->value());
    2288   settings.setValue("uploadAntexFile",        _uploadAntexFile->fileName());
    2289 // Upload Ephemeris
    2290   if (!uploadEphMountpointsOut.isEmpty()) {
    2291     settings.setValue("uploadEphMountpointsOut", uploadEphMountpointsOut);
    2292   }
    2293   else {
    2294     settings.setValue("uploadEphMountpointsOut", "");
    2295   }
    2296   settings.setValue("uploadSamplRtcmEph", _uploadSamplRtcmEphSpinBox->value());
    2297 
    2298   if (_caster) {
    2299     _caster->readMountPoints();
    2300   }
    2301 
    2302   _pppWidgets.saveOptions();
    2303 }
    2304 
    2305 // All get slots terminated
    2306 ////////////////////////////////////////////////////////////////////////////
    2307 void bncWindow::slotGetThreadsFinished() {
    2308   BNC_CORE->slotMessage("All Get Threads Terminated", true);
    2309   delete _caster;    _caster    = 0; BNC_CORE->setCaster(0);
    2310   delete _casterEph; _casterEph = 0;
    2311   _runningRealTime = false;
    2312   enableStartStop();
    2313 }
    2314 
    2315 // Start It!
    2316 ////////////////////////////////////////////////////////////////////////////
    2317 void bncWindow::slotStart() {
    2318   saveOptions();
    2319   if      ( _pppWidgets._dataSource->currentText() == "RINEX Files") {
    2320     _runningPPP = true;
    2321     enableStartStop();
    2322     _caster = new bncCaster(); BNC_CORE->setCaster(_caster);
    2323     BNC_CORE->startPPP();
    2324     _bncFigurePPP->reset();
    2325   }
    2326   else if ( !_reqcActionComboBox->currentText().isEmpty() ) {
    2327     if (_reqcActionComboBox->currentText() == "Analyze") {
    2328       _runningQC = true;
    2329       t_reqcAnalyze* reqcAnalyze = new t_reqcAnalyze(this);
    2330       connect(reqcAnalyze, SIGNAL(finished()), this, SLOT(slotPostProcessingFinished()));
    2331       reqcAnalyze->start();
    2332     }
    2333     else {
    2334       _runningEdit = true;
    2335       t_reqcEdit* reqcEdit = new t_reqcEdit(this);
    2336       connect(reqcEdit, SIGNAL(finished()), this, SLOT(slotPostProcessingFinished()));
    2337       reqcEdit->start();
    2338     }
    2339     enableStartStop();
    2340   }
    2341   else if (!_sp3CompFileChooser->fileName().isEmpty()) {
    2342     _runningSp3Comp = true;
    2343     t_sp3Comp* sp3Comp = new t_sp3Comp(this);
    2344     connect(sp3Comp, SIGNAL(finished()), this, SLOT(slotPostProcessingFinished()));
    2345     sp3Comp->start();
    2346     enableStartStop();
    2347   }
    2348   else {
    2349     startRealTime();
    2350     BNC_CORE->startPPP();
    2351   }
    2352 }
    2353 
    2354 // Start Real-Time (Retrieve Data etc.)
    2355 ////////////////////////////////////////////////////////////////////////////
    2356 void bncWindow::startRealTime() {
    2357 
    2358   _runningRealTime = true;
    2359 
    2360   _bncFigurePPP->reset();
    2361 
    2362   _actDeleteMountPoints->setEnabled(false);
    2363 
    2364   enableStartStop();
    2365 
    2366   _caster = new bncCaster();
    2367 
    2368   BNC_CORE->setCaster(_caster);
    2369   BNC_CORE->setPortEph(_ephOutPortLineEdit->text().toInt());
    2370   BNC_CORE->setPortCorr(_corrPortLineEdit->text().toInt());
    2371   BNC_CORE->initCombination();
    2372 
    2373   connect(_caster, SIGNAL(getThreadsFinished()), this, SLOT(slotGetThreadsFinished()));
    2374 
    2375   connect(_caster, SIGNAL(mountPointsRead(QList<bncGetThread*>)), this, SLOT(slotMountPointsRead(QList<bncGetThread*>)));
    2376 
    2377   BNC_CORE->slotMessage("========== Start BNC v" BNCVERSION " (" BNC_OS ") ==========", true);
    2378 
    2379   bncSettings settings;
    2380 
    2381   // Active panels
    2382   // -------------
    2383   if (!_rnxPathLineEdit->text().isEmpty())
    2384       BNC_CORE->slotMessage("Panel 'RINEX Observations' active", true);
    2385   if (!_ephPathLineEdit->text().isEmpty())
    2386       BNC_CORE->slotMessage("Panel 'RINEX Ephemeris' active", true);
    2387   if (!_corrPathLineEdit->text().isEmpty())
    2388       BNC_CORE->slotMessage("Panel 'Broadcast Corrections' active", true);
    2389   if (!_outPortLineEdit->text().isEmpty())
    2390       BNC_CORE->slotMessage("Panel 'Feed Engine' active", true);
    2391   if (!_serialMountPointLineEdit->text().isEmpty())
    2392       BNC_CORE->slotMessage("Panel 'Serial Output' active", true);
    2393   if (!_adviseObsRateComboBox->currentText().isEmpty())
    2394       BNC_CORE->slotMessage("Panel 'Outages' active", true);
    2395   if (!_miscMountLineEdit->text().isEmpty())
    2396       BNC_CORE->slotMessage("Panel 'Miscellaneous' active", true);
    2397   if (_pppWidgets._dataSource->currentText() == "Real-Time Streams")
    2398       BNC_CORE->slotMessage("Panel 'PPP' active", true);
    2399   if (_cmbTable->rowCount() > 0)
    2400       BNC_CORE->slotMessage("Panel 'Combine Corrections' active", true);
    2401   if (_uploadTable->rowCount() > 0)
    2402       BNC_CORE->slotMessage("Panel 'Upload Corrections' active", true);
    2403   if (_uploadEphTable->rowCount() > 0)
    2404       BNC_CORE->slotMessage("Panel 'UploadEphemeris' active", true);
    2405 
    2406   QDir rnxdir(settings.value("rnxPath").toString());
    2407   if (!rnxdir.exists()) BNC_CORE->slotMessage("Cannot find RINEX Observations directory", true);
    2408 
    2409   QString rnx_file = settings.value("rnxScript").toString();
    2410   if ( !rnx_file.isEmpty() ) {
    2411     QFile rnxfile(settings.value("rnxScript").toString());
    2412     if (!rnxfile.exists()) BNC_CORE->slotMessage("Cannot find RINEX Observations script", true);
    2413   }
    2414 
    2415   QDir ephdir(settings.value("ephPath").toString());
    2416   if (!ephdir.exists()) BNC_CORE->slotMessage("Cannot find RINEX Ephemeris directory", true);
    2417 
    2418   QDir corrdir(settings.value("corrPath").toString());
    2419   if (!corrdir.exists()) BNC_CORE->slotMessage("Cannot find Broadcast Corrections directory", true);
    2420 
    2421   QString advise_file = settings.value("adviseScript").toString();
    2422   if ( !advise_file.isEmpty() ) {
    2423     QFile advisefile(settings.value("adviseScript").toString());
    2424     if (!advisefile.exists()) BNC_CORE->slotMessage("Cannot find Outages script", true);
    2425   }
    2426 
    2427   _caster->readMountPoints();
    2428 
    2429   _casterEph = new bncEphUploadCaster();
    2430 }
    2431 
    2432 // Retrieve Data
    2433 ////////////////////////////////////////////////////////////////////////////
    2434 void bncWindow::slotStop() {
    2435   int iRet = QMessageBox::question(this, "Stop", "Stop retrieving/processing data?",
    2436                                    QMessageBox::Yes, QMessageBox::No,
    2437                                    QMessageBox::NoButton);
    2438   if (iRet == QMessageBox::Yes) {
    2439     BNC_CORE->stopPPP();
    2440     BNC_CORE->stopCombination();
    2441     delete _caster;    _caster    = 0; BNC_CORE->setCaster(0);
    2442     delete _casterEph; _casterEph = 0;
    2443     _runningRealTime = false;
    2444     _runningPPP      = false;
    2445     enableStartStop();
    2446   }
    2447 }
    2448 
    2449 // Close Application gracefully
    2450 ////////////////////////////////////////////////////////////////////////////
    2451 void bncWindow::closeEvent(QCloseEvent* event) {
    2452 
    2453   int iRet = QMessageBox::question(this, "Close", "Save Options?",
    2454                                    QMessageBox::Yes, QMessageBox::No,
    2455                                    QMessageBox::Cancel);
    2456 
    2457   if      (iRet == QMessageBox::Cancel) {
    2458     event->ignore();
    2459     return;
    2460   }
    2461   else if (iRet == QMessageBox::Yes) {
    2462     slotSaveOptions();
    2463   }
    2464 
    2465   BNC_CORE->stopPPP();
    2466 
    2467   QMainWindow::closeEvent(event);
    2468 }
    2469 
    2470 // User changed the selection of mountPoints
    2471 ////////////////////////////////////////////////////////////////////////////
    2472 void bncWindow::slotSelectionChanged() {
    2473   if (_mountPointsTable->selectedItems().isEmpty()) {
    2474     _actDeleteMountPoints->setEnabled(false);
    2475   }
    2476   else {
    2477     _actDeleteMountPoints->setEnabled(true);
    2478   }
    2479 }
    2480 
    2481 // Display Program Messages
    2482 ////////////////////////////////////////////////////////////////////////////
    2483 void bncWindow::slotWindowMessage(const QByteArray msg, bool showOnScreen) {
    2484   if (showOnScreen ) {
    2485     _log->append(QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ") + msg);
    2486   }
    2487 }
    2488 
    2489 // About Message
    2490 ////////////////////////////////////////////////////////////////////////////
    2491 void bncWindow::slotAbout() {
    2492  new bncAboutDlg(0);
    2493 }
    2494 
    2495 //Flowchart
    2496 ////////////////////////////////////////////////////////////////////////////
    2497 void bncWindow::slotFlowchart() {
    2498  new bncFlowchartDlg(0);
    2499 }
    2500 
    2501 // Help Window
    2502 ////////////////////////////////////////////////////////////////////////////
    2503 void bncWindow::slotHelp() {
    2504   QUrl url = QUrl::fromLocalFile(":/bnchelp.html");
    2505   new bncHlpDlg(0, url);
    2506 }
    2507 
    2508 // Select Fonts
    2509 ////////////////////////////////////////////////////////////////////////////
    2510 void bncWindow::slotFontSel() {
    2511   bool ok;
    2512   QFont newFont = QFontDialog::getFont(&ok, this->font(), this);
    2513   if (ok) {
     3302        _actStart->setEnabled(true);
     3303        _actStop->setEnabled(false);
     3304    }
     3305}
     3306
     3307// Show Map
     3308////////////////////////////////////////////////////////////////////////////
     3309void bncWindow::slotMapMountPoints() {
     3310    saveOptions();
     3311    t_bncMap* bncMap = new t_bncMap(this);
     3312    bncMap->setMinimumSize(800, 600);
     3313    bncMap->setWindowTitle("Selected Mountpoints");
     3314
    25143315    bncSettings settings;
    2515     settings.setValue("font", newFont.toString());
    2516     QApplication::setFont(newFont);
    2517     int ww = QFontMetrics(newFont).horizontalAdvance('w');
    2518     setMinimumSize(60*ww, 80*ww);
    2519     resize(60*ww, 80*ww);
    2520   }
    2521 }
    2522 
    2523 // Whats This Help
    2524 void bncWindow::slotWhatsThis() {
    2525   QWhatsThis::enterWhatsThisMode();
    2526 }
    2527 
    2528 //
    2529 ////////////////////////////////////////////////////////////////////////////
    2530 void bncWindow::slotMountPointsRead(QList<bncGetThread*> threads) {
    2531   _threads = threads;
    2532 
    2533   _bncFigure->updateMountPoints();
    2534   _bncFigureLate->updateMountPoints();
    2535 
    2536   populateMountPointsTable();
    2537   bncSettings settings;
    2538   _outSamplComboBox->findText(settings.value("outSampl").toString());
    2539   _outWaitSpinBox->setValue(settings.value("outWait").toInt());
    2540   QListIterator<bncGetThread*> iTh(threads);
    2541   while (iTh.hasNext()) {
    2542     bncGetThread* thread = iTh.next();
    2543     for (int iRow = 0; iRow < _mountPointsTable->rowCount(); iRow++) {
    2544       QUrl url( "//" + _mountPointsTable->item(iRow, 0)->text() +
    2545                 "@"  + _mountPointsTable->item(iRow, 1)->text() );
    2546       if (url                                      == thread->mountPoint() &&
    2547           _mountPointsTable->item(iRow, 4)->text() == thread->latitude()   &&
    2548           _mountPointsTable->item(iRow, 5)->text() == thread->longitude() ) {
    2549         ((bncTableItem*) _mountPointsTable->item(iRow, 8))->setGetThread(thread);
    2550         disconnect(thread, SIGNAL(newBytes(QByteArray, double)), _bncFigure, SLOT(slotNewData(QByteArray, double)));
    2551         connect(thread, SIGNAL(newBytes(QByteArray, double)), _bncFigure, SLOT(slotNewData(QByteArray, double)));
    2552         disconnect(thread, SIGNAL(newLatency(QByteArray, double)), _bncFigureLate, SLOT(slotNewLatency(QByteArray, double)));
    2553         connect(thread, SIGNAL(newLatency(QByteArray, double)), _bncFigureLate, SLOT(slotNewLatency(QByteArray, double)));
    2554         break;
    2555       }
    2556     }
    2557   }
    2558 }
    2559 
    2560 //
    2561 ////////////////////////////////////////////////////////////////////////////
    2562 void bncWindow::CreateMenu() {
    2563   // Create Menus
    2564   // ------------
    2565   _menuFile = menuBar()->addMenu(tr("&File"));
    2566   _menuFile->addAction(_actFontSel);
    2567   _menuFile->addSeparator();
    2568   _menuFile->addAction(_actSaveOpt);
    2569   _menuFile->addSeparator();
    2570   _menuFile->addAction(_actQuit);
    2571 
    2572   _menuHlp = menuBar()->addMenu(tr("&Help"));
    2573   _menuHlp->addAction(_actHelp);
    2574   _menuHlp->addAction(_actFlowchart);
    2575   _menuHlp->addAction(_actAbout);
    2576 }
    2577 
    2578 // Toolbar
    2579 ////////////////////////////////////////////////////////////////////////////
    2580 void bncWindow::AddToolbar() {
    2581   QToolBar* toolBar = new QToolBar;
    2582   addToolBar(Qt::BottomToolBarArea, toolBar);
    2583   toolBar->setMovable(false);
    2584   toolBar->addAction(_actAddMountPoints);
    2585   toolBar->addAction(_actDeleteMountPoints);
    2586   toolBar->addAction(_actMapMountPoints);
    2587   toolBar->addAction(_actStart);
    2588   toolBar->addAction(_actStop);
    2589   toolBar->addWidget(new QLabel("                                           "));
    2590   toolBar->addAction(_actwhatsthis);
    2591 }
    2592 
    2593 // About
    2594 ////////////////////////////////////////////////////////////////////////////
    2595 bncAboutDlg::bncAboutDlg(QWidget* parent) :
    2596    QDialog(parent) {
    2597 
    2598   QTextBrowser* tb = new QTextBrowser;
    2599   QUrl url = QUrl::fromLocalFile(":/bncabout.html");
    2600   tb->setSource(url);
    2601   tb->setReadOnly(true);
    2602 
    2603   int ww = QFontMetrics(font()).horizontalAdvance('w');
    2604   QPushButton* _closeButton = new QPushButton("Close");
    2605   _closeButton->setMaximumWidth(10*ww);
    2606   connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
    2607 
    2608   QGridLayout* dlgLayout = new QGridLayout();
    2609   QLabel* img = new QLabel();
    2610   img->setPixmap(QPixmap(":ntrip-logo.png"));
    2611   dlgLayout->addWidget(img, 0,0);
    2612   dlgLayout->addWidget(new QLabel("BKG Ntrip Client (BNC) Version " BNCVERSION), 0,1);
    2613   dlgLayout->addWidget(tb,1,0,1,2);
    2614   dlgLayout->addWidget(_closeButton,2,1,Qt::AlignRight);
    2615 
    2616   setLayout(dlgLayout);
    2617   resize(60*ww, 60*ww);
    2618   setWindowTitle("About BNC");
    2619   show();
    2620 }
    2621 
    2622 //
    2623 ////////////////////////////////////////////////////////////////////////////
    2624 bncAboutDlg::~bncAboutDlg() {
    2625 
    2626 };
    2627 
    2628 // Flowchart
    2629 ////////////////////////////////////////////////////////////////////////////
    2630 bncFlowchartDlg::bncFlowchartDlg(QWidget* parent) :
    2631    QDialog(parent) {
    2632 
    2633   int ww = QFontMetrics(font()).horizontalAdvance('w');
    2634   QPushButton* _closeButton = new QPushButton("Close");
    2635   _closeButton->setMaximumWidth(10*ww);
    2636   connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
    2637 
    2638   QGridLayout* dlgLayout = new QGridLayout();
    2639   QLabel* img = new QLabel();
    2640   img->setPixmap(QPixmap(":bncflowchart.png"));
    2641   dlgLayout->addWidget(img, 0,0);
    2642   dlgLayout->addWidget(_closeButton,1,0,Qt::AlignLeft);
    2643 
    2644   setLayout(dlgLayout);
    2645   setWindowTitle("Flow Chart");
    2646   show();
    2647 }
    2648 
    2649 //
    2650 ////////////////////////////////////////////////////////////////////////////
    2651 bncFlowchartDlg::~bncFlowchartDlg() {
    2652 };
    2653 
    2654 // Enable/Disable Widget (and change its color)
    2655 ////////////////////////////////////////////////////////////////////////////
    2656 void bncWindow::enableWidget(bool enable, QWidget* widget) {
    2657 
    2658   const static QPalette paletteWhite(QColor(255, 255, 255));
    2659   const static QPalette paletteGray(QColor(230, 230, 230));
    2660 
    2661   widget->setEnabled(enable);
    2662   if (enable) {
    2663     widget->setPalette(paletteWhite);
    2664   }
    2665   else {
    2666     widget->setPalette(paletteGray);
    2667   }
    2668 }
    2669 
    2670 //  Bnc Text
    2671 ////////////////////////////////////////////////////////////////////////////
    2672 void bncWindow::slotBncTextChanged(){
    2673 
    2674   const static QPalette paletteWhite(QColor(255, 255, 255));
    2675   const static QPalette paletteGray(QColor(230, 230, 230));
    2676 
    2677   bool enable = true;
    2678 
    2679   // Proxy
    2680   //------
    2681   if (sender() == 0 || sender() == _proxyHostLineEdit) {
    2682     enable = !_proxyHostLineEdit->text().isEmpty();
    2683     enableWidget(enable, _proxyPortLineEdit);
    2684   }
    2685 
    2686   // RINEX Observations
    2687   // ------------------
    2688   if (sender() == 0 || sender() == _rnxPathLineEdit) {
    2689     enable = !_rnxPathLineEdit->text().isEmpty();
    2690     enableWidget(enable, _rnxIntrComboBox);
    2691     enableWidget(enable, _rnxSamplComboBox);
    2692     enableWidget(enable, _rnxSkelExtComboBox);
    2693     enableWidget(enable, _rnxSkelPathLineEdit);
    2694     enableWidget(enable, _rnxFileCheckBox);
    2695     enableWidget(enable, _rnxScrpLineEdit);
    2696     enableWidget(enable, _rnxV2Priority);
    2697     enableWidget(enable, _rnxVersComboBox);
    2698 
    2699     bool enable1 = true;
    2700     enable1 = _rnxVersComboBox->currentText() == "2";
    2701     if (enable && enable1) {
    2702       enableWidget(true, _rnxV2Priority);
    2703     }
    2704     if (enable && !enable1) {
    2705       enableWidget(false, _rnxV2Priority);
    2706     }
    2707   }
    2708 
    2709   // RINEX Observations, Signal Priority
    2710   // -----------------------------------
    2711   if (sender() == 0 || sender() == _rnxVersComboBox) {
    2712     if (!_rnxPathLineEdit->text().isEmpty()) {
    2713       enableWidget(enable, _rnxIntrComboBox);
    2714       enable = _rnxVersComboBox->currentText() == "2";
    2715       enableWidget(enable, _rnxV2Priority);
    2716     }
    2717   }
    2718 
    2719   // RINEX Ephemeris
    2720   // ---------------
    2721   if (sender() == 0 || sender() == _ephPathLineEdit || sender() == _ephOutPortLineEdit) {
    2722     enable = !_ephPathLineEdit->text().isEmpty() || !_ephOutPortLineEdit->text().isEmpty();
    2723     enableWidget(enable, _ephIntrComboBox);
    2724     enableWidget(enable, _ephVersComboBox);
    2725     //enableWidget(enable, _ephVersComboBox);
    2726     //enableWidget(enable, _ephFilePerStation);
    2727   }
    2728 
    2729   // Broadcast Corrections
    2730   // ---------------------
    2731   if (sender() == 0 || sender() == _corrPathLineEdit || sender() == _corrPortLineEdit) {
    2732     enable = !_corrPathLineEdit->text().isEmpty() || !_corrPortLineEdit->text().isEmpty();
    2733     enableWidget(enable, _corrIntrComboBox);
    2734   }
    2735 
    2736   // Feed Engine
    2737   // -----------
    2738   if (sender() == 0 || sender() == _outPortLineEdit || sender() == _outFileLineEdit) {
    2739     enable = !_outPortLineEdit->text().isEmpty() || !_outFileLineEdit->text().isEmpty();
    2740     enableWidget(enable, _outWaitSpinBox);
    2741     enableWidget(enable, _outSamplComboBox);
    2742   }
    2743 
    2744   // Serial Output
    2745   // -------------
    2746   if (sender() == 0 ||
    2747       sender() == _serialMountPointLineEdit ||
    2748       sender() == _serialAutoNMEAComboBox) {
    2749     enable = !_serialMountPointLineEdit->text().isEmpty();
    2750     enableWidget(enable, _serialPortNameLineEdit);
    2751     enableWidget(enable, _serialBaudRateComboBox);
    2752     enableWidget(enable, _serialParityComboBox);
    2753     enableWidget(enable, _serialDataBitsComboBox);
    2754     enableWidget(enable, _serialStopBitsComboBox);
    2755     enableWidget(enable, _serialFlowControlComboBox);
    2756     enableWidget(enable, _serialAutoNMEAComboBox);
    2757     if (enable && _serialAutoNMEAComboBox->currentText() == "Auto") {
    2758       enableWidget(true, _serialFileNMEALineEdit);
    2759       enableWidget(false, _serialHeightNMEALineEdit);
    2760       enableWidget(true, _serialNMEASamplingSpinBox);
    2761     }
    2762     else if (enable && _serialAutoNMEAComboBox->currentText().contains("Manual")) {
    2763       enableWidget(false, _serialFileNMEALineEdit);
    2764       enableWidget(true,  _serialHeightNMEALineEdit);
    2765       enableWidget(true,  _serialNMEASamplingSpinBox);
    2766     }
    2767     else {
    2768       enableWidget(false, _serialFileNMEALineEdit);
    2769       enableWidget(false, _serialHeightNMEALineEdit);
    2770       enableWidget(false, _serialNMEASamplingSpinBox);
    2771     }
    2772   }
    2773 
    2774   // Outages
    2775   // -------
    2776   if (sender() == 0 || sender() == _adviseObsRateComboBox) {
    2777     enable = !_adviseObsRateComboBox->currentText().isEmpty();
    2778     enableWidget(enable, _adviseFailSpinBox);
    2779     enableWidget(enable, _adviseRecoSpinBox);
    2780     enableWidget(enable, _adviseScriptLineEdit);
    2781   }
    2782 
    2783   // Miscellaneous
    2784   // -------------
    2785   if (sender() == 0 || sender() == _miscMountLineEdit) {
    2786     enable = !_miscMountLineEdit->text().isEmpty();
    2787     enableWidget(enable, _miscIntrComboBox);
    2788     enableWidget(enable, _miscScanRTCMCheckBox);
    2789     enableWidget(enable, _miscPortLineEdit);
    2790   }
    2791 
    2792   // Combine Corrections
    2793   // -------------------
    2794   if (sender() == 0 || sender() == _cmbTable) {
    2795     int iRow = _cmbTable->rowCount();
    2796     if (iRow > 0) {
    2797       enableWidget(true, _cmbMethodComboBox);
    2798       enableWidget(true, _cmbMaxresLineEdit);
    2799       enableWidget(true, _cmbMaxdisplacementLineEdit);
    2800       enableWidget(true, _cmbSamplSpinBox);
    2801       enableWidget(true, _cmbLogPath);
    2802       enableWidget(true, _cmbGpsCheckBox);
    2803       enableWidget(true, _cmbGloCheckBox);
    2804       enableWidget(true, _cmbGalCheckBox);
    2805       enableWidget(true, _cmbBdsCheckBox);
    2806       enableWidget(true, _cmbQzssCheckBox);
    2807       enableWidget(true, _cmbSbasCheckBox);
    2808       enableWidget(true, _cmbNavicCheckBox);
    2809       enableWidget(true, _cmbBsxFile);
    2810     }
    2811     else {
    2812       enableWidget(false, _cmbMethodComboBox);
    2813       enableWidget(false, _cmbMaxresLineEdit);
    2814       enableWidget(false, _cmbMaxdisplacementLineEdit);
    2815       enableWidget(false, _cmbSamplSpinBox);
    2816       enableWidget(false, _cmbLogPath);
    2817       enableWidget(false, _cmbGpsCheckBox);
    2818       enableWidget(false, _cmbGloCheckBox);
    2819       enableWidget(false, _cmbGalCheckBox);
    2820       enableWidget(false, _cmbBdsCheckBox);
    2821       enableWidget(false, _cmbQzssCheckBox);
    2822       enableWidget(false, _cmbSbasCheckBox);
    2823       enableWidget(false, _cmbNavicCheckBox);
    2824       enableWidget(false, _cmbBsxFile);
    2825     }
    2826   }
    2827 
    2828   // Upload(clk)
    2829   // -----------
    2830   int iRow = _uploadTable->rowCount();
    2831   if (iRow > 0) {
    2832     enableWidget(true, _uploadIntrComboBox);
    2833     enableWidget(true, _uploadSamplRtcmEphCorrSpinBox);
    2834     enableWidget(true, _uploadSamplClkRnxSpinBox);
    2835     enableWidget(true, _uploadSamplBiaSnxSpinBox);
    2836     enableWidget(true, _uploadSamplSp3ComboBox);
    2837     enableWidget(true, _uploadAntexFile);
    2838   }
    2839   else {
    2840     enableWidget(false, _uploadIntrComboBox);
    2841     enableWidget(false, _uploadSamplRtcmEphCorrSpinBox);
    2842     enableWidget(false, _uploadSamplClkRnxSpinBox);
    2843     enableWidget(false, _uploadSamplBiaSnxSpinBox);
    2844     enableWidget(false, _uploadSamplSp3ComboBox);
    2845     enableWidget(false, _uploadAntexFile);
    2846   }
    2847 
    2848   // Upload(eph)
    2849   // -----------
    2850   iRow = _uploadEphTable->rowCount();
    2851   if (iRow > 0) {
    2852     enableWidget(true, _uploadSamplRtcmEphSpinBox);
    2853   }
    2854   else {
    2855     enableWidget(false, _uploadSamplRtcmEphSpinBox);
    2856   }
    2857 
    2858   // QC
    2859   // --
    2860   if (sender() == 0 || sender() == _reqcActionComboBox || sender() == _reqcSkyPlotSignals) {
    2861     enable = !_reqcActionComboBox->currentText().isEmpty();
    2862     bool enable10   = _reqcActionComboBox->currentText() == "Edit/Concatenate";
    2863 //  bool enablePlot = !_reqcSkyPlotSignals->text().isEmpty();
    2864     enableWidget(enable,                            _reqcObsFileChooser);
    2865     enableWidget(enable,                            _reqcNavFileChooser);
    2866     enableWidget(enable,                            _reqcOutLogLineEdit);
    2867     enableWidget(enable &&  enable10,               _reqcEditOptionButton);
    2868     enableWidget(enable &&  enable10,               _reqcOutObsLineEdit);
    2869     enableWidget(enable &&  enable10,               _reqcOutNavLineEdit);
    2870     enableWidget(enable && !enable10,               _reqcLogSummaryOnly);
    2871     enableWidget(enable && !enable10,               _reqcSkyPlotSignals);
    2872 //  enableWidget(enable && !enable10 && enablePlot, _reqcPlotDirLineEdit);
    2873     enableWidget(enable && !enable10,               _reqcPlotDirLineEdit);
    2874   }
    2875 
    2876   // SP3 File Comparison
    2877   // -------------------
    2878   if (sender() == 0 || sender() == _sp3CompFileChooser) {
    2879     enable = !_sp3CompFileChooser->fileName().isEmpty();
    2880     enableWidget(enable, _sp3CompLogLineEdit);
    2881     enableWidget(enable, _sp3CompExclude);
    2882     enableWidget(enable, _sp3CompSummaryOnly);
    2883   }
    2884 
    2885   enableStartStop();
    2886 }
    2887 
    2888 //
    2889 ////////////////////////////////////////////////////////////////////////////
    2890 void bncWindow::slotAddCmbRow() {
    2891   int iRow = _cmbTable->rowCount();
    2892   _cmbTable->insertRow(iRow);
    2893   for (int iCol = 0; iCol < _cmbTable->columnCount(); iCol++) {
    2894     _cmbTable->setItem(iRow, iCol, new QTableWidgetItem(""));
    2895   }
    2896 }
    2897 
    2898 //
    2899 ////////////////////////////////////////////////////////////////////////////
    2900 void bncWindow::slotDelCmbRow() {
    2901 
    2902   const static QPalette paletteWhite(QColor(255, 255, 255));
    2903   const static QPalette paletteGray(QColor(230, 230, 230));
    2904 
    2905   int nRows = _cmbTable->rowCount();
    2906   std::vector <bool> flg(nRows);
    2907   for (int iRow = 0; iRow < nRows; iRow++) {
    2908     if (_cmbTable->item(iRow,1)->isSelected()) {
    2909       flg[iRow] = true;
    2910     }
    2911     else {
    2912       flg[iRow] = false;
    2913     }
    2914   }
    2915   for (int iRow = nRows-1; iRow >= 0; iRow--) {
    2916     if (flg[iRow]) {
    2917       _cmbTable->removeRow(iRow);
    2918     }
    2919   }
    2920   nRows = _cmbTable->rowCount();
    2921   if (nRows < 1) {
    2922     enableWidget(false, _cmbMethodComboBox);
    2923     enableWidget(false, _cmbMaxresLineEdit);
    2924     enableWidget(false, _cmbMaxdisplacementLineEdit);
    2925     enableWidget(false, _cmbSamplSpinBox);
    2926     enableWidget(false, _cmbLogPath);
    2927   }
    2928 }
    2929 
    2930 //
    2931 ////////////////////////////////////////////////////////////////////////////
    2932 void bncWindow::populateCmbTable() {
    2933 
    2934   for (int iRow = _cmbTable->rowCount()-1; iRow >=0; iRow--) {
    2935     _cmbTable->removeRow(iRow);
    2936   }
    2937 
    2938   bncSettings settings;
    2939 
    2940   int iRow = -1;
    2941   QListIterator<QString> it(settings.value("cmbStreams").toStringList());
    2942   while (it.hasNext()) {
    2943     QStringList hlp = it.next().split(" ");
    2944     if (hlp.size() > 2) {
    2945       ++iRow;
    2946       _cmbTable->insertRow(iRow);
    2947     }
    2948     for (int iCol = 0; iCol < hlp.size(); iCol++) {
    2949       _cmbTable->setItem(iRow, iCol, new QTableWidgetItem(hlp[iCol]));
    2950     }
    2951   }
    2952 }
    2953 
    2954 //
    2955 ////////////////////////////////////////////////////////////////////////////
    2956 void bncWindow::slotAddUploadRow() {
    2957   int iRow = _uploadTable->rowCount();
    2958   _uploadTable->insertRow(iRow);
    2959   for (int iCol = 0; iCol < _uploadTable->columnCount(); iCol++) {
    2960     if (iCol == 3) {
    2961       QComboBox* ntripversion = new QComboBox();
    2962       ntripversion->setEditable(false);
    2963       ntripversion->addItems(QString("1,2,2s").split(","));
    2964       ntripversion->setFrame(false);
    2965       _uploadTable->setCellWidget(iRow, iCol, ntripversion);
    2966 
    2967     }
    2968     else if (iCol == 4) {
    2969       QLineEdit* user = new QLineEdit();
    2970       user->setFrame(false);
    2971       _uploadTable->setCellWidget(iRow, iCol, user);
    2972     }
    2973     else if (iCol == 5) {
    2974       QLineEdit* passwd = new QLineEdit();
    2975       passwd->setFrame(false);
    2976       passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
    2977       _uploadTable->setCellWidget(iRow, iCol, passwd);
    2978     }
    2979     else if (iCol == 6) {
    2980       QComboBox* system = new QComboBox();
    2981       system->setEditable(false);
    2982       system->addItems(QString("IGS20,ETRF2000,GDA2020,SIRGAS2000,DREF91,Custom").split(","));
    2983       system->setFrame(false);
    2984       _uploadTable->setCellWidget(iRow, iCol, system);
    2985     }
    2986     else if (iCol == 7) {
    2987       QComboBox* format = new QComboBox();
    2988       format->setEditable(false);
    2989       format->addItems(QString("IGS-SSR,RTCM-SSR").split(","));
    2990       format->setFrame(false);
    2991       _uploadTable->setCellWidget(iRow, iCol, format);
    2992     }
    2993     else if (iCol == 8) {
    2994       QCheckBox* com = new QCheckBox();
    2995       _uploadTable->setCellWidget(iRow, iCol, com);
    2996     }
    2997     else if (iCol == 15) {
    2998       bncTableItem* bncIt = new bncTableItem();
    2999       bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
    3000       _uploadTable->setItem(iRow, iCol, bncIt);
    3001       BNC_CORE->_uploadTableItems[iRow] = bncIt;
    3002     }
    3003     else {
    3004       _uploadTable->setItem(iRow, iCol, new QTableWidgetItem(""));
    3005     }
    3006   }
    3007 }
    3008 
    3009 //
    3010 ////////////////////////////////////////////////////////////////////////////
    3011 void bncWindow::slotDelUploadRow() {
    3012   BNC_CORE->_uploadTableItems.clear();
    3013   int nRows = _uploadTable->rowCount();
    3014   std::vector <bool> flg(nRows);
    3015   for (int iRow = 0; iRow < nRows; iRow++) {
    3016     if (_uploadTable->item(iRow,1)->isSelected()) {
    3017       flg[iRow] = true;
    3018     }
    3019     else {
    3020       flg[iRow] = false;
    3021     }
    3022   }
    3023   for (int iRow = nRows-1; iRow >= 0; iRow--) {
    3024     if (flg[iRow]) {
    3025       _uploadTable->removeRow(iRow);
    3026     }
    3027   }
    3028   for (int iRow = 0; iRow < _uploadTable->rowCount(); iRow++) {
    3029     BNC_CORE->_uploadTableItems[iRow] =
    3030                                 (bncTableItem*) _uploadTable->item(iRow, 14);
    3031   }
    3032   nRows = _uploadTable->rowCount();
    3033   if (nRows < 1) {
    3034     enableWidget(false, _uploadIntrComboBox);
    3035     enableWidget(false, _uploadSamplRtcmEphCorrSpinBox);
    3036     enableWidget(false, _uploadSamplSp3ComboBox);
    3037     enableWidget(false, _uploadSamplClkRnxSpinBox);
    3038     enableWidget(false, _uploadAntexFile);
    3039   }
    3040 }
    3041 
    3042 //
    3043 ////////////////////////////////////////////////////////////////////////////
    3044 void bncWindow::populateUploadTable() {
    3045   for (int iRow = _uploadTable->rowCount()-1; iRow >=0; iRow--) {
    3046     _uploadTable->removeRow(iRow);
    3047   }
    3048 
    3049   bncSettings settings;
    3050 
    3051   int iRow = -1;
    3052   QListIterator<QString> it(settings.value("uploadMountpointsOut").toStringList());
    3053 
    3054   while (it.hasNext()) {
    3055     QStringList hlp = it.next().split(",");
    3056     if (hlp.size() > 6) {
    3057       ++iRow;
    3058       _uploadTable->insertRow(iRow);
    3059     }
    3060     for (int iCol = 0; iCol < hlp.size(); iCol++) {
    3061       if      (iCol == 3) {
    3062         QComboBox* ntripversion = new QComboBox();
    3063         ntripversion->setEditable(false);
    3064         ntripversion->addItems(QString("1,2,2s").split(","));
    3065         ntripversion->setFrame(false);
    3066         ntripversion->setCurrentIndex(ntripversion->findText(hlp[iCol]));
    3067         _uploadTable->setCellWidget(iRow, iCol, ntripversion);
    3068       }
    3069       else if (iCol == 4) {
    3070         QLineEdit* user = new QLineEdit();
    3071         user->setFrame(false);
    3072         user->setText(hlp[iCol]);
    3073         _uploadTable->setCellWidget(iRow, iCol, user);
    3074       }
    3075       else if (iCol == 5) {
    3076         QLineEdit* passwd = new QLineEdit();
    3077         passwd->setFrame(false);
    3078         passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
    3079         passwd->setText(hlp[iCol]);
    3080         _uploadTable->setCellWidget(iRow, iCol, passwd);
    3081       }
    3082       else if (iCol == 6) {
    3083         QComboBox* system = new QComboBox();
    3084         system->setEditable(false);
    3085         system->addItems(QString("IGS20,ETRF2000,GDA2020,SIRGAS2000,DREF91,Custom").split(","));
    3086         system->setFrame(false);
    3087         system->setCurrentIndex(system->findText(hlp[iCol]));
    3088         _uploadTable->setCellWidget(iRow, iCol, system);
    3089       }
    3090       else if (iCol == 7) {
    3091         QComboBox* format = new QComboBox();
    3092         format->setEditable(false);
    3093         format->addItems(QString("IGS-SSR,RTCM-SSR").split(","));
    3094         format->setFrame(false);
    3095         format->setCurrentIndex(format->findText(hlp[iCol]));
    3096         _uploadTable->setCellWidget(iRow, iCol, format);
    3097       }
    3098       else if (iCol == 8) {
    3099         QCheckBox* com = new QCheckBox();
    3100         if (hlp[iCol].toInt() == Qt::Checked) {
    3101           com->setCheckState(Qt::Checked);
    3102         }
    3103         _uploadTable->setCellWidget(iRow, iCol, com);
    3104       }
    3105       else if (iCol == 15) {
    3106         bncTableItem* bncIt = new bncTableItem();
    3107         bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
    3108         _uploadTable->setItem(iRow, iCol, bncIt);
    3109         BNC_CORE->_uploadTableItems[iRow] = bncIt;
    3110       }
    3111       else {
    3112         _uploadTable->setItem(iRow, iCol, new QTableWidgetItem(hlp[iCol]));
    3113       }
    3114     }
    3115   }
    3116 }
    3117 
    3118 //
    3119 ////////////////////////////////////////////////////////////////////////////
    3120 void bncWindow::slotSetUploadTrafo() {
    3121   bncCustomTrafo* dlg = new bncCustomTrafo(this);
    3122   dlg->exec();
    3123   delete dlg;
    3124 }
    3125 
    3126 //
    3127 ////////////////////////////////////////////////////////////////////////////
    3128 void bncWindow::slotAddUploadEphRow() {
    3129   int iRow = _uploadEphTable->rowCount();
    3130   _uploadEphTable->insertRow(iRow);
    3131   for (int iCol = 0; iCol < _uploadEphTable->columnCount(); iCol++) {
    3132     if      (iCol == 3) {
    3133       QComboBox* ntripversion = new QComboBox();
    3134       ntripversion->setEditable(false);
    3135       ntripversion->addItems(QString("1,2,2s").split(","));
    3136       ntripversion->setFrame(false);
    3137       _uploadEphTable->setCellWidget(iRow, iCol, ntripversion);
    3138 
    3139     }
    3140     else if (iCol == 4) {
    3141       QLineEdit* user = new QLineEdit();
    3142       user->setFrame(false);
    3143       _uploadEphTable->setCellWidget(iRow, iCol, user);
    3144     }
    3145     else if (iCol == 5) {
    3146       QLineEdit* passwd = new QLineEdit();
    3147       passwd->setFrame(false);
    3148       passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
    3149       _uploadEphTable->setCellWidget(iRow, iCol, passwd);
    3150     }
    3151     else if (iCol == 6) {
    3152       QLineEdit* system = new QLineEdit("GREC");
    3153       system->setFrame(false);
    3154       _uploadEphTable->setCellWidget(iRow, iCol, system);
    3155     }
    3156     else if (iCol == 7) {
    3157       bncTableItem* bncIt = new bncTableItem();
    3158       bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
    3159       _uploadEphTable->setItem(iRow, iCol, bncIt);
    3160       BNC_CORE->_uploadEphTableItems[iRow] = bncIt;
    3161     }
    3162     else {
    3163       _uploadEphTable->setItem(iRow, iCol, new QTableWidgetItem(""));
    3164     }
    3165   }
    3166 }
    3167 
    3168 //
    3169 ////////////////////////////////////////////////////////////////////////////
    3170 void bncWindow::slotDelUploadEphRow() {
    3171   BNC_CORE->_uploadTableItems.clear();
    3172   int nRows = _uploadEphTable->rowCount();
    3173   std::vector <bool> flg(nRows);
    3174   for (int iRow = 0; iRow < nRows; iRow++) {
    3175     if (_uploadEphTable->item(iRow,1)->isSelected()) {
    3176       flg[iRow] = true;
    3177     }
    3178     else {
    3179       flg[iRow] = false;
    3180     }
    3181   }
    3182   for (int iRow = nRows-1; iRow >= 0; iRow--) {
    3183     if (flg[iRow]) {
    3184       _uploadEphTable->removeRow(iRow);
    3185     }
    3186   }
    3187   for (int iRow = 0; iRow < _uploadTable->rowCount(); iRow++) {
    3188     BNC_CORE->_uploadTableItems[iRow] =
    3189                                 (bncTableItem*) _uploadEphTable->item(iRow, 7);
    3190   }
    3191   nRows = _uploadEphTable->rowCount();
    3192   if (nRows < 1) {
    3193     enableWidget(false, _uploadSamplRtcmEphSpinBox);
    3194   }
    3195 }
    3196 
    3197 //
    3198 ////////////////////////////////////////////////////////////////////////////
    3199 void bncWindow::populateUploadEphTable() {
    3200   for (int iRow = _uploadEphTable->rowCount()-1; iRow >=0; iRow--) {
    3201     _uploadEphTable->removeRow(iRow);
    3202   }
    3203 
    3204   bncSettings settings;
    3205 
    3206   int iRow = -1;
    3207   QListIterator<QString> it(settings.value("uploadEphMountpointsOut").toStringList());
    3208   while (it.hasNext()) {
    3209     QStringList hlp = it.next().split(",");
    3210     if (hlp.size() > 6) {
    3211       ++iRow;
    3212       _uploadEphTable->insertRow(iRow);
    3213     }
    3214     for (int iCol = 0; iCol < hlp.size(); iCol++) {
    3215       if (iCol == 3) {
    3216         QComboBox* ntripversion = new QComboBox();
    3217         ntripversion->setEditable(false);
    3218         ntripversion->addItems(QString("1,2,2s").split(","));
    3219         ntripversion->setFrame(false);
    3220         ntripversion->setCurrentIndex(ntripversion->findText(hlp[iCol]));
    3221         _uploadEphTable->setCellWidget(iRow, iCol, ntripversion);
    3222       }
    3223       else if (iCol == 4) {
    3224         QLineEdit* user = new QLineEdit();
    3225         user->setFrame(false);
    3226         user->setText(hlp[iCol]);
    3227         _uploadEphTable->setCellWidget(iRow, iCol, user);
    3228       }
    3229       else if (iCol == 5) {
    3230         QLineEdit* passwd = new QLineEdit();
    3231         passwd->setFrame(false);
    3232         passwd->setEchoMode(QLineEdit::PasswordEchoOnEdit);
    3233         passwd->setText(hlp[iCol]);
    3234         _uploadEphTable->setCellWidget(iRow, iCol, passwd);
    3235       }
    3236       else if (iCol == 6) {
    3237         QLineEdit* system = new QLineEdit();
    3238         system->setFrame(false);
    3239         system->setText(hlp[iCol]);
    3240         _uploadEphTable->setCellWidget(iRow, iCol, system);
    3241       }
    3242       else if (iCol == 7) {
    3243         bncTableItem* bncIt = new bncTableItem();
    3244         bncIt->setFlags(bncIt->flags() & ~Qt::ItemIsEditable);
    3245         _uploadEphTable->setItem(iRow, iCol, bncIt);
    3246         BNC_CORE->_uploadEphTableItems[iRow] = bncIt;
    3247       }
    3248       else {
    3249         _uploadEphTable->setItem(iRow, iCol, new QTableWidgetItem(hlp[iCol]));
    3250       }
    3251     }
    3252   }
    3253 }
    3254 
    3255 
    3256 // Progress Bar Change
    3257 ////////////////////////////////////////////////////////////////////////////
    3258 void bncWindow::slotPostProcessingProgress(int nEpo) {
    3259   _actStart->setText(QString("%1 Epochs").arg(nEpo));
    3260 }
    3261 
    3262 // Post-Processing Reqc Finished
    3263 ////////////////////////////////////////////////////////////////////////////
    3264 void bncWindow::slotPostProcessingFinished() {
    3265   delete _caster; _caster = 0; BNC_CORE->setCaster(0);
    3266   _runningPPP     = false;
    3267   _runningEdit    = false;
    3268   _runningQC      = false;
    3269   _runningSp3Comp = false;
    3270   _actStart->setText(tr("Sta&rt"));
    3271   enableStartStop();
    3272 }
    3273 
    3274 // Edit teqc-like editing options
    3275 ////////////////////////////////////////////////////////////////////////////
    3276 void bncWindow::slotReqcEditOption() {
    3277   saveOptions();
    3278   reqcDlg* dlg = new reqcDlg(this);
    3279   dlg->move(this->pos().x()+50, this->pos().y()+50);
    3280   dlg->exec();
    3281   delete dlg;
    3282 }
    3283 
    3284 // Enable/Disable Start and Stop Buttons
    3285 ////////////////////////////////////////////////////////////////////////////
    3286 void bncWindow::enableStartStop() {
    3287 
    3288   if ( running() ) {
    3289     _actStart->setEnabled(false);
    3290     if (_runningRealTime || _runningPPP) {
    3291       _actStop->setEnabled(true);
    3292     }
    3293   }
    3294   else {
    3295     _actStart->setEnabled(true);
    3296     _actStop->setEnabled(false);
    3297   }
    3298 }
    3299 
    3300 // Show Map
    3301 ////////////////////////////////////////////////////////////////////////////
    3302 void bncWindow::slotMapMountPoints() {
    3303   saveOptions();
    3304   t_bncMap* bncMap = new t_bncMap(this);
    3305   bncMap->setMinimumSize(800, 600);
    3306   bncMap->setWindowTitle("Selected Mountpoints");
    3307 
    3308   bncSettings settings;
    3309   QListIterator<QString> it(settings.value("mountPoints").toStringList());
    3310   while (it.hasNext()) {
    3311     QStringList hlp = it.next().split(" ");
    3312     if (hlp.size() < 5) continue;
    3313     QUrl   url(hlp[0]);
    3314     double latDeg = hlp[3].toDouble();
    3315     double lonDeg = hlp[4].toDouble();
    3316     bncMap->slotNewPoint(QFileInfo(url.path()).fileName(), latDeg, lonDeg);
    3317   }
    3318 
    3319   bncMap->show();
     3316    QListIterator<QString> it(settings.value("mountPoints").toStringList());
     3317    while (it.hasNext()) {
     3318        QStringList hlp = it.next().split(" ");
     3319        if (hlp.size() < 5) continue;
     3320        QUrl   url(hlp[0]);
     3321        double latDeg = hlp[3].toDouble();
     3322        double lonDeg = hlp[4].toDouble();
     3323        bncMap->slotNewPoint(QFileInfo(url.path()).fileName(), latDeg, lonDeg);
     3324    }
     3325
     3326    bncMap->show();
    33203327}
    33213328
     
    33243331void bncWindow::slotMapPPP() {
    33253332#ifdef QT_WEBENGINE
    3326   saveOptions();
    3327   enableWidget(false, _pppWidgets._mapWinButton);
    3328   enableWidget(false, _pppWidgets._mapWinDotSize);
    3329   enableWidget(false, _pppWidgets._mapWinDotColor);
    3330 
    3331   if (!_mapWin) {
    3332     _mapWin = new bncMapWin(this);
    3333     connect(_mapWin, SIGNAL(mapClosed()), this, SLOT(slotMapPPPClosed()));
    3334     connect(BNC_CORE, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)),
     3333    saveOptions();
     3334    enableWidget(false, _pppWidgets._mapWinButton);
     3335    enableWidget(false, _pppWidgets._mapWinDotSize);
     3336    enableWidget(false, _pppWidgets._mapWinDotColor);
     3337
     3338    if (!_mapWin) {
     3339        _mapWin = new bncMapWin(this);
     3340        connect(_mapWin, SIGNAL(mapClosed()), this, SLOT(slotMapPPPClosed()));
     3341        connect(BNC_CORE, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)),
    33353342            _mapWin, SLOT(slotNewPosition(QByteArray, bncTime, QVector<double>)));
    3336   }
    3337   _mapWin->show();
     3343    }
     3344    _mapWin->show();
    33383345#else
    3339   QMessageBox::information(this, "Information",
    3340                            "Qt Library compiled without QT_WEBENGINE");
     3346    QMessageBox::information(this, "Information",
     3347        "Qt Library compiled without QT_WEBENGINE");
    33413348#endif
    33423349}
     
    33463353void bncWindow::slotMapPPPClosed() {
    33473354#ifdef QT_WEBENGINE
    3348   enableWidget(true, _pppWidgets._mapWinButton);
    3349   enableWidget(true, _pppWidgets._mapWinDotSize);
    3350   enableWidget(true, _pppWidgets._mapWinDotColor);
    3351   if (_mapWin) {
    3352     QListIterator<bncGetThread*> it(_threads);
    3353     while (it.hasNext()) {
    3354       bncGetThread* thread = it.next();
    3355       thread->disconnect(_mapWin);
    3356     }
    3357     _mapWin->deleteLater();
    3358     _mapWin = 0;
    3359   }
     3355    enableWidget(true, _pppWidgets._mapWinButton);
     3356    enableWidget(true, _pppWidgets._mapWinDotSize);
     3357    enableWidget(true, _pppWidgets._mapWinDotColor);
     3358    if (_mapWin) {
     3359        QListIterator<bncGetThread*> it(_threads);
     3360        while (it.hasNext()) {
     3361            bncGetThread* thread = it.next();
     3362            thread->disconnect(_mapWin);
     3363        }
     3364        _mapWin->deleteLater();
     3365        _mapWin = 0;
     3366    }
    33603367#endif
    33613368}
  • trunk/BNC/src/bncwindow.h

    r10619 r10657  
    3737
    3838class bncAboutDlg : public QDialog {
    39   Q_OBJECT
    40   public:
     39    Q_OBJECT
     40public:
    4141    bncAboutDlg(QWidget* parent);
    4242    ~bncAboutDlg();
     
    4444
    4545class bncFlowchartDlg : public QDialog {
    46   Q_OBJECT
    47 
    48   public:
     46    Q_OBJECT
     47
     48public:
    4949    bncFlowchartDlg(QWidget* parent);
    5050    ~bncFlowchartDlg();
     
    6060
    6161class bncWindow : public QMainWindow {
    62   Q_OBJECT
    63 
    64   public:
     62    Q_OBJECT
     63
     64public:
    6565    bncWindow();
    6666    ~bncWindow();
     
    6868    void AddToolbar();
    6969
    70   public slots:
     70public slots:
    7171    void slotMountPointsRead(QList<bncGetThread*>);
    7272    void slotBncTextChanged();
    7373
    74   private slots:
     74private slots:
    7575    void slotWindowMessage(const QByteArray msg, bool showOnScreen);
    7676    void slotHelp();
     
    101101    void slotPostProcessingProgress(int);
    102102
    103   protected:
    104     virtual void closeEvent(QCloseEvent *);
    105 
    106   private:
     103protected:
     104    virtual void closeEvent(QCloseEvent*);
     105
     106private:
    107107    void saveOptions();
    108108    void populateMountPointsTable();
     
    114114    void enableStartStop();
    115115
    116     QMenu*     _menuHlp;
    117     QMenu*     _menuFile;
    118 
    119     QAction*   _actHelp;
    120     QAction*   _actAbout;
    121     QAction*   _actFlowchart;
    122     QAction*   _actFontSel;
    123     QAction*   _actSaveOpt;
    124     QAction*   _actQuit;
    125     QAction*   _actMapMountPoints;
    126     QAction*   _actStart;
    127     QAction*   _actStop;
    128     QAction*   _actAddMountPoints;
    129     QAction*   _actDeleteMountPoints;
    130     QAction*   _actwhatsthis;
    131     QAction*   _actwhatsthismenu;
     116    QMenu* _menuHlp;
     117    QMenu* _menuFile;
     118
     119    QAction* _actHelp;
     120    QAction* _actAbout;
     121    QAction* _actFlowchart;
     122    QAction* _actFontSel;
     123    QAction* _actSaveOpt;
     124    QAction* _actQuit;
     125    QAction* _actMapMountPoints;
     126    QAction* _actStart;
     127    QAction* _actStop;
     128    QAction* _actAddMountPoints;
     129    QAction* _actDeleteMountPoints;
     130    QAction* _actwhatsthis;
     131    QAction* _actwhatsthismenu;
    132132
    133133    QLineEdit* _proxyHostLineEdit;
     
    149149    QLineEdit* _miscPortLineEdit;
    150150
    151     QComboBox*     _reqcActionComboBox;
    152     QPushButton*   _reqcEditOptionButton;
     151    QComboBox* _reqcActionComboBox;
     152    QPushButton* _reqcEditOptionButton;
    153153    qtFileChooser* _reqcObsFileChooser;
    154154    qtFileChooser* _reqcNavFileChooser;
    155     QLineEdit*     _reqcOutObsLineEdit;
    156     QLineEdit*     _reqcOutNavLineEdit;
    157     QLineEdit*     _reqcOutLogLineEdit;
    158     QLineEdit*     _reqcPlotDirLineEdit;
    159     QLineEdit*     _reqcSkyPlotSignals;
    160     QCheckBox*     _reqcLogSummaryOnly;
     155    QLineEdit* _reqcOutObsLineEdit;
     156    QLineEdit* _reqcOutNavLineEdit;
     157    QLineEdit* _reqcOutLogLineEdit;
     158    QLineEdit* _reqcPlotDirLineEdit;
     159    QLineEdit* _reqcSkyPlotSignals;
     160    QCheckBox* _reqcLogSummaryOnly;
    161161
    162162    qtFileChooser* _sp3CompFileChooser;
    163     QLineEdit*     _sp3CompExclude;
    164     QLineEdit*     _sp3CompLogLineEdit;
    165     QCheckBox*     _sp3CompSummaryOnly;
     163    QLineEdit* _sp3CompExclude;
     164    QLineEdit* _sp3CompLogLineEdit;
     165    QCheckBox* _sp3CompSummaryOnly;
    166166
    167167    QComboBox* _rnxVersComboBox;
     
    182182    QCheckBox* _autoStartCheckBox;
    183183    QCheckBox* _miscScanRTCMCheckBox;
    184     QSpinBox*  _outWaitSpinBox;
     184    QSpinBox* _outWaitSpinBox;
    185185    QComboBox* _adviseObsRateComboBox;
    186     QSpinBox*  _adviseFailSpinBox;
    187     QSpinBox*  _adviseRecoSpinBox;
     186    QSpinBox* _adviseFailSpinBox;
     187    QSpinBox* _adviseRecoSpinBox;
    188188    QLineEdit* _adviseScriptLineEdit;
    189189    QComboBox* _miscIntrComboBox;
     
    200200    QLineEdit* _serialFileNMEALineEdit;
    201201    QComboBox* _serialAutoNMEAComboBox;
    202     QSpinBox*  _serialNMEASamplingSpinBox;
    203 
    204     QLineEdit*   _LatLineEdit;
    205     QLineEdit*   _LonLineEdit;
    206 
    207     QComboBox*  _onTheFlyComboBox;
    208 
    209     QTextEdit*  _log;
    210 
    211     QWidget*    _canvas;
     202    QSpinBox* _serialNMEASamplingSpinBox;
     203
     204    QLineEdit* _LatLineEdit;
     205    QLineEdit* _LonLineEdit;
     206
     207    QComboBox* _onTheFlyComboBox;
     208
     209    QTextEdit* _log;
     210
     211    QWidget* _canvas;
    212212    QTabWidget* _aogroup;
    213213
    214214    QTabWidget* _loggroup;
    215     bncFigure*  _bncFigure;
    216     bncFigureLate*  _bncFigureLate;
    217     bncFigurePPP*   _bncFigurePPP;
    218 
    219     QTableWidget*  _cmbTable;
    220     QLineEdit*     _cmbMaxresLineEdit;
    221     QLineEdit*     _cmbMaxdisplacementLineEdit;
    222     QComboBox*     _cmbMethodComboBox;
    223     QSpinBox*      _cmbSamplSpinBox;
    224     QLineEdit*     _cmbLogPath;
    225     QCheckBox*     _cmbGpsCheckBox;
    226     QCheckBox*     _cmbGloCheckBox;
    227     QCheckBox*     _cmbGalCheckBox;
    228     QCheckBox*     _cmbBdsCheckBox;
    229     QCheckBox*     _cmbQzssCheckBox;
    230     QCheckBox*     _cmbSbasCheckBox;
    231     QCheckBox*     _cmbNavicCheckBox;
     215    bncFigure* _bncFigure;
     216    bncFigureLate* _bncFigureLate;
     217    bncFigurePPP* _bncFigurePPP;
     218
     219    QTableWidget* _cmbTable;
     220    QLineEdit* _cmbMaxresLineEdit;
     221    QLineEdit* _cmbMaxdisplacementLineEdit;
     222    QComboBox* _cmbMethodComboBox;
     223    QComboBox* _cmbSamplComboBox;
     224    QLineEdit* _cmbLogPath;
     225    QCheckBox* _cmbGpsCheckBox;
     226    QCheckBox* _cmbGloCheckBox;
     227    QCheckBox* _cmbGalCheckBox;
     228    QCheckBox* _cmbBdsCheckBox;
     229    QCheckBox* _cmbQzssCheckBox;
     230    QCheckBox* _cmbSbasCheckBox;
     231    QCheckBox* _cmbNavicCheckBox;
    232232    qtFileChooser* _cmbBsxFile;
    233233
    234     QTableWidget*  _uploadTable;
    235     QComboBox*     _uploadIntrComboBox;
    236     QSpinBox*      _uploadSamplRtcmEphCorrSpinBox;
    237     QComboBox*     _uploadSamplSp3ComboBox;
    238     QSpinBox*      _uploadSamplClkRnxSpinBox;
    239     QSpinBox*      _uploadSamplBiaSnxSpinBox;
     234    QTableWidget* _uploadTable;
     235    QComboBox* _uploadIntrComboBox;
     236    QComboBox* _uploadSamplRtcmEphCorrComboBox;
     237    QComboBox* _uploadSamplSp3ComboBox;
     238    QSpinBox* _uploadSamplClkRnxSpinBox;
     239    QSpinBox* _uploadSamplBiaSnxSpinBox;
    240240    qtFileChooser* _uploadAntexFile;
    241241
    242     QTableWidget*  _uploadEphTable;
    243     QSpinBox*      _uploadSamplRtcmEphSpinBox;
    244 
    245     bncCaster*          _caster;
     242    QTableWidget* _uploadEphTable;
     243    QSpinBox* _uploadSamplRtcmEphSpinBox;
     244
     245    bncCaster* _caster;
    246246    bncEphUploadCaster* _casterEph;
    247247
     
    252252    bool _runningSp3Comp;
    253253
    254     bool running() {return _runningRealTime || _runningPPP || _runningEdit ||
    255                     _runningQC || _runningSp3Comp;}
    256 
    257     bncMapWin*           _mapWin;
     254    bool running() {
     255        return _runningRealTime || _runningPPP || _runningEdit ||
     256            _runningQC || _runningSp3Comp;
     257    }
     258
     259    bncMapWin* _mapWin;
    258260
    259261    QList<bncGetThread*> _threads;
     
    265267#include "plugininterface.h"
    266268class t_bncFactory : public QObject, public GnssCenter::t_pluginFactoryInterface {
    267  Q_OBJECT
    268  Q_INTERFACES(GnssCenter::t_pluginFactoryInterface)
    269  public:
    270   virtual QWidget* create() {return new bncWindow();}
    271   virtual QString getName() const {return QString("BNC");}
     269    Q_OBJECT
     270        Q_INTERFACES(GnssCenter::t_pluginFactoryInterface)
     271public:
     272    virtual QWidget* create() { return new bncWindow(); }
     273    virtual QString getName() const { return QString("BNC"); }
    272274};
    273275#endif
  • trunk/BNC/src/upload/bncrtnetuploadcaster.cpp

    r10616 r10657  
    3737    bncUploadCaster(mountpoint, outHost, outPort, ntripVersion, userName, password, iRow, 0) {
    3838
    39   if (!mountpoint.isEmpty()) {
    40     _casterID += mountpoint;
    41   }
    42   if (!outHost.isEmpty()) {
    43     _casterID +=  " " + outHost;
    44     if (outPort) {
    45       _casterID += ":" +  QString("%1").arg(outPort, 10);
    46     }
    47   }
    48   if (!crdTrafo.isEmpty()) {
    49     _casterID += " " + crdTrafo;
    50   }
    51   if (!sp3FileName.isEmpty()) {
    52     _casterID += " " + sp3FileName;
    53   }
    54   if (!rnxFileName.isEmpty()) {
    55     _casterID += " " + rnxFileName;
    56   }
    57 
    58   if (!bsxFileName.isEmpty()) {
    59     _casterID += " " + bsxFileName;
    60   }
    61 
    62   _crdTrafoStr = crdTrafo;
    63 
    64   _ssrFormat = ssrFormat;
    65 
    66   _ssrCorr = 0;
    67   if      (_ssrFormat == "IGS-SSR") {
    68     _ssrCorr = new SsrCorrIgs();
    69   }
    70   else if (_ssrFormat == "RTCM-SSR") {
    71     _ssrCorr = new SsrCorrRtcm();
    72   }
    73 
    74   _CoM = CoM;
    75   _PID = PID;
    76   _SID = SID;
    77   _IOD = IOD;
    78   _phaseBiasInformationDecoded = false;
    79 
    80   // Member that receives the ephemeris
    81   // ----------------------------------
    82   _ephUser = new bncEphUser(true);
    83 
    84   bncSettings settings;
    85   QString intr = settings.value("uploadIntr").toString();
    86   QStringList hlp = settings.value("cmbStreams").toStringList();
    87   _samplRtcmEphCorr = settings.value("uploadSamplRtcmEphCorr").toDouble();
    88   if (hlp.size() > 1) { // combination stream upload
    89     _samplRtcmClkCorr = settings.value("cmbSampl").toInt();
    90   }
    91   else { // single stream upload or sp3 file generation
    92     _samplRtcmClkCorr = 5; // default
    93   }
    94   _samplRtcmVtec = 60.0;
    95   _samplRtcmCrs  = 60.0;
    96   int samplClkRnx = settings.value("uploadSamplClkRnx").toInt();
    97   int samplSp3    = settings.value("uploadSamplSp3").toString().split("sec").first().toInt();
    98   int samplBiaSnx = settings.value("uploadSamplBiaSnx").toInt();
    99 
    100   if (_samplRtcmEphCorr == 0.0) {
    101     _usedEph = 0;
    102   }
    103   else {
    104     _usedEph = new QMap<QString, const t_eph*>;
    105   }
    106 
    107   // RINEX writer
    108   // ------------
    109   if (!rnxFileName.isEmpty()) {
    110     _rnx = new bncClockRinex(rnxFileName, intr, samplClkRnx);
    111   }
    112   else {
    113     _rnx = 0;
    114   }
    115 
    116   // SP3 writer
    117   // ----------
    118   if (!sp3FileName.isEmpty()) {
    119     _sp3 = new bncSP3(sp3FileName, intr, samplSp3);
    120   }
    121   else {
    122     _sp3 = 0;
    123   }
    124 
    125   // SINEX writer
    126   // ------------
    127   if (!bsxFileName.isEmpty()) {
    128     _bsx = new bncBiasSinex(bsxFileName, intr, samplBiaSnx);
    129   }
    130   else {
    131     _bsx = 0;
    132   }
    133 
    134 
    135   // Set Transformation Parameters
    136   // -----------------------------
    137   // Transformation Parameters from ITRF2014 to ETRF2000
    138   // http://etrs89.ign.fr/pub/EUREF-TN-1-Mar-04-2024.pdf
    139   if (_crdTrafoStr == "ETRF2000") {
    140     _dx  =  0.0552;
    141     _dy  =  0.0527;
    142     _dz  = -0.0836;
    143 
    144     _dxr =  0.0001;
    145     _dyr =  0.0001;
    146     _dzr = -0.0019;
    147 
    148     _ox  =  0.002106;
    149     _oy  =  0.012740;
    150     _oz  = -0.020592;
    151 
    152     _oxr =  0.000081;
    153     _oyr =  0.000490;
    154     _ozr = -0.000792;
    155 
    156     _sc  =  2.67;
    157     _scr =  0.11;
    158 
    159     _t0  =  2015.0;
    160   }
    161   // Transformation Parameters from ITRF2014 to GDA2020 (Ryan Ruddick, GA)
    162   else if (_crdTrafoStr == "GDA2020") {
    163     _dx  = 0.0;
    164     _dy  = 0.0;
    165     _dz  = 0.0;
    166 
    167     _dxr = 0.0;
    168     _dyr = 0.0;
    169     _dzr = 0.0;
    170 
    171     _ox  = 0.0;
    172     _oy  = 0.0;
    173     _oz  = 0.0;
    174 
    175     _oxr = 0.00150379;
    176     _oyr = 0.00118346;
    177     _ozr = 0.00120716;
    178 
    179     _sc  = 0.0;
    180     _scr = 0.0;
    181 
    182     _t0  = 2020.0;
    183   }
    184   // Transformation Parameters from IGb14 to SIRGAS2000 (Thanks to Sonia Costa, BRA)
    185   // June 29 2020: TX:-0.0027 m  TY:-0.0025 m  TZ:-0.0042 m  SCL:1.20 (ppb) no rotations and no rates.*/
    186   else if (_crdTrafoStr == "SIRGAS2000") {
    187     _dx  = -0.0027;
    188     _dy  = -0.0025;
    189     _dz  = -0.0042;
    190 
    191     _dxr =  0.0;
    192     _dyr =  0.0;
    193     _dzr =  0.0;
    194 
    195     _ox  =  0.0;
    196     _oy  =  0.0;
    197     _oz  =  0.0;
    198 
    199     _oxr =  0.0;
    200     _oyr =  0.0;
    201     _ozr =  0.0;
    202 
    203     _sc  =  1.2;
    204     _scr =  0.0;
    205     _t0  =  2000.0;
    206   }
    207   // Transformation Parameters from ITRF2014 to DREF91
    208   else if (_crdTrafoStr == "DREF91") {
    209     _dx  =  0.0547;
    210     _dy  =  0.0522;
    211     _dz  = -0.0741;
    212 
    213     _dxr =  0.0001;
    214     _dyr =  0.0001;
    215     _dzr = -0.0019;
    216     // ERTF200  + rotation parameters (ETRF2000 => DREF91)
    217     _ox  =  0.001701 + 0.000658;
    218     _oy  =  0.010290 - 0.000208;
    219     _oz  = -0.016632 + 0.000755;
    220 
    221     _oxr =  0.000081;
    222     _oyr =  0.000490;
    223     _ozr = -0.000729;
    224 
    225     _sc  =  2.12;
    226     _scr =  0.11;
    227 
    228     _t0  =  2010.0;
    229   }
    230   else if (_crdTrafoStr == "Custom") {
    231     _dx = settings.value("trafo_dx").toDouble();
    232     _dy = settings.value("trafo_dy").toDouble();
    233     _dz = settings.value("trafo_dz").toDouble();
    234     _dxr = settings.value("trafo_dxr").toDouble();
    235     _dyr = settings.value("trafo_dyr").toDouble();
    236     _dzr = settings.value("trafo_dzr").toDouble();
    237     _ox = settings.value("trafo_ox").toDouble();
    238     _oy = settings.value("trafo_oy").toDouble();
    239     _oz = settings.value("trafo_oz").toDouble();
    240     _oxr = settings.value("trafo_oxr").toDouble();
    241     _oyr = settings.value("trafo_oyr").toDouble();
    242     _ozr = settings.value("trafo_ozr").toDouble();
    243     _sc = settings.value("trafo_sc").toDouble();
    244     _scr = settings.value("trafo_scr").toDouble();
    245     _t0 = settings.value("trafo_t0").toDouble();
    246   }
     39    if (!mountpoint.isEmpty()) {
     40        _casterID += mountpoint;
     41    }
     42    if (!outHost.isEmpty()) {
     43        _casterID += " " + outHost;
     44        if (outPort) {
     45            _casterID += ":" + QString("%1").arg(outPort, 10);
     46        }
     47    }
     48    if (!crdTrafo.isEmpty()) {
     49        _casterID += " " + crdTrafo;
     50    }
     51    if (!sp3FileName.isEmpty()) {
     52        _casterID += " " + sp3FileName;
     53    }
     54    if (!rnxFileName.isEmpty()) {
     55        _casterID += " " + rnxFileName;
     56    }
     57
     58    if (!bsxFileName.isEmpty()) {
     59        _casterID += " " + bsxFileName;
     60    }
     61
     62    _crdTrafoStr = crdTrafo;
     63
     64    _ssrFormat = ssrFormat;
     65
     66    _ssrCorr = 0;
     67    if (_ssrFormat == "IGS-SSR") {
     68        _ssrCorr = new SsrCorrIgs();
     69    }
     70    else if (_ssrFormat == "RTCM-SSR") {
     71        _ssrCorr = new SsrCorrRtcm();
     72    }
     73
     74    _CoM = CoM;
     75    _PID = PID;
     76    _SID = SID;
     77    _IOD = IOD;
     78    _phaseBiasInformationDecoded = false;
     79
     80    // Member that receives the ephemeris
     81    // ----------------------------------
     82    _ephUser = new bncEphUser(true);
     83
     84    bncSettings settings;
     85    QString intr      = settings.value("uploadIntr").toString();
     86    QStringList hlp   = settings.value("cmbStreams").toStringList();
     87    _samplRtcmEphCorr = settings.value("uploadSamplRtcmEphCorr").toString().split("sec").first().toDouble();
     88
     89    if (hlp.size() > 1) { // combination stream upload
     90        _samplRtcmClkCorr = settings.value("cmbSampl").toString().split("sec").first().toDouble();
     91    }
     92    else { // single stream upload or sp3 file generation
     93        _samplRtcmClkCorr = 5.0; // default
     94    }
     95    _samplRtcmVtec = 60.0;
     96    _samplRtcmCrs = 60.0;
     97    int samplClkRnx = settings.value("uploadSamplClkRnx").toString().split("sec").first().toInt();
     98    int samplSp3    = settings.value("uploadSamplSp3").toString().split("sec").first().toInt();
     99    int samplBiaSnx = settings.value("uploadSamplBiaSnx").toString().split("sec").first().toInt();
     100
     101    if (_samplRtcmEphCorr == 0.0) {
     102        _usedEph = 0;
     103    }
     104    else {
     105        _usedEph = new QMap<QString, const t_eph*>;
     106    }
     107
     108    // RINEX writer
     109    // ------------
     110    if (!rnxFileName.isEmpty()) {
     111        _rnx = new bncClockRinex(rnxFileName, intr, samplClkRnx);
     112    }
     113    else {
     114        _rnx = 0;
     115    }
     116
     117    // SP3 writer
     118    // ----------
     119    if (!sp3FileName.isEmpty()) {
     120        _sp3 = new bncSP3(sp3FileName, intr, samplSp3);
     121    }
     122    else {
     123        _sp3 = 0;
     124    }
     125
     126    // SINEX writer
     127    // ------------
     128    if (!bsxFileName.isEmpty()) {
     129        _bsx = new bncBiasSinex(bsxFileName, intr, samplBiaSnx);
     130    }
     131    else {
     132        _bsx = 0;
     133    }
     134
     135
     136    // Set Transformation Parameters
     137    // -----------------------------
     138    // Transformation Parameters from ITRF2014 to ETRF2000
     139    // http://etrs89.ign.fr/pub/EUREF-TN-1-Mar-04-2024.pdf
     140    if (_crdTrafoStr == "ETRF2000") {
     141        _dx = 0.0552;
     142        _dy = 0.0527;
     143        _dz = -0.0836;
     144
     145        _dxr = 0.0001;
     146        _dyr = 0.0001;
     147        _dzr = -0.0019;
     148
     149        _ox = 0.002106;
     150        _oy = 0.012740;
     151        _oz = -0.020592;
     152
     153        _oxr = 0.000081;
     154        _oyr = 0.000490;
     155        _ozr = -0.000792;
     156
     157        _sc = 2.67;
     158        _scr = 0.11;
     159
     160        _t0 = 2015.0;
     161    }
     162    // Transformation Parameters from ITRF2014 to GDA2020 (Ryan Ruddick, GA)
     163    else if (_crdTrafoStr == "GDA2020") {
     164        _dx = 0.0;
     165        _dy = 0.0;
     166        _dz = 0.0;
     167
     168        _dxr = 0.0;
     169        _dyr = 0.0;
     170        _dzr = 0.0;
     171
     172        _ox = 0.0;
     173        _oy = 0.0;
     174        _oz = 0.0;
     175
     176        _oxr = 0.00150379;
     177        _oyr = 0.00118346;
     178        _ozr = 0.00120716;
     179
     180        _sc = 0.0;
     181        _scr = 0.0;
     182
     183        _t0 = 2020.0;
     184    }
     185    // Transformation Parameters from IGb14 to SIRGAS2000 (Thanks to Sonia Costa, BRA)
     186    // June 29 2020: TX:-0.0027 m  TY:-0.0025 m  TZ:-0.0042 m  SCL:1.20 (ppb) no rotations and no rates.*/
     187    else if (_crdTrafoStr == "SIRGAS2000") {
     188        _dx = -0.0027;
     189        _dy = -0.0025;
     190        _dz = -0.0042;
     191
     192        _dxr = 0.0;
     193        _dyr = 0.0;
     194        _dzr = 0.0;
     195
     196        _ox = 0.0;
     197        _oy = 0.0;
     198        _oz = 0.0;
     199
     200        _oxr = 0.0;
     201        _oyr = 0.0;
     202        _ozr = 0.0;
     203
     204        _sc = 1.2;
     205        _scr = 0.0;
     206        _t0 = 2000.0;
     207    }
     208    // Transformation Parameters from ITRF2014 to DREF91
     209    else if (_crdTrafoStr == "DREF91") {
     210        _dx = 0.0547;
     211        _dy = 0.0522;
     212        _dz = -0.0741;
     213
     214        _dxr = 0.0001;
     215        _dyr = 0.0001;
     216        _dzr = -0.0019;
     217        // ERTF200  + rotation parameters (ETRF2000 => DREF91)
     218        _ox = 0.001701 + 0.000658;
     219        _oy = 0.010290 - 0.000208;
     220        _oz = -0.016632 + 0.000755;
     221
     222        _oxr = 0.000081;
     223        _oyr = 0.000490;
     224        _ozr = -0.000729;
     225
     226        _sc = 2.12;
     227        _scr = 0.11;
     228
     229        _t0 = 2010.0;
     230    }
     231    else if (_crdTrafoStr == "Custom") {
     232        _dx = settings.value("trafo_dx").toDouble();
     233        _dy = settings.value("trafo_dy").toDouble();
     234        _dz = settings.value("trafo_dz").toDouble();
     235        _dxr = settings.value("trafo_dxr").toDouble();
     236        _dyr = settings.value("trafo_dyr").toDouble();
     237        _dzr = settings.value("trafo_dzr").toDouble();
     238        _ox = settings.value("trafo_ox").toDouble();
     239        _oy = settings.value("trafo_oy").toDouble();
     240        _oz = settings.value("trafo_oz").toDouble();
     241        _oxr = settings.value("trafo_oxr").toDouble();
     242        _oyr = settings.value("trafo_oyr").toDouble();
     243        _ozr = settings.value("trafo_ozr").toDouble();
     244        _sc = settings.value("trafo_sc").toDouble();
     245        _scr = settings.value("trafo_scr").toDouble();
     246        _t0 = settings.value("trafo_t0").toDouble();
     247    }
    247248    // TODO: the following lines can be deleted if all parameters are updated regarding ITRF2020
    248   if (_crdTrafoStr == "ETRF2000" ||
    249       _crdTrafoStr == "GDA2020"  ||
    250       _crdTrafoStr == "DREF91"  ||
    251       _crdTrafoStr == "SIRGAS2000") {
    252        // Transformation Parameters from ITRF2020 to ITRF2014
    253        // from ITRF web site: https://itrf.ign.fr/en/solutions/transformations
    254    _dx14 = -0.0014;
    255    _dy14 = -0.0009;
    256    _dz14  = 0.0014;
    257    _dxr14 =  0.0;
    258    _dyr14 = -0.0001;
    259    _dzr14 = -0.0002;
    260    _ox14  = 0.0;
    261    _oy14  = 0.0;
    262    _oz14  = 0.0;
    263    _oxr14 =  0.0;
    264    _oyr14 =  0.0;
    265    _ozr14 =  0.0;
    266    _sc14 = -0.42;
    267    _scr14 =  0.0;
    268    _t014  = 2015.0;
    269  }
     249    if (_crdTrafoStr == "ETRF2000" ||
     250        _crdTrafoStr == "GDA2020" ||
     251        _crdTrafoStr == "DREF91" ||
     252        _crdTrafoStr == "SIRGAS2000") {
     253        // Transformation Parameters from ITRF2020 to ITRF2014
     254        // from ITRF web site: https://itrf.ign.fr/en/solutions/transformations
     255        _dx14 = -0.0014;
     256        _dy14 = -0.0009;
     257        _dz14 = 0.0014;
     258        _dxr14 = 0.0;
     259        _dyr14 = -0.0001;
     260        _dzr14 = -0.0002;
     261        _ox14 = 0.0;
     262        _oy14 = 0.0;
     263        _oz14 = 0.0;
     264        _oxr14 = 0.0;
     265        _oyr14 = 0.0;
     266        _ozr14 = 0.0;
     267        _sc14 = -0.42;
     268        _scr14 = 0.0;
     269        _t014 = 2015.0;
     270    }
    270271}
    271272
     
    273274////////////////////////////////////////////////////////////////////////////
    274275bncRtnetUploadCaster::~bncRtnetUploadCaster() {
    275   if (isRunning()) {
    276     wait();
    277   }
    278   delete _rnx;
    279   delete _sp3;
    280   delete _ephUser;
    281   delete _usedEph;
    282   delete _ssrCorr;
     276    if (isRunning()) {
     277        wait();
     278    }
     279    delete _rnx;
     280    delete _sp3;
     281    delete _bsx;
     282    delete _ephUser;
     283    delete _usedEph;
     284    delete _ssrCorr;
    283285}
    284286
     
    287289void bncRtnetUploadCaster::decodeRtnetStream(char* buffer, int bufLen) {
    288290
    289   QMutexLocker locker(&_mutex);
    290 
    291   // Append to internal buffer
    292   // -------------------------
    293   _rtnetStreamBuffer.append(QByteArray(buffer, bufLen));
    294 
    295   // Select buffer part that contains last epoch
    296   // -------------------------------------------
    297   QStringList lines;
    298   int iEpoBeg = _rtnetStreamBuffer.lastIndexOf('*');   // begin of last epoch
    299   if (iEpoBeg == -1) {
    300     _rtnetStreamBuffer.clear();
    301     return;
    302   }
    303   _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoBeg);
    304 
    305   int iEpoEnd = _rtnetStreamBuffer.lastIndexOf("EOE"); // end   of last epoch
    306   if (iEpoEnd == -1) {
    307     return;
    308   }
    309   else {
    310     lines = _rtnetStreamBuffer.left(iEpoEnd).split('\n', Qt::SkipEmptyParts);
    311     _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoEnd+3);
    312   }
    313 
    314   if (lines.size() < 2) {
    315       emit(newMessage(
     291    QMutexLocker locker(&_mutex);
     292
     293    // Append to internal buffer
     294    // -------------------------
     295    _rtnetStreamBuffer.append(QByteArray(buffer, bufLen));
     296
     297    // Select buffer part that contains last epoch
     298    // -------------------------------------------
     299    QStringList lines;
     300    int iEpoBeg = _rtnetStreamBuffer.lastIndexOf('*');   // begin of last epoch
     301    if (iEpoBeg == -1) {
     302        _rtnetStreamBuffer.clear();
     303        return;
     304    }
     305    _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoBeg);
     306
     307    int iEpoEnd = _rtnetStreamBuffer.lastIndexOf("EOE"); // end   of last epoch
     308    if (iEpoEnd == -1) {
     309        return;
     310    }
     311    else {
     312        lines = _rtnetStreamBuffer.left(iEpoEnd).split('\n', Qt::SkipEmptyParts);
     313        _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoEnd + 3);
     314    }
     315
     316    if (lines.size() < 2) {
     317        emit(newMessage(
    316318            "bncRtnetUploadCaster: less than 2 lines to decode " + _casterID.toLatin1(), false));
    317     return;
    318   }
    319 
    320   // Keep the last unfinished line in buffer
    321   // ---------------------------------------
    322   int iLastEOL = _rtnetStreamBuffer.lastIndexOf('\n');
    323   if (iLastEOL != -1) {
    324     _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iLastEOL+1);
    325   }
    326 
    327   decodeRtnetEpoch(lines);
    328 }
    329 
    330 //
    331 ////////////////////////////////////////////////////////////////////////////
    332 void bncRtnetUploadCaster::decodeRtnetEpoch(QStringList epochLines) {
    333 
    334   // Read first line (with epoch time)
    335   // ---------------------------------
    336   QTextStream in(epochLines[0].toLatin1());
    337   QString hlp;
    338   int year, month, day, hour, min;
    339   double sec;
    340   in >> hlp >> year >> month >> day >> hour >> min >> sec;
    341   bncTime epoTime;
    342   epoTime.set(year, month, day, hour, min, sec);//cout <<  epoTime.timestr().c_str() << endl;
    343 
    344   emit(newMessage(
    345       "bncRtnetUploadCaster: decode " + QByteArray(epoTime.datestr().c_str())
    346           + " " + QByteArray(epoTime.timestr().c_str()) + " "
    347           + _casterID.toLatin1(), false));
    348 
    349   struct SsrCorr::ClockOrbit co;
    350   memset(&co, 0, sizeof(co));
    351   co.EpochTime[CLOCKORBIT_SATGPS] = static_cast<int>(epoTime.gpssec());
    352   double gt = epoTime.gpssec() - gnumleap(year, month, day);
    353   if      (_ssrFormat == "RTCM-SSR") {
    354     gt += 3 * 3600;
    355   }
    356   co.EpochTime[CLOCKORBIT_SATGLONASS] = static_cast<int>(fmod(gt, 86400.0));
    357   co.EpochTime[CLOCKORBIT_SATGALILEO] = static_cast<int>(epoTime.gpssec());
    358   co.EpochTime[CLOCKORBIT_SATQZSS]    = static_cast<int>(epoTime.gpssec());
    359   co.EpochTime[CLOCKORBIT_SATSBAS]    = static_cast<int>(epoTime.gpssec());
    360   co.EpochTime[CLOCKORBIT_SATBDS]     = static_cast<int>(epoTime.bdssec());
    361   co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
    362   co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
    363   (_crdTrafoStr == "IGS20") ?
    364       co.SatRefDatum = _ssrCorr->DATUM_ITRF :
    365       co.SatRefDatum = _ssrCorr->DATUM_LOCAL;
    366   co.SSRIOD        = _IOD;
    367   co.SSRProviderID = _PID; // 256 .. BKG,  257 ... EUREF
    368   co.SSRSolutionID = _SID;
    369   if      (_ssrFormat == "RTCM-SSR") {
     319        return;
     320    }
     321
     322    // Keep the last unfinished line in buffer
     323    // ---------------------------------------
     324    int iLastEOL = _rtnetStreamBuffer.lastIndexOf('\n');
     325    if (iLastEOL != -1) {
     326        _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iLastEOL + 1);
     327    }
     328
     329
     330    // Read first line (with epoch time)
     331    // ---------------------------------
     332    //QTextStream in(lines[0].toLatin1());
     333    QTextStream in(&lines[0], QIODevice::ReadOnly);
     334    QString hlp;
     335    int year, month, day, hour, min;
     336    double sec;
     337    in >> hlp >> year >> month >> day >> hour >> min >> sec;
     338    bncTime epoTime;
     339    epoTime.set(year, month, day, hour, min, sec);
     340
     341    emit(newMessage(
     342        "bncRtnetUploadCaster: decode " + QByteArray(epoTime.datestr().c_str())
     343        + " " + QByteArray(epoTime.timestr().c_str()) + " "
     344        + _casterID.toLatin1(), false));
     345
     346    struct SsrCorr::ClockOrbit co;
     347    memset(&co, 0, sizeof(co));
     348    co.EpochTime[CLOCKORBIT_SATGPS] = static_cast<int>(epoTime.gpssec());
     349    double gt = epoTime.gpssec() - gnumleap(year, month, day);
     350    if (_ssrFormat == "RTCM-SSR") {
     351        gt += 3 * 3600;
     352    }
     353    co.EpochTime[CLOCKORBIT_SATGLONASS] = static_cast<int>(fmod(gt, 86400.0));
     354    co.EpochTime[CLOCKORBIT_SATGALILEO] = static_cast<int>(epoTime.gpssec());
     355    co.EpochTime[CLOCKORBIT_SATQZSS] = static_cast<int>(epoTime.gpssec());
     356    co.EpochTime[CLOCKORBIT_SATSBAS] = static_cast<int>(epoTime.gpssec());
    370357    co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.bdssec());
    371   }
    372   else if (_ssrFormat == "IGS-SSR") {
    373     co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.gpssec());
    374   }
    375   co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
    376   co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
    377 
    378 
    379   t_serviceCrs serviceCrs;
    380   t_rtcmCrs    rtcmCrs;
    381   if (_crdTrafoStr == "IGS20") {
    382     serviceCrs._CE = serviceCrs._coordinateEpoch  = 0;
    383     int nc = _crdTrafoStr.length();
    384     if (nc > 31) {nc = 31;}
    385     for (int i = 0; i < nc; i++) {
    386       serviceCrs._name[i] =
    387          rtcmCrs._name[i] = _crdTrafoStr.toStdString()[i];
    388     }
    389     serviceCrs._name[nc] = 0;
    390     rtcmCrs._name[nc] = 0;
    391     rtcmCrs._anchor      = 0; // global CRS
    392     rtcmCrs._plateNumber = 0; // unknown
    393     rtcmCrs._databaseLinks << "ISO.DATUM.979" << "ISO.CRS:980";
    394   }
    395   else {
    396     if (_crdTrafoStr != "Custom") {
    397       serviceCrs._coordinateEpoch = _t0;
    398       serviceCrs.setCEFromCoordinateEpoch();
    399       int nc = _crdTrafoStr.length();
    400       if (nc > 31) {nc = 31;}
    401       for (int i = 0; i < nc; i++) {
    402         serviceCrs._name[i] = _crdTrafoStr.toStdString()[i];
    403       }
    404       serviceCrs._name[nc] = 0;
    405       QString rtcmcrsname = _crdTrafoStr + QString("(%1)").arg(_t0,4,'d',0);
    406       nc = rtcmcrsname.length();
    407       if (nc > 31) {nc = 31;}
    408       for (int i = 0; i < nc; i++) {
    409         rtcmCrs._name[i] = rtcmcrsname.toStdString()[i];
    410       }
    411       rtcmCrs._name[nc] = 0;
    412       if (_crdTrafoStr == "ETRF2000") {
    413         rtcmCrs._anchor      = 1; // plate-fixed CRS
    414         rtcmCrs._plateNumber = 7; // Eurasia
    415         rtcmCrs._databaseLinks << "ISO.DATUM.187"    << "ISO.CRS:260"   << "ISO.CRS:457"
    416                                << "EPSG.DATUM:1186"  << "EPSG.CRS:7930" << "EPSG.CRS:7931";
    417       }
    418       else if (_crdTrafoStr == "DREF91") {
    419         rtcmCrs._anchor      = 1; // plate-fixed CRS
    420         rtcmCrs._plateNumber = 7; // Eurasia
    421       }
    422       else if (_crdTrafoStr == "GDA2020") {
    423         rtcmCrs._anchor      = 1; // plate-fixed CRS
    424         rtcmCrs._plateNumber = 4; // Australia
    425         rtcmCrs._databaseLinks << "ISO.DATUM.186"   << "ISO.CRS:404"   << "ISO.CRS:329"
    426                                << "EPSG.DATUM:1168" << "EPSG.CRS:7842" << "EPSG.CRS:7843";
    427       }
    428       else if (_crdTrafoStr == "SIRGAS2000") {
    429         rtcmCrs._anchor      =  1; // plate-fixed CRS
    430         rtcmCrs._plateNumber = 12; // S.America
    431         rtcmCrs._databaseLinks << "ISO.DATUM:169"   << "ISO.CRS:384"   << "ISO.CRS:313"
    432                                << "EPSG.DATUM:6674" << "EPSG.CRS:4988" << "EPSG.CRS:4989";
    433       }
    434     }
    435   }
    436 
    437   struct SsrCorr::CodeBias bias;
    438   memset(&bias, 0, sizeof(bias));
    439   bias.EpochTime[CLOCKORBIT_SATGPS]     = co.EpochTime[CLOCKORBIT_SATGPS];
    440   bias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
    441   bias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
    442   bias.EpochTime[CLOCKORBIT_SATQZSS]    = co.EpochTime[CLOCKORBIT_SATQZSS];
    443   bias.EpochTime[CLOCKORBIT_SATSBAS]    = co.EpochTime[CLOCKORBIT_SATSBAS];
    444   bias.EpochTime[CLOCKORBIT_SATBDS]     = co.EpochTime[CLOCKORBIT_SATBDS];
    445   bias.SSRIOD        = _IOD;
    446   bias.SSRProviderID = _PID;
    447   bias.SSRSolutionID = _SID;
    448 
    449   struct SsrCorr::PhaseBias phasebias;
    450   memset(&phasebias, 0, sizeof(phasebias));
    451   unsigned int dispersiveBiasConsistenyIndicator = 0;
    452   unsigned int mwConsistencyIndicator = 0;
    453   phasebias.EpochTime[CLOCKORBIT_SATGPS]     = co.EpochTime[CLOCKORBIT_SATGPS];
    454   phasebias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
    455   phasebias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
    456   phasebias.EpochTime[CLOCKORBIT_SATQZSS]    = co.EpochTime[CLOCKORBIT_SATQZSS];
    457   phasebias.EpochTime[CLOCKORBIT_SATSBAS]    = co.EpochTime[CLOCKORBIT_SATSBAS];
    458   phasebias.EpochTime[CLOCKORBIT_SATBDS]     = co.EpochTime[CLOCKORBIT_SATBDS];
    459   phasebias.SSRIOD        = _IOD;
    460   phasebias.SSRProviderID = _PID;
    461   phasebias.SSRSolutionID = _SID;
    462 
    463   struct SsrCorr::VTEC vtec;
    464   memset(&vtec, 0, sizeof(vtec));
    465   vtec.EpochTime = static_cast<int>(epoTime.gpssec());
    466   vtec.SSRIOD        = _IOD;
    467   vtec.SSRProviderID = _PID;
    468   vtec.SSRSolutionID = _SID;
    469 
    470   // Default Update Interval
    471   // -----------------------
    472   int clkUpdInd = 2;         // 5 sec
    473   int ephUpdInd = clkUpdInd; // default
    474 
    475   if (!_samplRtcmEphCorr) {
    476     _samplRtcmEphCorr = 5.0;
    477   }
    478 
    479   if (_samplRtcmClkCorr > 5.0 && _samplRtcmEphCorr <= 5.0) { // combined orb and clock
    480     ephUpdInd = determineUpdateInd(_samplRtcmClkCorr);
    481   }
    482   if (_samplRtcmClkCorr > 5.0) {
    483     clkUpdInd = determineUpdateInd(_samplRtcmClkCorr);
    484   }
    485   if (_samplRtcmEphCorr > 5.0) {
    486     ephUpdInd = determineUpdateInd(_samplRtcmEphCorr);
    487   }
    488 
    489   co.UpdateInterval = clkUpdInd;
    490   bias.UpdateInterval = ephUpdInd;
    491   phasebias.UpdateInterval = ephUpdInd;
    492 
    493   for (int ii = 1; ii < epochLines.size(); ii++) {
    494     QString key;  // prn or key VTEC, IND (phase bias indicators)
    495     double rtnUra = 0.0; // [m]
    496     ColumnVector rtnAPC; rtnAPC.ReSize(3); rtnAPC = 0.0;          // [m, m, m]
    497     ColumnVector rtnVel; rtnVel.ReSize(3); rtnVel = 0.0;          // [m/s, m/s, m/s]
    498     ColumnVector rtnCoM; rtnCoM.ReSize(3); rtnCoM = 0.0;          // [m, m, m]
    499     ColumnVector rtnClk; rtnClk.ReSize(3); rtnClk = 0.0;          // [m, m/s, m/s²]
    500     ColumnVector rtnClkSig; rtnClkSig.ReSize(3); rtnClkSig = 0.0; // [m, m/s, m/s²]
    501 
    502     QTextStream in(epochLines[ii].toLatin1());
    503 
    504     in >> key;
    505 
    506     // non-satellite specific parameters
    507     if (key.contains("IND", Qt::CaseSensitive)) {
    508       in >> dispersiveBiasConsistenyIndicator >> mwConsistencyIndicator;
    509       continue;
    510     }
    511     // non-satellite specific parameters
    512     if (key.contains("VTEC", Qt::CaseSensitive)) {
    513       double ui;
    514       in >> ui >> vtec.NumLayers;
    515       vtec.UpdateInterval = (unsigned int) determineUpdateInd(ui);
    516       for (unsigned ll = 0; ll < vtec.NumLayers; ll++) {
    517         int dummy;
    518         in >> dummy >> vtec.Layers[ll].Degree >> vtec.Layers[ll].Order
    519             >> vtec.Layers[ll].Height;
    520         for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
    521           for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
    522             in >> vtec.Layers[ll].Cosinus[iDeg][iOrd];
    523           }
    524         }
    525         for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
    526           for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
    527             in >> vtec.Layers[ll].Sinus[iDeg][iOrd];
    528           }
    529         }
    530       }
    531       continue;
    532     }
    533     // satellite specific parameters
    534     t_prn prn;
    535     char sys = key.mid(0, 1).at(0).toLatin1();
    536     int  num = key.mid(1, 2).toInt();
    537     int flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
    538     if (!num) {
    539       continue;
    540     }
    541     prn.set(sys, num, flag);
    542     QString prnInternalStr = QString::fromStdString(prn.toInternalString());
    543     QString prnStr         = QString::fromStdString(prn.toString());
    544 
    545     const t_eph* ephLast = _ephUser->ephLast(prnInternalStr);
    546     const t_eph* ephPrev = _ephUser->ephPrev(prnInternalStr);
    547     const t_eph* eph = ephLast;
    548     if (eph) {
    549 
    550       // Use previous ephemeris if the last one is too recent
    551       // ----------------------------------------------------
    552       const int MINAGE = 60; // seconds
    553       if (ephPrev && eph->receptDateTime().isValid() &&
    554           eph->receptDateTime().secsTo(currentDateAndTimeGPS()) < MINAGE) {
    555         eph = ephPrev;
    556       }
    557 
    558       // Make sure the clock messages refer to same IOD as orbit messages
    559       // ----------------------------------------------------------------
    560       if (_usedEph) {
     358    co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
     359    co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
     360    (_crdTrafoStr == "IGS20") ?
     361        co.SatRefDatum = _ssrCorr->DATUM_ITRF :
     362        co.SatRefDatum = _ssrCorr->DATUM_LOCAL;
     363    co.SSRIOD = _IOD;
     364    co.SSRProviderID = _PID; // 256 .. BKG,  257 ... EUREF
     365    co.SSRSolutionID = _SID;
     366    if (_ssrFormat == "RTCM-SSR") {
     367        co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.bdssec());
     368    }
     369    else if (_ssrFormat == "IGS-SSR") {
     370        co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.gpssec());
     371    }
     372    co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
     373    co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
     374
     375
     376    t_serviceCrs serviceCrs;
     377    t_rtcmCrs    rtcmCrs;
     378    if (_crdTrafoStr == "IGS20") {
     379        serviceCrs._CE = serviceCrs._coordinateEpoch = 0;
     380        int nc = _crdTrafoStr.length();
     381        if (nc > 31) { nc = 31; }
     382        for (int i = 0; i < nc; i++) {
     383            serviceCrs._name[i] =
     384                rtcmCrs._name[i] = _crdTrafoStr.toStdString()[i];
     385        }
     386        serviceCrs._name[nc] = 0;
     387        rtcmCrs._name[nc] = 0;
     388        rtcmCrs._anchor = 0; // global CRS
     389        rtcmCrs._plateNumber = 0; // unknown
     390        rtcmCrs._databaseLinks << "ISO.DATUM.979" << "ISO.CRS:980";
     391    }
     392    else {
     393        if (_crdTrafoStr != "Custom") {
     394            serviceCrs._coordinateEpoch = _t0;
     395            serviceCrs.setCEFromCoordinateEpoch();
     396            int nc = _crdTrafoStr.length();
     397            if (nc > 31) { nc = 31; }
     398            for (int i = 0; i < nc; i++) {
     399                serviceCrs._name[i] = _crdTrafoStr.toStdString()[i];
     400            }
     401            serviceCrs._name[nc] = 0;
     402            QString rtcmcrsname = _crdTrafoStr + QString("(%1)").arg(_t0, 4, 'd', 0);
     403            nc = rtcmcrsname.length();
     404            if (nc > 31) { nc = 31; }
     405            for (int i = 0; i < nc; i++) {
     406                rtcmCrs._name[i] = rtcmcrsname.toStdString()[i];
     407            }
     408            rtcmCrs._name[nc] = 0;
     409            if (_crdTrafoStr == "ETRF2000") {
     410                rtcmCrs._anchor = 1; // plate-fixed CRS
     411                rtcmCrs._plateNumber = 7; // Eurasia
     412                rtcmCrs._databaseLinks << "ISO.DATUM.187" << "ISO.CRS:260" << "ISO.CRS:457"
     413                    << "EPSG.DATUM:1186" << "EPSG.CRS:7930" << "EPSG.CRS:7931";
     414            }
     415            else if (_crdTrafoStr == "DREF91") {
     416                rtcmCrs._anchor = 1; // plate-fixed CRS
     417                rtcmCrs._plateNumber = 7; // Eurasia
     418            }
     419            else if (_crdTrafoStr == "GDA2020") {
     420                rtcmCrs._anchor = 1; // plate-fixed CRS
     421                rtcmCrs._plateNumber = 4; // Australia
     422                rtcmCrs._databaseLinks << "ISO.DATUM.186" << "ISO.CRS:404" << "ISO.CRS:329"
     423                    << "EPSG.DATUM:1168" << "EPSG.CRS:7842" << "EPSG.CRS:7843";
     424            }
     425            else if (_crdTrafoStr == "SIRGAS2000") {
     426                rtcmCrs._anchor = 1; // plate-fixed CRS
     427                rtcmCrs._plateNumber = 12; // S.America
     428                rtcmCrs._databaseLinks << "ISO.DATUM:169" << "ISO.CRS:384" << "ISO.CRS:313"
     429                    << "EPSG.DATUM:6674" << "EPSG.CRS:4988" << "EPSG.CRS:4989";
     430            }
     431        }
     432    }
     433
     434    struct SsrCorr::CodeBias bias;
     435    memset(&bias, 0, sizeof(bias));
     436    bias.EpochTime[CLOCKORBIT_SATGPS] = co.EpochTime[CLOCKORBIT_SATGPS];
     437    bias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
     438    bias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
     439    bias.EpochTime[CLOCKORBIT_SATQZSS] = co.EpochTime[CLOCKORBIT_SATQZSS];
     440    bias.EpochTime[CLOCKORBIT_SATSBAS] = co.EpochTime[CLOCKORBIT_SATSBAS];
     441    bias.EpochTime[CLOCKORBIT_SATBDS] = co.EpochTime[CLOCKORBIT_SATBDS];
     442    bias.SSRIOD = _IOD;
     443    bias.SSRProviderID = _PID;
     444    bias.SSRSolutionID = _SID;
     445
     446    struct SsrCorr::PhaseBias phasebias;
     447    memset(&phasebias, 0, sizeof(phasebias));
     448    unsigned int dispersiveBiasConsistenyIndicator = 0;
     449    unsigned int mwConsistencyIndicator = 0;
     450    phasebias.EpochTime[CLOCKORBIT_SATGPS] = co.EpochTime[CLOCKORBIT_SATGPS];
     451    phasebias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
     452    phasebias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
     453    phasebias.EpochTime[CLOCKORBIT_SATQZSS] = co.EpochTime[CLOCKORBIT_SATQZSS];
     454    phasebias.EpochTime[CLOCKORBIT_SATSBAS] = co.EpochTime[CLOCKORBIT_SATSBAS];
     455    phasebias.EpochTime[CLOCKORBIT_SATBDS] = co.EpochTime[CLOCKORBIT_SATBDS];
     456    phasebias.SSRIOD = _IOD;
     457    phasebias.SSRProviderID = _PID;
     458    phasebias.SSRSolutionID = _SID;
     459
     460    struct SsrCorr::VTEC vtec;
     461    memset(&vtec, 0, sizeof(vtec));
     462    vtec.EpochTime = static_cast<int>(epoTime.gpssec());
     463    vtec.SSRIOD = _IOD;
     464    vtec.SSRProviderID = _PID;
     465    vtec.SSRSolutionID = _SID;
     466
     467    // Update Interval
     468    // ---------------
     469
     470    if (_samplRtcmEphCorr == 0.0) {// combined orb and clock
     471        _samplRtcmEphCorr = _samplRtcmClkCorr = 5.0;
     472    }
     473    int clkUpdInd = determineUpdateInd(_samplRtcmClkCorr);
     474    int ephUpdInd = determineUpdateInd(_samplRtcmEphCorr);
     475
     476    co.UpdateInterval = clkUpdInd;
     477    bias.UpdateInterval = ephUpdInd;
     478    phasebias.UpdateInterval = ephUpdInd;
     479
     480    for (int ii = 1; ii < lines.size(); ii++) {
     481        QString key;  // prn or key VTEC, IND (phase bias indicators)
     482        double rtnUra = 0.0; // [m]
     483        ColumnVector rtnAPC; rtnAPC.ReSize(3); rtnAPC = 0.0;          // [m, m, m]
     484        ColumnVector rtnVel; rtnVel.ReSize(3); rtnVel = 0.0;          // [m/s, m/s, m/s]
     485        ColumnVector rtnCoM; rtnCoM.ReSize(3); rtnCoM = 0.0;          // [m, m, m]
     486        ColumnVector rtnClk; rtnClk.ReSize(3); rtnClk = 0.0;          // [m, m/s, m/s²]
     487        ColumnVector rtnClkSig; rtnClkSig.ReSize(3); rtnClkSig = 0.0; // [m, m/s, m/s²]
     488
     489        //QTextStream in(lines[ii].toLatin1());
     490        QTextStream in(&lines[ii], QIODevice::ReadOnly);
     491        in >> key;
     492
     493        // non-satellite specific parameters
     494        if (key.contains("IND", Qt::CaseSensitive)) {
     495            in >> dispersiveBiasConsistenyIndicator >> mwConsistencyIndicator;
     496            continue;
     497        }
     498        // non-satellite specific parameters
     499        if (key.contains("VTEC", Qt::CaseSensitive)) {
     500            double ui;
     501            in >> ui >> vtec.NumLayers;
     502            vtec.UpdateInterval = (unsigned int)determineUpdateInd(ui);
     503            for (unsigned ll = 0; ll < vtec.NumLayers; ll++) {
     504                int dummy;
     505                in >> dummy >> vtec.Layers[ll].Degree >> vtec.Layers[ll].Order
     506                    >> vtec.Layers[ll].Height;
     507                for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
     508                    for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
     509                        in >> vtec.Layers[ll].Cosinus[iDeg][iOrd];
     510                    }
     511                }
     512                for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
     513                    for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
     514                        in >> vtec.Layers[ll].Sinus[iDeg][iOrd];
     515                    }
     516                }
     517            }
     518            continue;
     519        }
     520        // satellite specific parameters
     521        t_prn prn;
     522        char sys = key.mid(0, 1).at(0).toLatin1();
     523        int  num = key.mid(1, 2).toInt();
     524        int flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
     525        if (!num) {
     526            continue;
     527        }
     528        prn.set(sys, num, flag);
     529        QString prnInternalStr = QString::fromStdString(prn.toInternalString());
     530        QString prnStr = QString::fromStdString(prn.toString());
     531
     532        const t_eph* ephLast = _ephUser->ephLast(prnInternalStr);
     533        const t_eph* ephPrev = _ephUser->ephPrev(prnInternalStr);
     534        const t_eph* eph = ephLast;
     535        if (eph) {
     536
     537            // Use previous ephemeris if the last one is too recent
     538            // ----------------------------------------------------
     539            const int MINAGE = 60; // seconds
     540            if (ephPrev && eph->receptDateTime().isValid() &&
     541                eph->receptDateTime().secsTo(currentDateAndTimeGPS()) < MINAGE) {
     542                eph = ephPrev;
     543            }
     544
     545            // Make sure the clock messages refer to same IOD as orbit messages
     546            // ----------------------------------------------------------------
     547            if (_usedEph) {
     548                if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     549                    (*_usedEph)[prnInternalStr] = eph;
     550                }
     551                else {
     552                    eph = 0;
     553                    if (_usedEph->contains(prnInternalStr)) {
     554                        const t_eph* usedEph = _usedEph->value(prnInternalStr);
     555                        if (usedEph == ephLast) {
     556                            eph = ephLast;
     557                        }
     558                        else if (usedEph == ephPrev) {
     559                            eph = ephPrev;
     560                        }
     561                    }
     562                }
     563            }
     564        }
     565
     566        QDateTime now = currentDateAndTimeGPS();
     567        bncTime   currentTime(now.toString(Qt::ISODate).toStdString());
     568        if (eph &&
     569            !outDatedBcep(eph, currentTime) &&  // detected from storage because of no update
     570            eph->checkState() != t_eph::bad &&
     571            eph->checkState() != t_eph::unhealthy &&
     572            eph->checkState() != t_eph::outdated) {   // detected during reception (bncephuser)
     573            QMap<QString, double> codeBiases;
     574            QList<phaseBiasSignal> phaseBiasList;
     575            phaseBiasesSat pbSat;
     576            _phaseBiasInformationDecoded = false;
     577
     578            while (true) {
     579                QString key;
     580                int numVal = 0;
     581                in >> key;
     582                if (in.status() != QTextStream::Ok) {
     583                    break;
     584                }
     585                if (key == "APC") {
     586                    in >> numVal;
     587                    rtnAPC.ReSize(3); rtnAPC = 0.0;
     588                    for (int ii = 0; ii < numVal; ii++) {
     589                        in >> rtnAPC[ii];
     590                    }
     591                }
     592                else if (key == "Ura") {
     593                    in >> numVal;
     594                    if (numVal == 1)
     595                        in >> rtnUra;
     596                }
     597                else if (key == "Clk") {
     598                    in >> numVal;
     599                    rtnClk.ReSize(3); rtnClk = 0.0;
     600                    for (int ii = 0; ii < numVal; ii++) {
     601                        in >> rtnClk[ii];
     602                    }
     603                }
     604                else if (key == "ClkSig") {
     605                    in >> numVal;
     606                    rtnClkSig.ReSize(3); rtnClkSig = 0.0;
     607                    for (int ii = 0; ii < numVal; ii++) {
     608                        in >> rtnClkSig[ii];
     609                    }
     610                }
     611                else if (key == "Vel") {
     612                    in >> numVal;
     613                    rtnVel.ReSize(3); rtnVel = 0.0;
     614                    for (int ii = 0; ii < numVal; ii++) {
     615                        in >> rtnVel[ii];
     616                    }
     617                }
     618                else if (key == "CoM") {
     619                    in >> numVal;
     620                    rtnCoM.ReSize(3); rtnCoM = 0.0;
     621                    for (int ii = 0; ii < numVal; ii++) {
     622                        in >> rtnCoM[ii];
     623                    }
     624                }
     625                else if (key == "CodeBias") {
     626                    in >> numVal;
     627                    for (int ii = 0; ii < numVal; ii++) {
     628                        QString type;
     629                        double value;
     630                        in >> type >> value;
     631                        codeBiases[type] = value;
     632                    }
     633                }
     634                else if (key == "YawAngle") {
     635                    _phaseBiasInformationDecoded = true;
     636                    in >> numVal >> pbSat.yawAngle;
     637                    if (pbSat.yawAngle < 0.0) {
     638                        pbSat.yawAngle += (2 * M_PI);
     639                    }
     640                    else if (pbSat.yawAngle > 2 * M_PI) {
     641                        pbSat.yawAngle -= (2 * M_PI);
     642                    }
     643                }
     644                else if (key == "YawRate") {
     645                    _phaseBiasInformationDecoded = true;
     646                    in >> numVal >> pbSat.yawRate;
     647                }
     648                else if (key == "PhaseBias") {
     649                    _phaseBiasInformationDecoded = true;
     650                    in >> numVal;
     651                    for (int ii = 0; ii < numVal; ii++) {
     652                        phaseBiasSignal pb;
     653                        in >> pb.type >> pb.bias >> pb.integerIndicator
     654                            >> pb.wlIndicator >> pb.discontinuityCounter;
     655                        phaseBiasList.append(pb);
     656                    }
     657                }
     658                else {
     659                    in >> numVal;
     660                    for (int ii = 0; ii < numVal; ii++) {
     661                        double dummy;
     662                        in >> dummy;
     663                    }
     664                    emit(newMessage("                      RTNET format error: "
     665                        + lines[ii].toLatin1(), false));
     666                    break;
     667                }
     668            }
     669
     670            struct SsrCorr::ClockOrbit::SatData* sd = 0;
     671            if (prn.system() == 'G') {
     672                sd = co.Sat + co.NumberOfSat[CLOCKORBIT_SATGPS];
     673                ++co.NumberOfSat[CLOCKORBIT_SATGPS];
     674            }
     675            else if (prn.system() == 'R') {
     676                sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfSat[CLOCKORBIT_SATGLONASS];
     677                ++co.NumberOfSat[CLOCKORBIT_SATGLONASS];
     678            }
     679            else if (prn.system() == 'E') {
     680                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     681                    + co.NumberOfSat[CLOCKORBIT_SATGALILEO];
     682                ++co.NumberOfSat[CLOCKORBIT_SATGALILEO];
     683            }
     684            else if (prn.system() == 'J') {
     685                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     686                    + CLOCKORBIT_NUMGALILEO
     687                    + co.NumberOfSat[CLOCKORBIT_SATQZSS];
     688                ++co.NumberOfSat[CLOCKORBIT_SATQZSS];
     689            }
     690            else if (prn.system() == 'S') {
     691                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     692                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     693                    + co.NumberOfSat[CLOCKORBIT_SATSBAS];
     694                ++co.NumberOfSat[CLOCKORBIT_SATSBAS];
     695            }
     696            else if (prn.system() == 'C') {
     697                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     698                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     699                    + CLOCKORBIT_NUMSBAS
     700                    + co.NumberOfSat[CLOCKORBIT_SATBDS];
     701                ++co.NumberOfSat[CLOCKORBIT_SATBDS];
     702            }
     703            if (sd) {
     704                QString outLine;
     705                t_irc irc = processSatellite(eph, epoTime.gpsw(), epoTime.gpssec(), prnStr, rtnAPC,
     706                    rtnUra, rtnClk, rtnVel, rtnCoM, rtnClkSig, sd, outLine);
     707                if (irc != success) {
     708                    continue;
     709                }
     710            }
     711
     712            // Code Biases
     713            // -----------
     714            struct SsrCorr::CodeBias::BiasSat* biasSat = 0;
     715            if (!codeBiases.isEmpty()) {
     716                if (prn.system() == 'G') {
     717                    biasSat = bias.Sat + bias.NumberOfSat[CLOCKORBIT_SATGPS];
     718                    ++bias.NumberOfSat[CLOCKORBIT_SATGPS];
     719                }
     720                else if (prn.system() == 'R') {
     721                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS
     722                        + bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     723                    ++bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     724                }
     725                else if (prn.system() == 'E') {
     726                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     727                        + bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     728                    ++bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     729                }
     730                else if (prn.system() == 'J') {
     731                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     732                        + CLOCKORBIT_NUMGALILEO
     733                        + bias.NumberOfSat[CLOCKORBIT_SATQZSS];
     734                    ++bias.NumberOfSat[CLOCKORBIT_SATQZSS];
     735                }
     736                else if (prn.system() == 'S') {
     737                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     738                        + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     739                        + bias.NumberOfSat[CLOCKORBIT_SATSBAS];
     740                    ++bias.NumberOfSat[CLOCKORBIT_SATSBAS];
     741                }
     742                else if (prn.system() == 'C') {
     743                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     744                        + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     745                        + CLOCKORBIT_NUMSBAS
     746                        + bias.NumberOfSat[CLOCKORBIT_SATBDS];
     747                    ++bias.NumberOfSat[CLOCKORBIT_SATBDS];
     748                }
     749            }
     750
     751            if (biasSat) {
     752                biasSat->ID = prn.number();
     753                biasSat->NumberOfCodeBiases = 0;
     754                QMapIterator<QString, double> it(codeBiases);
     755                while (it.hasNext()) {
     756                    it.next();
     757                    int ii = biasSat->NumberOfCodeBiases;
     758                    if (ii >= CLOCKORBIT_NUMBIAS)
     759                        break;
     760                    SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), it.key().toStdString());
     761                    if (type != _ssrCorr->RESERVED) {
     762                        biasSat->NumberOfCodeBiases += 1;
     763                        biasSat->Biases[ii].Type = type;
     764                        biasSat->Biases[ii].Bias = it.value();
     765                        if (_bsx) {
     766                            QString obsCode = 'C' + it.key();
     767                            _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, it.value());
     768                        }
     769                    }
     770                }
     771            }
     772
     773            // Phase Biases
     774            // ------------
     775            struct SsrCorr::PhaseBias::PhaseBiasSat* phasebiasSat = 0;
     776            if (prn.system() == 'G') {
     777                phasebiasSat = phasebias.Sat
     778                    + phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
     779                ++phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
     780            }
     781            else if (prn.system() == 'R') {
     782                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS
     783                    + phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     784                ++phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     785            }
     786            else if (prn.system() == 'E') {
     787                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     788                    + phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     789                ++phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     790            }
     791            else if (prn.system() == 'J') {
     792                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     793                    + CLOCKORBIT_NUMGALILEO
     794                    + phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
     795                ++phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
     796            }
     797            else if (prn.system() == 'S') {
     798                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     799                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     800                    + phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
     801                ++phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
     802            }
     803            else if (prn.system() == 'C') {
     804                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     805                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     806                    + CLOCKORBIT_NUMSBAS
     807                    + phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
     808                ++phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
     809            }
     810
     811            if (phasebiasSat && _phaseBiasInformationDecoded) {
     812                phasebias.DispersiveBiasConsistencyIndicator = dispersiveBiasConsistenyIndicator;
     813                phasebias.MWConsistencyIndicator = mwConsistencyIndicator;
     814                phasebiasSat->ID = prn.number();
     815                phasebiasSat->NumberOfPhaseBiases = 0;
     816                phasebiasSat->YawAngle = pbSat.yawAngle;
     817                phasebiasSat->YawRate = pbSat.yawRate;
     818                QListIterator<phaseBiasSignal> it(phaseBiasList);
     819                while (it.hasNext()) {
     820                    const phaseBiasSignal& pbSig = it.next();
     821                    int ii = phasebiasSat->NumberOfPhaseBiases;
     822                    if (ii >= CLOCKORBIT_NUMBIAS)
     823                        break;
     824                    SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), pbSig.type.toStdString());
     825                    if (type != _ssrCorr->RESERVED) {
     826                        phasebiasSat->NumberOfPhaseBiases += 1;
     827                        phasebiasSat->Biases[ii].Type = type;
     828                        phasebiasSat->Biases[ii].Bias = pbSig.bias;
     829                        phasebiasSat->Biases[ii].SignalIntegerIndicator = pbSig.integerIndicator;
     830                        phasebiasSat->Biases[ii].SignalsWideLaneIntegerIndicator = pbSig.wlIndicator;
     831                        phasebiasSat->Biases[ii].SignalDiscontinuityCounter = pbSig.discontinuityCounter;
     832                        if (_bsx) {
     833                            QString obsCode = 'L' + pbSig.type;
     834                            _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, pbSig.bias);
     835                        }
     836                    }
     837                }
     838            }
     839        }
     840    }
     841
     842    QByteArray hlpBufferCo;
     843    char obuffer[CLOCKORBIT_BUFFERSIZE];
     844    size_t len = 0;
     845
     846    // Orbit and Clock Corrections together
     847    // ------------------------------------
     848    if (_samplRtcmEphCorr == _samplRtcmClkCorr) {
     849        if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0
     850            || co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
     851            || co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
     852            || co.NumberOfSat[CLOCKORBIT_SATBDS] > 0
     853            || co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
     854            || co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
     855            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     856                memset(obuffer, 0, sizeof(obuffer));
     857                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
     858                if (len > 0) {
     859                    hlpBufferCo = QByteArray(obuffer, int(len));
     860                }
     861            }
     862        }
     863    }
     864
     865    // Orbit and Clock Corrections separately
     866    // --------------------------------------
     867    else {
     868        if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
     869            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     870                co.UpdateInterval = ephUpdInd;
     871                memset(obuffer, 0, sizeof(obuffer));
     872                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSORBIT, 1, obuffer, sizeof(obuffer));
     873                if (len > 0) {
     874                    hlpBufferCo += QByteArray(obuffer, int(len));
     875                }
     876            }
     877            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0 ||
     878                co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
     879                co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ||
     880                co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     881                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     882            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     883                co.UpdateInterval = clkUpdInd;
     884                memset(obuffer, 0, sizeof(obuffer));
     885                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSCLOCK, mmsg, obuffer, sizeof(obuffer));
     886                if (len > 0) {
     887                    hlpBufferCo += QByteArray(obuffer, int(len));
     888                }
     889            }
     890        }
     891        if (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
     892            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     893                co.UpdateInterval = ephUpdInd;
     894                memset(obuffer, 0, sizeof(obuffer));
     895                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSORBIT, 1, obuffer, sizeof(obuffer));
     896                if (len > 0) {
     897                    hlpBufferCo += QByteArray(obuffer, int(len));
     898                }
     899            }
     900            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
     901                co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ||
     902                co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     903                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     904            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     905                co.UpdateInterval = clkUpdInd;
     906                memset(obuffer, 0, sizeof(obuffer));
     907                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSCLOCK, mmsg, obuffer, sizeof(obuffer));
     908                if (len > 0) {
     909                    hlpBufferCo += QByteArray(obuffer, int(len));
     910                }
     911            }
     912        }
     913        if (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
     914            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     915                co.UpdateInterval = ephUpdInd;
     916                memset(obuffer, 0, sizeof(obuffer));
     917                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOORBIT, 1, obuffer, sizeof(obuffer));
     918                if (len > 0) {
     919                    hlpBufferCo += QByteArray(obuffer, int(len));
     920                }
     921            }
     922            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ||
     923                co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     924                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     925            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     926                co.UpdateInterval = clkUpdInd;
     927                memset(obuffer, 0, sizeof(obuffer));
     928                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOCLOCK, mmsg, obuffer, sizeof(obuffer));
     929                if (len > 0) {
     930                    hlpBufferCo += QByteArray(obuffer, int(len));
     931                }
     932            }
     933        }
     934        if (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
     935            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     936                co.UpdateInterval = ephUpdInd;
     937                memset(obuffer, 0, sizeof(obuffer));
     938                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSORBIT, 1, obuffer, sizeof(obuffer));
     939                if (len > 0) {
     940                    hlpBufferCo += QByteArray(obuffer, int(len));
     941                }
     942            }
     943            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     944                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     945            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     946                co.UpdateInterval = clkUpdInd;
     947                memset(obuffer, 0, sizeof(obuffer));
     948                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSCLOCK, mmsg, obuffer, sizeof(obuffer));
     949                if (len > 0) {
     950                    hlpBufferCo += QByteArray(obuffer, int(len));
     951                }
     952            }
     953        }
     954        if (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
     955            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     956                co.UpdateInterval = ephUpdInd;
     957                memset(obuffer, 0, sizeof(obuffer));
     958                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSORBIT, 1, obuffer, sizeof(obuffer));
     959                if (len > 0) {
     960                    hlpBufferCo += QByteArray(obuffer, int(len));
     961                }
     962            }
     963            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     964            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     965                co.UpdateInterval = clkUpdInd;
     966                memset(obuffer, 0, sizeof(obuffer));
     967                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSCLOCK, mmsg, obuffer, sizeof(obuffer));
     968                if (len > 0) {
     969                    hlpBufferCo += QByteArray(obuffer, int(len));
     970                }
     971            }
     972        }
     973        if (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
     974            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     975                co.UpdateInterval = ephUpdInd;
     976                memset(obuffer, 0, sizeof(obuffer));
     977                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASORBIT, 1, obuffer, sizeof(obuffer));
     978                co.UpdateInterval = clkUpdInd;
     979                if (len > 0) {
     980                    hlpBufferCo += QByteArray(obuffer, int(len));
     981                }
     982            }
     983            int mmsg = 0;
     984            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     985                co.UpdateInterval = clkUpdInd;
     986                memset(obuffer, 0, sizeof(obuffer));
     987                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASCLOCK, mmsg, obuffer, sizeof(obuffer));
     988                if (len > 0) {
     989                    hlpBufferCo += QByteArray(obuffer, int(len));
     990                }
     991            }
     992        }
     993    }
     994
     995    // Code Biases
     996    // -----------
     997    QByteArray hlpBufferBias;
     998    if (bias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
     999        || bias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
     1000        || bias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
     1001        || bias.NumberOfSat[CLOCKORBIT_SATBDS] > 0
     1002        || bias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
     1003        || bias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
    5611004        if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    562           (*_usedEph)[prnInternalStr] = eph;
    563         }
    564         else {
    565           eph = 0;
    566           if (_usedEph->contains(prnInternalStr)) {
    567             const t_eph* usedEph = _usedEph->value(prnInternalStr);
    568             if (usedEph == ephLast) {
    569               eph = ephLast;
    570             }
    571             else if (usedEph == ephPrev) {
    572               eph = ephPrev;
    573             }
    574           }
    575         }
    576       }
    577     }
    578 
    579     QDateTime now = currentDateAndTimeGPS();
    580     bncTime   currentTime(now.toString(Qt::ISODate).toStdString());
    581     if (eph &&
    582         !outDatedBcep(eph, currentTime)       &&  // detected from storage because of no update
    583         eph->checkState() != t_eph::bad       &&
    584         eph->checkState() != t_eph::unhealthy &&
    585         eph->checkState() != t_eph::outdated) {   // detected during reception (bncephuser)
    586       QMap<QString, double> codeBiases;
    587       QList<phaseBiasSignal> phaseBiasList;
    588       phaseBiasesSat pbSat;
    589       _phaseBiasInformationDecoded = false;
    590 
    591       while (true) {
    592         QString key;
    593         int numVal = 0;
    594         in >> key;
    595         if (in.status() != QTextStream::Ok) {
    596           break;
    597         }
    598         if (key == "APC") {
    599           in >> numVal;
    600           rtnAPC.ReSize(3); rtnAPC = 0.0;
    601           for (int ii = 0; ii < numVal; ii++) {
    602             in >> rtnAPC[ii];
    603           }
    604         }
    605         else if (key == "Ura") {
    606           in >> numVal;
    607           if (numVal == 1)
    608             in >> rtnUra;
    609         }
    610         else if (key == "Clk") {
    611           in >> numVal;
    612           rtnClk.ReSize(3); rtnClk = 0.0;
    613           for (int ii = 0; ii < numVal; ii++) {
    614             in >> rtnClk[ii];
    615           }
    616         }
    617         else if (key == "ClkSig") {
    618           in >> numVal;
    619           rtnClkSig.ReSize(3); rtnClkSig = 0.0;
    620           for (int ii = 0; ii < numVal; ii++) {
    621             in >> rtnClkSig[ii];
    622           }
    623         }
    624         else if (key == "Vel") {
    625           in >> numVal;
    626           rtnVel.ReSize(3); rtnVel = 0.0;
    627           for (int ii = 0; ii < numVal; ii++) {
    628             in >> rtnVel[ii];
    629           }
    630         }
    631         else if (key == "CoM") {
    632           in >> numVal;
    633           rtnCoM.ReSize(3); rtnCoM = 0.0;
    634           for (int ii = 0; ii < numVal; ii++) {
    635             in >> rtnCoM[ii];
    636           }
    637         }
    638         else if (key == "CodeBias") {
    639           in >> numVal;
    640           for (int ii = 0; ii < numVal; ii++) {
    641             QString type;
    642             double value;
    643             in >> type >> value;
    644             codeBiases[type] = value;
    645           }
    646         }
    647         else if (key == "YawAngle") {
    648           _phaseBiasInformationDecoded = true;
    649           in >> numVal >> pbSat.yawAngle;
    650           if      (pbSat.yawAngle < 0.0) {
    651             pbSat.yawAngle += (2*M_PI);
    652           }
    653           else if (pbSat.yawAngle > 2*M_PI) {
    654             pbSat.yawAngle -= (2*M_PI);
    655           }
    656         }
    657         else if (key == "YawRate") {
    658           _phaseBiasInformationDecoded = true;
    659           in >> numVal >> pbSat.yawRate;
    660         }
    661         else if (key == "PhaseBias") {
    662           _phaseBiasInformationDecoded = true;
    663           in >> numVal;
    664           for (int ii = 0; ii < numVal; ii++) {
    665             phaseBiasSignal pb;
    666             in >> pb.type >> pb.bias >> pb.integerIndicator
    667               >> pb.wlIndicator >> pb.discontinuityCounter;
    668             phaseBiasList.append(pb);
    669           }
    670         }
    671         else {
    672           in >> numVal;
    673           for (int ii = 0; ii < numVal; ii++) {
    674             double dummy;
    675             in >> dummy;
    676           }
    677           emit(newMessage("                      RTNET format error: "
    678                           +  epochLines[ii].toLatin1(), false));
    679           break;
    680         }
    681       }
    682 
    683       struct SsrCorr::ClockOrbit::SatData* sd = 0;
    684       if (prn.system() == 'G') {
    685         sd = co.Sat + co.NumberOfSat[CLOCKORBIT_SATGPS];
    686         ++co.NumberOfSat[CLOCKORBIT_SATGPS];
    687       }
    688       else if (prn.system() == 'R') {
    689         sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfSat[CLOCKORBIT_SATGLONASS];
    690         ++co.NumberOfSat[CLOCKORBIT_SATGLONASS];
    691       }
    692       else if (prn.system() == 'E') {
    693         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    694            + co.NumberOfSat[CLOCKORBIT_SATGALILEO];
    695         ++co.NumberOfSat[CLOCKORBIT_SATGALILEO];
    696       }
    697       else if (prn.system() == 'J') {
    698         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    699            + CLOCKORBIT_NUMGALILEO
    700            + co.NumberOfSat[CLOCKORBIT_SATQZSS];
    701         ++co.NumberOfSat[CLOCKORBIT_SATQZSS];
    702       }
    703       else if (prn.system() == 'S') {
    704         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    705             + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    706             + co.NumberOfSat[CLOCKORBIT_SATSBAS];
    707         ++co.NumberOfSat[CLOCKORBIT_SATSBAS];
    708       }
    709       else if (prn.system() == 'C') {
    710         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    711             + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    712             + CLOCKORBIT_NUMSBAS
    713             + co.NumberOfSat[CLOCKORBIT_SATBDS];
    714         ++co.NumberOfSat[CLOCKORBIT_SATBDS];
    715       }
    716       if (sd) {
    717         QString outLine;
    718         t_irc irc = processSatellite(eph, epoTime.gpsw(), epoTime.gpssec(), prnStr, rtnAPC,
    719                                      rtnUra, rtnClk, rtnVel, rtnCoM, rtnClkSig, sd, outLine);
    720         if (irc != success) {
    721           continue;
    722         }
    723       }
    724 
    725       // Code Biases
    726       // -----------
    727       struct SsrCorr::CodeBias::BiasSat* biasSat = 0;
    728       if (!codeBiases.isEmpty()) {
    729         if (prn.system() == 'G') {
    730           biasSat = bias.Sat + bias.NumberOfSat[CLOCKORBIT_SATGPS];
    731           ++bias.NumberOfSat[CLOCKORBIT_SATGPS];
    732         }
    733         else if (prn.system() == 'R') {
    734           biasSat = bias.Sat + CLOCKORBIT_NUMGPS
    735                   + bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    736           ++bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    737         }
    738         else if (prn.system() == 'E') {
    739           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    740                   + bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    741           ++bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    742         }
    743         else if (prn.system() == 'J') {
    744           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    745                   + CLOCKORBIT_NUMGALILEO
    746                   + bias.NumberOfSat[CLOCKORBIT_SATQZSS];
    747           ++bias.NumberOfSat[CLOCKORBIT_SATQZSS];
    748         }
    749         else if (prn.system() == 'S') {
    750           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    751                   + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    752                   + bias.NumberOfSat[CLOCKORBIT_SATSBAS];
    753           ++bias.NumberOfSat[CLOCKORBIT_SATSBAS];
    754         }
    755         else if (prn.system() == 'C') {
    756           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    757                   + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    758                   + CLOCKORBIT_NUMSBAS
    759                   + bias.NumberOfSat[CLOCKORBIT_SATBDS];
    760           ++bias.NumberOfSat[CLOCKORBIT_SATBDS];
    761         }
    762       }
    763 
    764       if (biasSat) {
    765         biasSat->ID = prn.number();
    766         biasSat->NumberOfCodeBiases = 0;
    767         QMapIterator<QString, double> it(codeBiases);
    768         while (it.hasNext()) {
    769           it.next();
    770           int ii = biasSat->NumberOfCodeBiases;
    771           if (ii >= CLOCKORBIT_NUMBIAS)
    772             break;
    773           SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), it.key().toStdString());
    774           if (type != _ssrCorr->RESERVED) {
    775             biasSat->NumberOfCodeBiases += 1;
    776             biasSat->Biases[ii].Type = type;
    777             biasSat->Biases[ii].Bias = it.value();
    778             if (_bsx) {
    779               QString obsCode = 'C' + it.key();
    780               _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, it.value());
    781             }
    782           }
    783         }
    784       }
    785 
    786       // Phase Biases
    787       // ------------
    788       struct SsrCorr::PhaseBias::PhaseBiasSat* phasebiasSat = 0;
    789       if (prn.system()      == 'G') {
    790         phasebiasSat = phasebias.Sat
    791                      + phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
    792         ++phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
    793       }
    794       else if (prn.system() == 'R') {
    795         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS
    796                      + phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    797         ++phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    798       }
    799       else if (prn.system() == 'E') {
    800         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    801                      + phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    802         ++phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    803       }
    804       else if (prn.system() == 'J') {
    805         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    806                      + CLOCKORBIT_NUMGALILEO
    807                      + phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
    808         ++phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
    809       }
    810       else if (prn.system() == 'S') {
    811         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    812                      + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    813                      + phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
    814         ++phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
    815       }
    816       else if (prn.system() == 'C') {
    817         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    818                      + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    819                      + CLOCKORBIT_NUMSBAS
    820                      + phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
    821         ++phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
    822       }
    823 
    824       if (phasebiasSat && _phaseBiasInformationDecoded) {
    825         phasebias.DispersiveBiasConsistencyIndicator = dispersiveBiasConsistenyIndicator;
    826         phasebias.MWConsistencyIndicator = mwConsistencyIndicator;
    827         phasebiasSat->ID = prn.number();
    828         phasebiasSat->NumberOfPhaseBiases = 0;
    829         phasebiasSat->YawAngle = pbSat.yawAngle;
    830         phasebiasSat->YawRate = pbSat.yawRate;
    831         QListIterator<phaseBiasSignal> it(phaseBiasList);
    832         while (it.hasNext()) {
    833           const phaseBiasSignal &pbSig = it.next();
    834           int ii = phasebiasSat->NumberOfPhaseBiases;
    835           if (ii >= CLOCKORBIT_NUMBIAS)
    836             break;
    837           SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), pbSig.type.toStdString());
    838           if (type != _ssrCorr->RESERVED) {
    839             phasebiasSat->NumberOfPhaseBiases += 1;
    840             phasebiasSat->Biases[ii].Type = type;
    841             phasebiasSat->Biases[ii].Bias = pbSig.bias;
    842             phasebiasSat->Biases[ii].SignalIntegerIndicator = pbSig.integerIndicator;
    843             phasebiasSat->Biases[ii].SignalsWideLaneIntegerIndicator = pbSig.wlIndicator;
    844             phasebiasSat->Biases[ii].SignalDiscontinuityCounter = pbSig.discontinuityCounter;
    845             if (_bsx) {
    846               QString obsCode = 'L' + pbSig.type;
    847               _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, pbSig.bias);
    848             }
    849           }
    850         }
    851       }
    852     }
    853   }
    854 
    855   QByteArray hlpBufferCo;
    856 
    857   // Orbit and Clock Corrections together
    858   // ------------------------------------
    859   if (_samplRtcmEphCorr == _samplRtcmClkCorr) {
    860     if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0
    861         || co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
    862         || co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
    863         || co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
    864         || co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
    865         || co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
    866       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    867       int len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
    868       if (len > 0) {
    869         hlpBufferCo = QByteArray(obuffer, len);
    870       }
    871     }
    872   }
    873 
    874   // Orbit and Clock Corrections separately
    875   // --------------------------------------
    876   else {
    877     if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
    878       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    879       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    880         co.UpdateInterval = ephUpdInd;
    881         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSORBIT, 1, obuffer, sizeof(obuffer));
    882         co.UpdateInterval = clkUpdInd;
    883         if (len1 > 0) {
    884           hlpBufferCo += QByteArray(obuffer, len1);
    885         }
    886       }
    887       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0 ||
    888                   co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
    889                   co.NumberOfSat[CLOCKORBIT_SATQZSS]    > 0 ||
    890                   co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    891                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    892       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSCLOCK, mmsg, obuffer, sizeof(obuffer));
    893       if (len2 > 0) {
    894         hlpBufferCo += QByteArray(obuffer, len2);
    895       }
    896     }
    897     if (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
    898       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    899       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    900         co.UpdateInterval = ephUpdInd;
    901         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSORBIT, 1, obuffer, sizeof(obuffer));
    902         co.UpdateInterval = clkUpdInd;
    903         if (len1 > 0) {
    904           hlpBufferCo += QByteArray(obuffer, len1);
    905         }
    906       }
    907       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
    908                   co.NumberOfSat[CLOCKORBIT_SATQZSS]    > 0 ||
    909                   co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    910                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    911       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSCLOCK, mmsg, obuffer, sizeof(obuffer));
    912       if (len2 > 0) {
    913         hlpBufferCo += QByteArray(obuffer, len2);
    914       }
    915     }
    916     if (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
    917       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    918       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    919         co.UpdateInterval = ephUpdInd;
    920         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOORBIT, 1, obuffer, sizeof(obuffer));
    921         co.UpdateInterval = clkUpdInd;
    922         if (len1 > 0) {
    923           hlpBufferCo += QByteArray(obuffer, len1);
    924         }
    925       }
    926       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATQZSS]    > 0 ||
    927                   co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    928                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    929       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOCLOCK, mmsg, obuffer, sizeof(obuffer));
    930       if (len2 > 0) {
    931         hlpBufferCo += QByteArray(obuffer, len2);
    932       }
    933     }
    934     if (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
    935       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    936       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    937         co.UpdateInterval = ephUpdInd;
    938         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSORBIT, 1, obuffer, sizeof(obuffer));
    939         co.UpdateInterval = clkUpdInd;
    940         if (len1 > 0) {
    941           hlpBufferCo += QByteArray(obuffer, len1);
    942         }
    943       }
    944       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    945                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    946       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSCLOCK, mmsg, obuffer, sizeof(obuffer));
    947       if (len2 > 0) {
    948         hlpBufferCo += QByteArray(obuffer, len2);
    949       }
    950     }
    951     if (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
    952       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    953       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    954         co.UpdateInterval = ephUpdInd;
    955         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASORBIT, 1, obuffer, sizeof(obuffer));
    956         co.UpdateInterval = clkUpdInd;
    957         if (len1 > 0) {
    958           hlpBufferCo += QByteArray(obuffer, len1);
    959         }
    960       }
    961       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) ? 1 : 0;
    962       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASCLOCK, mmsg, obuffer,
    963           sizeof(obuffer));
    964       if (len2 > 0) {
    965         hlpBufferCo += QByteArray(obuffer, len2);
    966       }
    967     }
    968     if (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
    969       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    970       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    971         co.UpdateInterval = ephUpdInd;
    972         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSORBIT, 1, obuffer, sizeof(obuffer));
    973         co.UpdateInterval = clkUpdInd;
    974         if (len1 > 0) {
    975           hlpBufferCo += QByteArray(obuffer, len1);
    976         }
    977       }
    978       int mmsg = 0;
    979       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSCLOCK, mmsg, obuffer, sizeof(obuffer));
    980       if (len2 > 0) {
    981         hlpBufferCo += QByteArray(obuffer, len2);
    982       }
    983     }
    984   }
    985 
    986   // Code Biases
    987   // -----------
    988   QByteArray hlpBufferBias;
    989   if (bias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
    990       || bias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
    991       || bias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
    992       || bias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
    993       || bias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
    994       || bias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
    995     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    996     if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    997       int len = _ssrCorr->MakeCodeBias(&bias, _ssrCorr->CBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
    998       if (len > 0) {
    999         hlpBufferBias = QByteArray(obuffer, len);
    1000       }
    1001     }
    1002   }
    1003 
    1004   // Phase Biases
    1005   // ------------
    1006   QByteArray hlpBufferPhaseBias;
    1007   if ((phasebias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
    1008       || phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
    1009       || phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
    1010       || phasebias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
    1011       || phasebias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
    1012       || phasebias.NumberOfSat[CLOCKORBIT_SATBDS] > 0)
    1013       && (_phaseBiasInformationDecoded)) {
    1014     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1015     if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    1016       int len = _ssrCorr->MakePhaseBias(&phasebias, _ssrCorr->PBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
    1017       if (len > 0) {
    1018         hlpBufferPhaseBias = QByteArray(obuffer, len);
    1019       }
    1020     }
    1021   }
    1022 
    1023   // VTEC
    1024   // ----
    1025   QByteArray hlpBufferVtec;
    1026   if (vtec.NumLayers > 0) {
    1027     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1028     if (fmod(epoTime.gpssec(), _samplRtcmVtec) == 0.0) {
    1029       int len = _ssrCorr->MakeVTEC(&vtec, 0, obuffer, sizeof(obuffer));
    1030       if (len > 0) {
    1031         hlpBufferVtec = QByteArray(obuffer, len);
    1032       }
    1033     }
    1034   }
    1035 
    1036   // Service CRS
    1037   // -----------
    1038   QByteArray hlpBufferServiceCrs;
    1039   if (sizeof(serviceCrs._name) > 0) {
    1040     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1041     if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
    1042       int len = t_crsEncoder::RTCM3(serviceCrs, obuffer, sizeof(obuffer));
    1043       if (len > 0) {
    1044         hlpBufferServiceCrs = QByteArray(obuffer, len);
    1045       }
    1046     }
    1047   }
    1048 
    1049   // RTCM CRS
    1050   // --------
    1051   QByteArray hlpBufferRtcmCrs;
    1052   if (sizeof(rtcmCrs._name) > 0) {
    1053     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1054     if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
    1055       int len = t_crsEncoder::RTCM3(rtcmCrs, obuffer, sizeof(obuffer));
    1056       if (len > 0) {
    1057         hlpBufferRtcmCrs = QByteArray(obuffer, len);
    1058       }
    1059     }
    1060   }
    1061 
    1062   // Create OutBuffer
    1063   // ----------------
    1064   _outBuffer += hlpBufferCo + hlpBufferBias + hlpBufferPhaseBias + hlpBufferVtec
    1065       + hlpBufferServiceCrs + hlpBufferRtcmCrs + '\0';
     1005            memset(obuffer, 0, sizeof(obuffer));
     1006            len = _ssrCorr->MakeCodeBias(&bias, _ssrCorr->CBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
     1007            if (len > 0) {
     1008                hlpBufferBias = QByteArray(obuffer, int(len));
     1009            }
     1010        }
     1011    }
     1012
     1013    // Phase Biases
     1014    // ------------
     1015    QByteArray hlpBufferPhaseBias;
     1016    if ((phasebias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
     1017        || phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
     1018        || phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
     1019        || phasebias.NumberOfSat[CLOCKORBIT_SATBDS] > 0
     1020        || phasebias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
     1021        || phasebias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) && (_phaseBiasInformationDecoded)) {
     1022        if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     1023            memset(obuffer, 0, sizeof(obuffer));
     1024            len = _ssrCorr->MakePhaseBias(&phasebias, _ssrCorr->PBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
     1025            if (len > 0) {
     1026                hlpBufferPhaseBias = QByteArray(obuffer, int(len));
     1027            }
     1028        }
     1029    }
     1030
     1031    // VTEC
     1032    // ----
     1033    QByteArray hlpBufferVtec;
     1034    if (vtec.NumLayers > 0) {
     1035        if (fmod(epoTime.gpssec(), _samplRtcmVtec) == 0.0) {
     1036            memset(obuffer, 0, sizeof(obuffer));
     1037            len = _ssrCorr->MakeVTEC(&vtec, 0, obuffer, sizeof(obuffer));
     1038            if (len > 0) {
     1039                hlpBufferVtec = QByteArray(obuffer, int(len));
     1040            }
     1041        }
     1042    }
     1043
     1044    // Service CRS
     1045    // -----------
     1046    QByteArray hlpBufferServiceCrs;
     1047    if (sizeof(serviceCrs._name) > 0) {
     1048        if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
     1049            memset(obuffer, 0, sizeof(obuffer));
     1050            len = t_crsEncoder::RTCM3(serviceCrs, obuffer, sizeof(obuffer));
     1051            if (len > 0) {
     1052                hlpBufferServiceCrs = QByteArray(obuffer, int(len));
     1053            }
     1054        }
     1055    }
     1056
     1057    // RTCM CRS
     1058    // --------
     1059    QByteArray hlpBufferRtcmCrs;
     1060    if (sizeof(rtcmCrs._name) > 0) {
     1061        if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
     1062            memset(obuffer, 0, sizeof(obuffer));
     1063            len = t_crsEncoder::RTCM3(rtcmCrs, obuffer, sizeof(obuffer));
     1064            if (len > 0) {
     1065                hlpBufferRtcmCrs = QByteArray(obuffer, int(len));
     1066            }
     1067        }
     1068    }
     1069
     1070    // Create OutBuffer
     1071    // ----------------
     1072    _outBuffer += hlpBufferCo + hlpBufferBias + hlpBufferPhaseBias + hlpBufferVtec
     1073        + hlpBufferServiceCrs + hlpBufferRtcmCrs + '\0';
    10661074}
    10671075//
     
    10731081    struct SsrCorr::ClockOrbit::SatData* sd, QString& outLine) {
    10741082
    1075   // Broadcast Position and Velocity
    1076   // -------------------------------
    1077   ColumnVector xB(6);
    1078   ColumnVector vB(3);
    1079   t_irc irc = eph->getCrd(bncTime(GPSweek, GPSweeks), xB, vB, false);
    1080 
    1081   if (irc != success) {
    1082     return irc;
    1083   }
    1084 
    1085   // Precise Position
    1086   // ----------------
    1087   ColumnVector xP = _CoM ? rtnCoM : rtnAPC;
    1088 
    1089   if (xP.size() == 0) {
    1090     return failure;
    1091   }
    1092 
    1093   double dc = 0.0;
    1094   if (_crdTrafoStr != "IGS20") {
    1095     crdTrafo14(GPSweek, xP, dc); // ITRF2020 => ITRF2014
    1096     crdTrafo(GPSweek, xP, dc);   // ITRF2014 to other reference frames
    1097   }
    1098 
    1099   // Difference in xyz
    1100   // -----------------
    1101   ColumnVector dx = xB.Rows(1, 3) - xP;
    1102   ColumnVector dv = vB - rtnVel;
    1103 
    1104   // Difference in RSW
    1105   // -----------------
    1106   ColumnVector rsw(3);
    1107   XYZ_to_RSW(xB.Rows(1, 3), vB, dx, rsw);
    1108 
    1109   ColumnVector dotRsw(3);
    1110   XYZ_to_RSW(xB.Rows(1, 3), vB, dv, dotRsw);
    1111 
    1112   // Clock Correction
    1113   // ----------------
    1114   double dClkA0 = rtnClk(1) - (xB(4) - dc) * t_CST::c;
    1115   double dClkA1 = 0.0;
    1116   if (rtnClk(2)) {
    1117     dClkA1 = rtnClk(2) - xB(5) * t_CST::c;
    1118   }
    1119   double dClkA2 = 0.0;
    1120   if (rtnClk(3)) {
    1121     dClkA2 = rtnClk(3) - xB(6) * t_CST::c;
    1122   }
    1123 
    1124   if (sd) {
    1125     sd->ID = prn.mid(1).toInt();
    1126     sd->IOD = eph->IOD();
    1127     sd->Clock.DeltaA0 = dClkA0;
    1128     sd->Clock.DeltaA1 = dClkA1;
    1129     sd->Clock.DeltaA2 = dClkA2;
    1130     sd->UserRangeAccuracy = rtnUra;
    1131     sd->Orbit.DeltaRadial    = rsw(1);
    1132     sd->Orbit.DeltaAlongTrack = rsw(2);
    1133     sd->Orbit.DeltaCrossTrack = rsw(3);
    1134     sd->Orbit.DotDeltaRadial    = dotRsw(1);
    1135     sd->Orbit.DotDeltaAlongTrack = dotRsw(2);
    1136     sd->Orbit.DotDeltaCrossTrack = dotRsw(3);
    1137 
    1138     if (corrIsOutOfRange(sd)) {
    1139       emit(newMessage(QString("bncRtnetUploadCaster: SSR parameter is out of its defined range").toLatin1(), false));
    1140       return failure;
    1141     }
    1142   }
    1143 
    1144   outLine = QString().asprintf("%d %.1f %s  %u  %10.3f %8.3f %8.3f  %8.3f %8.3f %8.3f\n", GPSweek,
    1145       GPSweeks, eph->prn().toString().c_str(), eph->IOD(), dClkA0, dClkA1, dClkA2,
    1146       rsw(1), rsw(2), rsw(3));  //fprintf(stderr, "%s\n", outLine.toStdString().c_str());
    1147 
    1148   // RTNET full clock for RINEX and SP3 file
    1149   // ---------------------------------------
    1150   double relativity = -2.0 * DotProduct(xP, rtnVel) / t_CST::c;
    1151   double clkRnx    = (rtnClk[0] - relativity) / t_CST::c;  // [s]
    1152   double clkRnxRate = rtnClk[1] / t_CST::c;                 // [s/s  = -]
    1153   double clkRnxAcc  = rtnClk[2] / t_CST::c;                 // [s/s² = -/s]
    1154 
    1155   if (_rnx) {
    1156     double clkRnxSig, clkRnxRateSig, clkRnxAccSig;
    1157     int s = rtnClkSig.size();
    1158     switch (s) {
    1159       case 1:
    1160         clkRnxSig    = rtnClkSig[0] / t_CST::c;    // [s]
    1161         clkRnxRateSig = 0.0;                        // [s/s = -]
    1162         clkRnxAccSig  = 0.0;                        // [s/s² ) -/s]
    1163         break;
    1164       case 2:
    1165         clkRnxSig    = rtnClkSig[0] / t_CST::c;     // [s]
    1166         clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
    1167         clkRnxAccSig  = 0.0;                         // [s/s² ) -/s]
    1168         break;
    1169       case 3:
    1170         clkRnxSig    = rtnClkSig[0] / t_CST::c;     // [s]
    1171         clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
    1172         clkRnxAccSig  = rtnClkSig[2] / t_CST::c;     // [s/s² ) -/s]
    1173         break;
    1174     }
    1175     _rnx->write(GPSweek, GPSweeks, prn, clkRnx, clkRnxRate, clkRnxAcc,
    1176                 clkRnxSig, clkRnxRateSig, clkRnxAccSig);
    1177   }
    1178   if (_sp3) {
    1179     _sp3->write(GPSweek, GPSweeks, prn, rtnCoM, clkRnx, rtnVel, clkRnxRate);
    1180   }
    1181   return success;
     1083    // Broadcast Position and Velocity
     1084    // -------------------------------
     1085    ColumnVector xB(6);
     1086    ColumnVector vB(3);
     1087    t_irc irc = eph->getCrd(bncTime(GPSweek, GPSweeks), xB, vB, false);
     1088
     1089    if (irc != success) {
     1090        return irc;
     1091    }
     1092
     1093    // Precise Position
     1094    // ----------------
     1095    ColumnVector xP = _CoM ? rtnCoM : rtnAPC;
     1096
     1097    if (xP.size() == 0) {
     1098        return failure;
     1099    }
     1100
     1101    double dc = 0.0;
     1102    if (_crdTrafoStr != "IGS20") {
     1103        crdTrafo14(GPSweek, xP, dc); // ITRF2020 => ITRF2014
     1104        crdTrafo(GPSweek, xP, dc);   // ITRF2014 to other reference frames
     1105    }
     1106
     1107    // Difference in xyz
     1108    // -----------------
     1109    ColumnVector dx = xB.Rows(1, 3) - xP;
     1110    ColumnVector dv = vB - rtnVel;
     1111
     1112    // Difference in RSW
     1113    // -----------------
     1114    ColumnVector rsw(3);
     1115    XYZ_to_RSW(xB.Rows(1, 3), vB, dx, rsw);
     1116
     1117    ColumnVector dotRsw(3);
     1118    XYZ_to_RSW(xB.Rows(1, 3), vB, dv, dotRsw);
     1119
     1120    // Clock Correction
     1121    // ----------------
     1122    double dClkA0 = rtnClk(1) - (xB(4) - dc) * t_CST::c;
     1123    double dClkA1 = 0.0;
     1124    if (rtnClk(2)) {
     1125        dClkA1 = rtnClk(2) - xB(5) * t_CST::c;
     1126    }
     1127    double dClkA2 = 0.0;
     1128    if (rtnClk(3)) {
     1129        dClkA2 = rtnClk(3) - xB(6) * t_CST::c;
     1130    }
     1131
     1132    if (sd) {
     1133        sd->ID = prn.mid(1).toInt();
     1134        sd->IOD = eph->IOD();
     1135        sd->Clock.DeltaA0 = dClkA0;
     1136        sd->Clock.DeltaA1 = dClkA1;
     1137        sd->Clock.DeltaA2 = dClkA2;
     1138        sd->UserRangeAccuracy = rtnUra;
     1139        sd->Orbit.DeltaRadial = rsw(1);
     1140        sd->Orbit.DeltaAlongTrack = rsw(2);
     1141        sd->Orbit.DeltaCrossTrack = rsw(3);
     1142        sd->Orbit.DotDeltaRadial = dotRsw(1);
     1143        sd->Orbit.DotDeltaAlongTrack = dotRsw(2);
     1144        sd->Orbit.DotDeltaCrossTrack = dotRsw(3);
     1145
     1146        if (corrIsOutOfRange(sd)) {
     1147            emit(newMessage(QString("bncRtnetUploadCaster: SSR parameter is out of its defined range").toLatin1(), false));
     1148            return failure;
     1149        }
     1150    }
     1151
     1152    outLine = QString().asprintf("%d %.1f %s  %u  %10.3f %8.3f %8.3f  %8.3f %8.3f %8.3f\n", GPSweek,
     1153        GPSweeks, eph->prn().toString().c_str(), eph->IOD(), dClkA0, dClkA1, dClkA2,
     1154        rsw(1), rsw(2), rsw(3));  //fprintf(stderr, "%s\n", outLine.toStdString().c_str());
     1155
     1156    // RTNET full clock for RINEX and SP3 file
     1157    // ---------------------------------------
     1158    double relativity = -2.0 * DotProduct(xP, rtnVel) / t_CST::c;
     1159    double clkRnx = (rtnClk[0] - relativity) / t_CST::c;  // [s]
     1160    double clkRnxRate = rtnClk[1] / t_CST::c;                 // [s/s  = -]
     1161    double clkRnxAcc = rtnClk[2] / t_CST::c;                 // [s/s² = -/s]
     1162
     1163    if (_rnx) {
     1164        double clkRnxSig, clkRnxRateSig, clkRnxAccSig;
     1165        int s = rtnClkSig.size();
     1166        switch (s) {
     1167        case 1:
     1168            clkRnxSig = rtnClkSig[0] / t_CST::c;    // [s]
     1169            clkRnxRateSig = 0.0;                        // [s/s = -]
     1170            clkRnxAccSig = 0.0;                        // [s/s² ) -/s]
     1171            break;
     1172        case 2:
     1173            clkRnxSig = rtnClkSig[0] / t_CST::c;     // [s]
     1174            clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
     1175            clkRnxAccSig = 0.0;                         // [s/s² ) -/s]
     1176            break;
     1177        case 3:
     1178            clkRnxSig = rtnClkSig[0] / t_CST::c;     // [s]
     1179            clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
     1180            clkRnxAccSig = rtnClkSig[2] / t_CST::c;     // [s/s² ) -/s]
     1181            break;
     1182        }
     1183        _rnx->write(GPSweek, GPSweeks, prn, clkRnx, clkRnxRate, clkRnxAcc,
     1184            clkRnxSig, clkRnxRateSig, clkRnxAccSig);
     1185    }
     1186    if (_sp3) {
     1187        _sp3->write(GPSweek, GPSweeks, prn, rtnCoM, clkRnx, rtnVel, clkRnxRate);
     1188    }
     1189    return success;
    11821190}
    11831191
     
    11871195    double& dc) {
    11881196
    1189   // Current epoch minus 2000.0 in years
    1190   // ------------------------------------
    1191   double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
    1192 
    1193   ColumnVector dx(3);
    1194 
    1195   dx(1) = _dx + dt * _dxr;
    1196   dx(2) = _dy + dt * _dyr;
    1197   dx(3) = _dz + dt * _dzr;
    1198 
    1199   static const double arcSec = 180.0 * 3600.0 / M_PI;
    1200 
    1201   double ox = (_ox + dt * _oxr) / arcSec;
    1202   double oy = (_oy + dt * _oyr) / arcSec;
    1203   double oz = (_oz + dt * _ozr) / arcSec;
    1204 
    1205   double sc = 1.0 + _sc * 1e-9 + dt * _scr * 1e-9;
    1206 
    1207   // Specify approximate center of area
    1208   // ----------------------------------
    1209   ColumnVector meanSta(3);
    1210 
    1211   if (_crdTrafoStr == "ETRF2000") {
    1212     meanSta(1) = 3661090.0;
    1213     meanSta(2) = 845230.0;
    1214     meanSta(3) = 5136850.0;
    1215   }
    1216   else if (_crdTrafoStr == "GDA2020") {
    1217     meanSta(1) = -4052050.0;
    1218     meanSta(2) = 4212840.0;
    1219     meanSta(3) = -2545110.0;
    1220   }
    1221   else if (_crdTrafoStr == "SIRGAS2000") {
    1222     meanSta(1) = 3740860.0;
    1223     meanSta(2) = -4964290.0;
    1224     meanSta(3) = -1425420.0;
    1225   }
    1226   else if (_crdTrafoStr == "DREF91") {
    1227     meanSta(1) = 3959579.0;
    1228     meanSta(2) = 721719.0;
    1229     meanSta(3) = 4931539.0;
    1230   }
    1231   else if (_crdTrafoStr == "Custom") {
    1232     meanSta(1) = 0.0;
    1233     meanSta(2) = 0.0;
    1234     meanSta(3) = 0.0;
    1235   }
    1236 
    1237   // Clock correction proportional to topocentric distance to satellites
    1238   // -------------------------------------------------------------------
    1239   double rho = (xyz - meanSta).NormFrobenius();
    1240   dc = rho * (sc - 1.0) / sc / t_CST::c;
    1241 
    1242   Matrix rMat(3, 3);
    1243   rMat(1, 1) = 1.0;
    1244   rMat(1, 2) = -oz;
    1245   rMat(1, 3) = oy;
    1246   rMat(2, 1) = oz;
    1247   rMat(2, 2) = 1.0;
    1248   rMat(2, 3) = -ox;
    1249   rMat(3, 1) = -oy;
    1250   rMat(3, 2) = ox;
    1251   rMat(3, 3) = 1.0;
    1252 
    1253   xyz = sc * rMat * xyz + dx;
     1197    // Current epoch minus 2000.0 in years
     1198    // ------------------------------------
     1199    double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
     1200
     1201    ColumnVector dx(3);
     1202
     1203    dx(1) = _dx + dt * _dxr;
     1204    dx(2) = _dy + dt * _dyr;
     1205    dx(3) = _dz + dt * _dzr;
     1206
     1207    static const double arcSec = 180.0 * 3600.0 / M_PI;
     1208
     1209    double ox = (_ox + dt * _oxr) / arcSec;
     1210    double oy = (_oy + dt * _oyr) / arcSec;
     1211    double oz = (_oz + dt * _ozr) / arcSec;
     1212
     1213    double sc = 1.0 + _sc * 1e-9 + dt * _scr * 1e-9;
     1214
     1215    // Specify approximate center of area
     1216    // ----------------------------------
     1217    ColumnVector meanSta(3);
     1218
     1219    if (_crdTrafoStr == "ETRF2000") {
     1220        meanSta(1) = 3661090.0;
     1221        meanSta(2) = 845230.0;
     1222        meanSta(3) = 5136850.0;
     1223    }
     1224    else if (_crdTrafoStr == "GDA2020") {
     1225        meanSta(1) = -4052050.0;
     1226        meanSta(2) = 4212840.0;
     1227        meanSta(3) = -2545110.0;
     1228    }
     1229    else if (_crdTrafoStr == "SIRGAS2000") {
     1230        meanSta(1) = 3740860.0;
     1231        meanSta(2) = -4964290.0;
     1232        meanSta(3) = -1425420.0;
     1233    }
     1234    else if (_crdTrafoStr == "DREF91") {
     1235        meanSta(1) = 3959579.0;
     1236        meanSta(2) = 721719.0;
     1237        meanSta(3) = 4931539.0;
     1238    }
     1239    else if (_crdTrafoStr == "Custom") {
     1240        meanSta(1) = 0.0;
     1241        meanSta(2) = 0.0;
     1242        meanSta(3) = 0.0;
     1243    }
     1244
     1245    // Clock correction proportional to topocentric distance to satellites
     1246    // -------------------------------------------------------------------
     1247    double rho = (xyz - meanSta).NormFrobenius();
     1248    dc = rho * (sc - 1.0) / sc / t_CST::c;
     1249
     1250    Matrix rMat(3, 3);
     1251    rMat(1, 1) = 1.0;
     1252    rMat(1, 2) = -oz;
     1253    rMat(1, 3) = oy;
     1254    rMat(2, 1) = oz;
     1255    rMat(2, 2) = 1.0;
     1256    rMat(2, 3) = -ox;
     1257    rMat(3, 1) = -oy;
     1258    rMat(3, 2) = ox;
     1259    rMat(3, 3) = 1.0;
     1260
     1261    xyz = sc * rMat * xyz + dx;
    12541262}
    12551263
     
    12591267    double& dc) {
    12601268
    1261   // Current epoch minus 2000.0 in years
    1262   // ------------------------------------
    1263   double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
    1264 
    1265   ColumnVector dx(3);
    1266 
    1267   dx(1) = _dx14 + dt * _dxr14;
    1268   dx(2) = _dy14 + dt * _dyr14;
    1269   dx(3) = _dz14 + dt * _dzr14;
    1270 
    1271   static const double arcSec = 180.0 * 3600.0 / M_PI;
    1272 
    1273   double ox = (_ox14 + dt * _oxr14) / arcSec;
    1274   double oy = (_oy14 + dt * _oyr14) / arcSec;
    1275   double oz = (_oz14 + dt * _ozr14) / arcSec;
    1276 
    1277   double sc = 1.0 + _sc14 * 1e-9 + dt * _scr14 * 1e-9;
    1278 
    1279   // Specify approximate center of area
    1280   // ----------------------------------
    1281   ColumnVector meanSta(3);
    1282   meanSta(1) = 0.0; // TODO
    1283   meanSta(2) = 0.0; // TODO
    1284   meanSta(3) = 0.0; // TODO
    1285 
    1286   // Clock correction proportional to topocentric distance to satellites
    1287   // -------------------------------------------------------------------
    1288   double rho = (xyz - meanSta).NormFrobenius();
    1289   dc = rho * (sc - 1.0) / sc / t_CST::c;
    1290 
    1291   Matrix rMat(3, 3);
    1292   rMat(1, 1) = 1.0;
    1293   rMat(1, 2) = -oz;
    1294   rMat(1, 3) = oy;
    1295   rMat(2, 1) = oz;
    1296   rMat(2, 2) = 1.0;
    1297   rMat(2, 3) = -ox;
    1298   rMat(3, 1) = -oy;
    1299   rMat(3, 2) = ox;
    1300   rMat(3, 3) = 1.0;
    1301 
    1302   xyz = sc * rMat * xyz + dx;
     1269    // Current epoch minus 2000.0 in years
     1270    // ------------------------------------
     1271    double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
     1272
     1273    ColumnVector dx(3);
     1274
     1275    dx(1) = _dx14 + dt * _dxr14;
     1276    dx(2) = _dy14 + dt * _dyr14;
     1277    dx(3) = _dz14 + dt * _dzr14;
     1278
     1279    static const double arcSec = 180.0 * 3600.0 / M_PI;
     1280
     1281    double ox = (_ox14 + dt * _oxr14) / arcSec;
     1282    double oy = (_oy14 + dt * _oyr14) / arcSec;
     1283    double oz = (_oz14 + dt * _ozr14) / arcSec;
     1284
     1285    double sc = 1.0 + _sc14 * 1e-9 + dt * _scr14 * 1e-9;
     1286
     1287    // Specify approximate center of area
     1288    // ----------------------------------
     1289    ColumnVector meanSta(3);
     1290    meanSta(1) = 0.0; // TODO
     1291    meanSta(2) = 0.0; // TODO
     1292    meanSta(3) = 0.0; // TODO
     1293
     1294    // Clock correction proportional to topocentric distance to satellites
     1295    // -------------------------------------------------------------------
     1296    double rho = (xyz - meanSta).NormFrobenius();
     1297    dc = rho * (sc - 1.0) / sc / t_CST::c;
     1298
     1299    Matrix rMat(3, 3);
     1300    rMat(1, 1) = 1.0;
     1301    rMat(1, 2) = -oz;
     1302    rMat(1, 3) = oy;
     1303    rMat(2, 1) = oz;
     1304    rMat(2, 2) = 1.0;
     1305    rMat(2, 3) = -ox;
     1306    rMat(3, 1) = -oy;
     1307    rMat(3, 2) = ox;
     1308    rMat(3, 3) = 1.0;
     1309
     1310    xyz = sc * rMat * xyz + dx;
    13031311}
    13041312
     
    13071315int bncRtnetUploadCaster::determineUpdateInd(double samplingRate) {
    13081316
    1309   if (samplingRate == 10.0) {
    1310     return 3;
    1311   }
    1312   else if (samplingRate == 15.0) {
    1313     return 4;
    1314   }
    1315   else if (samplingRate == 30.0) {
    1316     return 5;
    1317   }
    1318   else if (samplingRate == 60.0) {
    1319     return 6;
    1320   }
    1321   else if (samplingRate == 120.0) {
    1322     return 7;
    1323   }
    1324   else if (samplingRate == 240.0) {
    1325     return 8;
    1326   }
    1327   else if (samplingRate == 300.0) {
    1328     return 9;
    1329   }
    1330   else if (samplingRate == 600.0) {
    1331     return 10;
    1332   }
    1333   else if (samplingRate == 900.0) {
    1334     return 11;
    1335   }
    1336   else if (samplingRate == 1800.0) {
    1337     return 12;
    1338   }
    1339   else if (samplingRate == 3600.0) {
    1340     return 13;
    1341   }
    1342   else if (samplingRate == 7200.0) {
    1343     return 14;
    1344   }
    1345   else if (samplingRate == 10800.0) {
    1346     return 15;
    1347   }
    1348   return 2;  // default
     1317    if (samplingRate == 1.0) {
     1318        return 0;
     1319    }
     1320    else if (samplingRate == 2.0) {
     1321        return 1;
     1322    }
     1323    else if (samplingRate == 5.0) {
     1324        return 2;
     1325    }
     1326    else if (samplingRate == 10.0) {
     1327        return 3;
     1328    }
     1329    else if (samplingRate == 15.0) {
     1330        return 4;
     1331    }
     1332    else if (samplingRate == 30.0) {
     1333        return 5;
     1334    }
     1335    else if (samplingRate == 60.0) {
     1336        return 6;
     1337    }
     1338    else if (samplingRate == 120.0) {
     1339        return 7;
     1340    }
     1341    else if (samplingRate == 240.0) {
     1342        return 8;
     1343    }
     1344    else if (samplingRate == 300.0) {
     1345        return 9;
     1346    }
     1347    else if (samplingRate == 600.0) {
     1348        return 10;
     1349    }
     1350    else if (samplingRate == 900.0) {
     1351        return 11;
     1352    }
     1353    else if (samplingRate == 1800.0) {
     1354        return 12;
     1355    }
     1356    else if (samplingRate == 3600.0) {
     1357        return 13;
     1358    }
     1359    else if (samplingRate == 7200.0) {
     1360        return 14;
     1361    }
     1362    else if (samplingRate == 10800.0) {
     1363        return 15;
     1364    }
     1365    return 2;  // default
    13491366}
    13501367
     
    13531370bool bncRtnetUploadCaster::corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd) {
    13541371
    1355   if (fabs(sd->Clock.DeltaA0) > 209.7151)   {return true;}
    1356   if (fabs(sd->Clock.DeltaA1) > 1.048575)   {return true;}
    1357   if (fabs(sd->Clock.DeltaA2) > 1.34217726) {return true;}
    1358 
    1359   if (fabs(sd->Orbit.DeltaRadial)     > 209.7151) {return true;}
    1360   if (fabs(sd->Orbit.DeltaAlongTrack) > 209.7148) {return true;}
    1361   if (fabs(sd->Orbit.DeltaCrossTrack) > 209.7148) {return true;}
    1362 
    1363   if (fabs(sd->Orbit.DotDeltaRadial)     > 1.048575) {return true;}
    1364   if (fabs(sd->Orbit.DotDeltaAlongTrack) > 1.048572) {return true;}
    1365   if (fabs(sd->Orbit.DotDeltaCrossTrack) > 1.048572) {return true;}
    1366   return false;
     1372    if (fabs(sd->Clock.DeltaA0) > 209.7151) { return true; }
     1373    if (fabs(sd->Clock.DeltaA1) > 1.048575) { return true; }
     1374    if (fabs(sd->Clock.DeltaA2) > 1.34217726) { return true; }
     1375
     1376    if (fabs(sd->Orbit.DeltaRadial) > 209.7151) { return true; }
     1377    if (fabs(sd->Orbit.DeltaAlongTrack) > 209.7148) { return true; }
     1378    if (fabs(sd->Orbit.DeltaCrossTrack) > 209.7148) { return true; }
     1379
     1380    if (fabs(sd->Orbit.DotDeltaRadial) > 1.048575) { return true; }
     1381    if (fabs(sd->Orbit.DotDeltaAlongTrack) > 1.048572) { return true; }
     1382    if (fabs(sd->Orbit.DotDeltaCrossTrack) > 1.048572) { return true; }
     1383    return false;
    13671384}
  • trunk/BNC/src/upload/bncrtnetuploadcaster.h

    r10543 r10657  
    1919
    2020class bncRtnetUploadCaster : public bncUploadCaster {
    21  Q_OBJECT
    22  public:
    23   bncRtnetUploadCaster(const QString& mountpoint,
    24                   const QString& outHost, int outPort,
    25                   const QString& ntripVersion, const QString& userName,
    26                   const QString& password,
    27                   const QString& crdTrafo, const QString& ssrFormat,
    28                   bool  CoM,
    29                   const QString& sp3FileName,
    30                   const QString& rnxFileName,
    31                   const QString& bsxFileName,
    32                   int PID, int SID, int IOD, int iRow);
    33   void decodeRtnetStream(char* buffer, int bufLen);
    34  protected:
    35   virtual ~bncRtnetUploadCaster();
    36  private:
    37   t_irc processSatellite(const t_eph* eph, int GPSweek,
    38                         double GPSweeks, const QString& prn,
    39                         const ColumnVector& rtnAPC,
    40                         double ura,
    41                         const ColumnVector& rtnClk,
    42                         const ColumnVector& rtnVel,
    43                         const ColumnVector& rtnCoM,
    44                         const ColumnVector& rtnClkSig,
    45                         struct SsrCorr::ClockOrbit::SatData* sd,
    46                         QString& outLine);
    47   void decodeRtnetEpoch(QStringList epochLines);
    48   bool corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd);
     21    Q_OBJECT
     22public:
     23    bncRtnetUploadCaster(const QString& mountpoint,
     24        const QString& outHost, int outPort,
     25        const QString& ntripVersion, const QString& userName,
     26        const QString& password,
     27        const QString& crdTrafo, const QString& ssrFormat,
     28        bool  CoM,
     29        const QString& sp3FileName,
     30        const QString& rnxFileName,
     31        const QString& bsxFileName,
     32        int PID, int SID, int IOD, int iRow);
     33    void decodeRtnetStream(char* buffer, int bufLen);
     34protected:
     35    virtual ~bncRtnetUploadCaster();
     36private:
     37    t_irc processSatellite(const t_eph* eph, int GPSweek,
     38        double GPSweeks, const QString& prn,
     39        const ColumnVector& rtnAPC,
     40        double ura,
     41        const ColumnVector& rtnClk,
     42        const ColumnVector& rtnVel,
     43        const ColumnVector& rtnCoM,
     44        const ColumnVector& rtnClkSig,
     45        struct SsrCorr::ClockOrbit::SatData* sd,
     46        QString& outLine);
     47    bool corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd);
    4948
    50   void crdTrafo(int GPSWeek, ColumnVector& xyz, double& dc);
    51   // TODO: the following line can be deleted if all parameters are updated regarding ITRF2020
    52   void crdTrafo14(int GPSWeek, ColumnVector& xyz, double& dc);
     49    void crdTrafo(int GPSWeek, ColumnVector& xyz, double& dc);
     50    // TODO: the following line can be deleted if all parameters are updated regarding ITRF2020
     51    void crdTrafo14(int GPSWeek, ColumnVector& xyz, double& dc);
    5352
    54   int determineUpdateInd(double samplingRate);
     53    int determineUpdateInd(double samplingRate);
    5554
    56   QString        _casterID;
    57   bncEphUser*    _ephUser;
    58   QString        _rtnetStreamBuffer;
    59   QString        _crdTrafoStr;
    60   SsrCorr*      _ssrCorr;
    61   QString        _ssrFormat;
    62   bool           _CoM;
    63   bool           _phaseBiasInformationDecoded;
    64   int            _PID;
    65   int            _SID;
    66   int            _IOD;
    67   int            _samplRtcmClkCorr;
    68   double         _samplRtcmEphCorr;
    69   double         _samplRtcmVtec;
    70   double         _samplRtcmCrs;
    71   double         _dx;
    72   double         _dy;
    73   double         _dz;
    74   double         _dxr;
    75   double         _dyr;
    76   double         _dzr;
    77   double         _ox;
    78   double         _oy;
    79   double         _oz;
    80   double         _oxr;
    81   double         _oyr;
    82   double         _ozr;
    83   double         _sc;
    84   double         _scr;
    85   double         _t0;
    86   /* TODO: the following lines can be deleted if all parameters are updated regarding ITRF2020*/
    87   double         _dx14;
    88   double         _dy14;
    89   double         _dz14;
    90   double         _dxr14;
    91   double         _dyr14;
    92   double         _dzr14;
    93   double         _ox14;
    94   double         _oy14;
    95   double         _oz14;
    96   double         _oxr14;
    97   double         _oyr14;
    98   double         _ozr14;
    99   double         _sc14;
    100   double         _scr14;
    101   double         _t014;
     55    QString        _casterID;
     56    bncEphUser* _ephUser;
     57    QString        _rtnetStreamBuffer;
     58    QString        _crdTrafoStr;
     59    SsrCorr* _ssrCorr;
     60    QString        _ssrFormat;
     61    bool           _CoM;
     62    bool           _phaseBiasInformationDecoded;
     63    int            _PID;
     64    int            _SID;
     65    int            _IOD;
     66    double         _samplRtcmClkCorr;
     67    double         _samplRtcmEphCorr;
     68    double         _samplRtcmVtec;
     69    double         _samplRtcmCrs;
     70    double         _dx;
     71    double         _dy;
     72    double         _dz;
     73    double         _dxr;
     74    double         _dyr;
     75    double         _dzr;
     76    double         _ox;
     77    double         _oy;
     78    double         _oz;
     79    double         _oxr;
     80    double         _oyr;
     81    double         _ozr;
     82    double         _sc;
     83    double         _scr;
     84    double         _t0;
     85    /* TODO: the following lines can be deleted if all parameters are updated regarding ITRF2020*/
     86    double         _dx14;
     87    double         _dy14;
     88    double         _dz14;
     89    double         _dxr14;
     90    double         _dyr14;
     91    double         _dzr14;
     92    double         _ox14;
     93    double         _oy14;
     94    double         _oz14;
     95    double         _oxr14;
     96    double         _oyr14;
     97    double         _ozr14;
     98    double         _sc14;
     99    double         _scr14;
     100    double         _t014;
    102101
    103   bncClockRinex* _rnx;
    104   bncSP3*        _sp3;
    105   bncBiasSinex*  _bsx;
    106   QMap<QString, const t_eph*>* _usedEph;
     102    bncClockRinex* _rnx;
     103    bncSP3* _sp3;
     104    bncBiasSinex* _bsx;
     105    QMap<QString, const t_eph*>* _usedEph;
    107106};
    108107
    109108struct phaseBiasesSat {
    110   phaseBiasesSat() {
    111     yawAngle = 0.0;
    112     yawRate = 0.0;
    113   }
    114   double yawAngle;
    115   double yawRate;
     109    phaseBiasesSat() {
     110        yawAngle = 0.0;
     111        yawRate = 0.0;
     112    }
     113    double yawAngle;
     114    double yawRate;
    116115};
    117116
    118117struct phaseBiasSignal {
    119   phaseBiasSignal() {
    120     bias      = 0.0;
    121     integerIndicator    = 0;
    122     wlIndicator          = 0;
    123     discontinuityCounter = 0;
    124   }
    125   QString type;
    126   double bias;
    127   unsigned int integerIndicator;
    128   unsigned int wlIndicator;
    129   unsigned int discontinuityCounter;
     118    phaseBiasSignal() {
     119        bias = 0.0;
     120        integerIndicator = 0;
     121        wlIndicator = 0;
     122        discontinuityCounter = 0;
     123    }
     124    QString type;
     125    double bias;
     126    unsigned int integerIndicator;
     127    unsigned int wlIndicator;
     128    unsigned int discontinuityCounter;
    130129};
    131130
Note: See TracChangeset for help on using the changeset viewer.