source: ntrip/branches/BNC_2.12/src/reqcdlg.cpp@ 7985

Last change on this file since 7985 was 7983, checked in by stuerze, 8 years ago

Frequency specific signal priorities are added for RINEX3 to RINEX2 conversion and the default 'Signal priority' list is improved

File size: 21.0 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: reqcDlg
30 *
31 * Purpose: Displays the teqc-like editing options
32 *
33 * Author: L. Mervart
34 *
35 * Created: 28-Mar-2012
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42
43#include "reqcdlg.h"
44#include "bncsettings.h"
45
46using namespace std;
47
48
49// Constructor
50////////////////////////////////////////////////////////////////////////////
51reqcDlg::reqcDlg(QWidget* parent) : QDialog(parent) {
52
53 setWindowTitle(tr("RINEX Editing Options"));
54
55 int ww = QFontMetrics(font()).width('w');
56
57 const QString timeFmtString = "yyyy-MM-dd hh:mm:ss";
58
59 _reqcRnxVersion = new QComboBox(this);
60 _reqcSampling = new QSpinBox(this);
61 _reqcStartDateTime = new QDateTimeEdit(this);
62 _reqcStartDateTime->setDisplayFormat(timeFmtString);
63 _reqcEndDateTime = new QDateTimeEdit(this);
64 _reqcEndDateTime->setDisplayFormat(timeFmtString);
65 _reqcRunBy = new QLineEdit(this);
66 _reqcUseObsTypes = new QLineEdit(this);
67 _reqcComment = new QLineEdit(this);
68 _reqcOldMarkerName = new QLineEdit(this);
69 _reqcNewMarkerName = new QLineEdit(this);
70 _reqcOldAntennaName = new QLineEdit(this);
71 _reqcNewAntennaName = new QLineEdit(this);
72 _reqcOldAntennaNumber = new QLineEdit(this);
73 _reqcNewAntennaNumber = new QLineEdit(this);
74 _reqcOldAntennadN = new QLineEdit(this);
75 _reqcNewAntennadN = new QLineEdit(this);
76 _reqcOldAntennadE = new QLineEdit(this);
77 _reqcNewAntennadE = new QLineEdit(this);
78 _reqcOldAntennadU = new QLineEdit(this);
79 _reqcNewAntennadU = new QLineEdit(this);
80 _reqcOldReceiverName = new QLineEdit(this);
81 _reqcNewReceiverName = new QLineEdit(this);
82 _reqcOldReceiverNumber = new QLineEdit(this);
83 _reqcNewReceiverNumber = new QLineEdit(this);
84
85
86 _reqcRnxVersion->setEditable(false);
87 _reqcRnxVersion->addItems(QString("2,3").split(","));
88 _reqcRnxVersion->setMaximumWidth(7*ww);
89
90 _reqcSampling->setMinimum(0);
91 _reqcSampling->setMaximum(60);
92 _reqcSampling->setSingleStep(5);
93 _reqcSampling->setSuffix(" sec");
94 _reqcSampling->setMaximumWidth(7*ww);
95
96 // Read Options
97 // ------------
98 bncSettings settings;
99
100 int kk = _reqcRnxVersion->findText(settings.value("reqcRnxVersion").toString());
101 if (kk != -1) {
102 _reqcRnxVersion->setCurrentIndex(kk);
103 }
104 _reqcSampling->setValue(settings.value("reqcSampling").toInt());
105 if (settings.value("reqcStartDateTime").toString().isEmpty()) {
106 _reqcStartDateTime->setDateTime(QDateTime::fromString("1967-11-02T00:00:00", Qt::ISODate));
107 }
108 else {
109 _reqcStartDateTime->setDateTime(settings.value("reqcStartDateTime").toDateTime());
110 }
111 if (settings.value("reqcEndDateTime").toString().isEmpty()) {
112 _reqcEndDateTime->setDateTime(QDateTime::fromString("2099-01-01T00:00:00", Qt::ISODate));
113 }
114 else {
115 _reqcEndDateTime->setDateTime(settings.value("reqcEndDateTime").toDateTime());
116 }
117 _reqcRunBy->setText(settings.value("reqcRunBy").toString());
118 _reqcUseObsTypes->setText(settings.value("reqcUseObsTypes").toString());
119 _reqcComment->setText(settings.value("reqcComment").toString());
120 _reqcOldMarkerName->setText(settings.value("reqcOldMarkerName").toString());
121 _reqcNewMarkerName->setText(settings.value("reqcNewMarkerName").toString());
122 _reqcOldAntennaName->setText(settings.value("reqcOldAntennaName").toString());
123 _reqcNewAntennaName->setText(settings.value("reqcNewAntennaName").toString());
124 _reqcOldAntennaNumber->setText(settings.value("reqcOldAntennaNumber").toString());
125 _reqcNewAntennaNumber->setText(settings.value("reqcNewAntennaNumber").toString());
126 _reqcOldAntennadN->setText(settings.value("reqcOldAntennadN").toString());
127 _reqcNewAntennadN->setText(settings.value("reqcNewAntennadN").toString());
128 _reqcOldAntennadE->setText(settings.value("reqcOldAntennadE").toString());
129 _reqcNewAntennadE->setText(settings.value("reqcNewAntennadE").toString());
130 _reqcOldAntennadU->setText(settings.value("reqcOldAntennadU").toString());
131 _reqcNewAntennadU->setText(settings.value("reqcNewAntennadU").toString());
132 _reqcOldReceiverName->setText(settings.value("reqcOldReceiverName").toString());
133 _reqcNewReceiverName->setText(settings.value("reqcNewReceiverName").toString());
134 _reqcOldReceiverNumber->setText(settings.value("reqcOldReceiverNumber").toString());
135 _reqcNewReceiverNumber->setText(settings.value("reqcNewReceiverNumber").toString());
136
137
138 QString hlp = settings.value("reqcV2Priority").toString();
139 if (hlp.isEmpty()) {
140 hlp = "G:12&PWCSLXYN G:5&IQX R:12&PC R:3&IQX E:16&BCX E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:IQX I:ABCX S:1&C S:5&IQX";
141 }
142 _reqcV2Priority = new QLineEdit(hlp);
143
144 // Dialog Layout
145 // -------------
146 QGridLayout* grid = new QGridLayout;
147
148 int ir = 0;
149 grid->addWidget(new QLabel("RINEX Version"), ir, 1);
150 grid->addWidget(_reqcRnxVersion, ir, 2);
151 grid->addWidget(new QLabel("Sampling"), ir, 3, Qt::AlignRight);
152 grid->addWidget(_reqcSampling, ir, 4);
153 ++ir;
154 grid->addWidget(new QLabel("Version 2 signal priority"), ir, 1);
155 grid->addWidget(_reqcV2Priority, ir, 2, 1, 4);
156 ++ir;
157 grid->addWidget(new QLabel("Start"), ir, 1);
158 grid->addWidget(_reqcStartDateTime, ir, 2);
159 grid->addWidget(new QLabel("End"), ir, 3, Qt::AlignRight);
160 grid->addWidget(_reqcEndDateTime, ir, 4);
161 ++ir;
162 grid->addWidget(new QLabel("Run By"), ir, 0);
163 grid->addWidget(_reqcRunBy, ir, 1);
164 ++ir;
165 grid->addWidget(new QLabel("Use Obs. Types"), ir, 0);
166 grid->addWidget(_reqcUseObsTypes, ir, 1, 1, 4);
167 ++ir;
168 grid->addWidget(new QLabel("Comment(s)"), ir, 0);
169 grid->addWidget(_reqcComment, ir, 1, 1, 4);
170 ++ir;
171 grid->addWidget(new QLabel("Old"), ir, 1, 1, 2, Qt::AlignCenter);
172 grid->addWidget(new QLabel("New"), ir, 3, 1, 2, Qt::AlignCenter);
173 ++ir;
174 grid->addWidget(new QLabel("Marker Name"), ir, 0);
175 grid->addWidget(_reqcOldMarkerName, ir, 1, 1, 2);
176 grid->addWidget(_reqcNewMarkerName, ir, 3, 1, 2);
177 ++ir;
178 grid->addWidget(new QLabel("Antenna Name"), ir, 0);
179 grid->addWidget(_reqcOldAntennaName, ir, 1, 1, 2);
180 grid->addWidget(_reqcNewAntennaName, ir, 3, 1, 2);
181 ++ir;
182 grid->addWidget(new QLabel("Antenna Number"), ir, 0);
183 grid->addWidget(_reqcOldAntennaNumber, ir, 1, 1, 2);
184 grid->addWidget(_reqcNewAntennaNumber, ir, 3, 1, 2);
185 ++ir;
186 grid->addWidget(new QLabel("Antenna ecc. dN"), ir, 0);
187 grid->addWidget(_reqcOldAntennadN, ir, 1, 1, 2);
188 grid->addWidget(_reqcNewAntennadN, ir, 3, 1, 2);
189 ++ir;
190 grid->addWidget(new QLabel("Antenna ecc. dE"), ir, 0);
191 grid->addWidget(_reqcOldAntennadE, ir, 1, 1, 2);
192 grid->addWidget(_reqcNewAntennadE, ir, 3, 1, 2);
193 ++ir;
194 grid->addWidget(new QLabel("Antenna ecc. dU"), ir, 0);
195 grid->addWidget(_reqcOldAntennadU, ir, 1, 1, 2);
196 grid->addWidget(_reqcNewAntennadU, ir, 3, 1, 2);
197 ++ir;
198 grid->addWidget(new QLabel("Receiver Name"), ir, 0);
199 grid->addWidget(_reqcOldReceiverName, ir, 1, 1, 2);
200 grid->addWidget(_reqcNewReceiverName, ir, 3, 1, 2);
201 ++ir;
202 grid->addWidget(new QLabel("Receiver Number"), ir, 0);
203 grid->addWidget(_reqcOldReceiverNumber, ir, 1, 1, 2);
204 grid->addWidget(_reqcNewReceiverNumber, ir, 3, 1, 2);
205
206
207 slotReqcTextChanged();
208 connect(_reqcRnxVersion, SIGNAL(currentIndexChanged(const QString &)),
209 this, SLOT(slotReqcTextChanged()));
210
211 _buttonWhatsThis = new QPushButton(tr("Help=Shift+F1"), this);
212 connect(_buttonWhatsThis, SIGNAL(clicked()), this, SLOT(slotWhatsThis()));
213
214 _buttonOK = new QPushButton(tr("OK / Save"), this);
215 connect(_buttonOK, SIGNAL(clicked()), this, SLOT(slotOK()));
216
217 _buttonCancel = new QPushButton(tr("Cancel"), this);
218 connect(_buttonCancel, SIGNAL(clicked()), this, SLOT(close()));
219
220 QHBoxLayout* buttonLayout = new QHBoxLayout;
221 buttonLayout->addWidget(_buttonWhatsThis);
222 buttonLayout->addStretch(1);
223 buttonLayout->addWidget(_buttonOK);
224 buttonLayout->addWidget(_buttonCancel);
225
226 QVBoxLayout* mainLayout = new QVBoxLayout(this);
227 mainLayout->addLayout(grid);
228 mainLayout->addLayout(buttonLayout);
229
230 // WhatsThis, RINEX Editing & QC
231 // -----------------------------
232 _reqcRnxVersion->setWhatsThis(tr("<p>Select version number of emerging new RINEX file.</p><p>Note the following:</p><p>When converting <u>RINEX Version 2 to Version 3 </u>Observation files, the tracking mode or channel information (signal attribute, see RINEX Version 3 documentation) in the (last out of the three characters) observation code is left blank if unknown.</p><p>When converting <u>RINEX Version 3 to Version 2</u>, the mapping of observations follows a 'Signal priority list' with signal attributes as defined in RINEX Version 3.</p>"));
233 _reqcSampling->setWhatsThis(tr("<p>Select sampling rate of emerging new RINEX Observation file.</p><p>'0 sec' means that observations from all epochs in the RINEX input file will become part of the RINEX output file.</p>"));
234 _reqcV2Priority->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>'C:IQX I:ABCX' (System specific signal priorities for BDS and IRNSS) </li><li>'G:12&PWCSLXYN 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&PWCSLXYN G:5&IQX R:12&PC R:3&IQX E:16&BCX E:578&IQX J:1&SLXCZ J:26&SLX J:5&IQX C:IQX I:ABCX S:1&C S:5&IQX'.</p>"));
235 _reqcStartDateTime->setWhatsThis(tr("<p>Specify begin of emerging new RINEX Observation file.</p>"));
236 _reqcEndDateTime->setWhatsThis(tr("<p>Specify end of emerging new RINEX Observation file.</p>"));
237 _reqcRunBy->setWhatsThis(tr("<p>Specify a 'RUN BY' string to be included in the emerging new RINEX file header.</p><p>Default is an empty option field, meaning the operator's user ID is used as 'RUN BY' string.</p>"));
238 _reqcComment->setWhatsThis(tr("<p>Specifying a comment line text to be added to the emerging new RINEX file header is an option. Any introduction of newline specification '\\n' in this enforces the beginning of a further comment line. Comment line(s) will be added to the header after the 'PGM / RUN BY / DATE' record.</p><p>Default is an empty option field meaning that no additional comment line is added to the RINEX header.</p>"));
239 _reqcUseObsTypes->setWhatsThis(tr("<p>This option lets you limit the RINEX output to specific observation types. Examples:</p><p><ul><li>G:C1C G:L1C R:C1C R:C1P S:C1C C:C1I C:L1I E:C1X E:L1X<br>(Valid for output of RINEX Version 3; output contains GPS C1C and L1C, GLONASS C1C and C1P, SBAS C1C, BeiDou C1C, C1I andL1I, Galileo C1X and L1X.)</li><li>C1 L2 L5<br>(Valid for output of RINEX Version 2 with mapping of Version 3 signals to Version 2 according to 'Version 2 Signal Priority'; output contains C1, L2 and L5 observations from any GNSS system.)</li></ul></p><p>Default is an empty option field, meaning that the RINEX output file contains all observations made available through RINEX input file.</p>"));
240 _reqcOldMarkerName->setWhatsThis(tr("<p>Enter old Marker Name in RINEX Observation file.</p><p>Default is an empty option field.</p>"));
241 _reqcNewMarkerName->setWhatsThis(tr("<p>Enter new Marker Name in RINEX Observation file.</p><p>If option 'Old Marker Name' is either left blank or its content is specified as given in the RINEX input file, then the marker name in the RINEX output file will be specified by 'New Marker Name'</p><p>Default is an empty option field, meaning that the content of the Marker Name data field in the RINEX file will not be changed.</p>"));
242 _reqcOldAntennaName->setWhatsThis(tr("<p>Enter old Antenna Name in RINEX Observation file.</p><p>Default is an empty option field.</p>"));
243 _reqcNewAntennaName->setWhatsThis(tr("<p>Enter new Antenna Name in RINEX Observation file.</p><p>If option 'Old Antenna Name' is either left blank or its content is specified as given in the RINEX input file, then the antenna name in the RINEX output file will be specified by 'New Antenna Name'</p><p>Default is an empty option field, meaning that the content of the Antenna Name data field in the RINEX file will not be changed.</p>"));
244 _reqcOldAntennaNumber->setWhatsThis(tr("<p>Enter old Antenna Number in RINEX Observation file.</p><p>Default is an empty option field.</p>"));
245 _reqcNewAntennaNumber->setWhatsThis(tr("<p>Enter new Antenna Number in RINEX Observation file.</p><p>If option 'Old Antenna Number' is either left blank or its content is specified as given in the RINEX input file, then the antenna number in the RINEX output file will be specified by 'New Antenna Number'</p><p>Default is an empty option field, meaning that the content of the Antenna Number data field in the RINEX file will not be changed.</p>"));
246 _reqcOldAntennadN->setWhatsThis(tr("<p>Enter old North Antenna Eccentricity in RINEX Observation file.</p><p>Default is an empty option field.</p>"));
247 _reqcNewAntennadN->setWhatsThis(tr("<p>Enter new North Antenna Eccentricity in RINEX Observation file.</p><p>If option 'Old Antenna North Eccentricity' is either left blank or its content is specified as given in the RINEX input file, then the north antenna eccentricity in the RINEX output file will be specified by 'New North Antenna Eccentricity'</p><p>Default is an empty option field, meaning that the content of the North Antenna Eccentricity data field in the RINEX file will not be changed.</p>"));
248 _reqcOldAntennadE->setWhatsThis(tr("<p>Enter old East Antenna Eccentricity in RINEX Observation file.</p><p>Default is an empty option field.</p>"));
249 _reqcNewAntennadE->setWhatsThis(tr("<p>Enter new East Antenna Eccentricity in RINEX Observation file.</p><p>If option 'Old Antenna East Eccentricity' is either left blank or its content is specified as given in the RINEX input file, then the east antenna eccentricity in the RINEX output file will be specified by 'New East Antenna Eccentricity'</p><p>Default is an empty option field, meaning that the content of the East Antenna Eccentricity data field in the RINEX file will not be changed.</p>"));
250 _reqcOldAntennadU->setWhatsThis(tr("<p>Enter old Up Antenna Eccentricity in RINEX Observation file.</p><p>Default is an empty option field.</p>"));
251 _reqcNewAntennadU->setWhatsThis(tr("<p>Enter new Up Antenna Eccentricity in RINEX Observation file.</p><p>If option 'Old Antenna Up Eccentricity' is either left blank or its content is specified as given in the RINEX input file, then the up antenna eccentricity in the RINEX output file will be specified by 'New Up Antenna Eccentricity'</p><p>Default is an empty option field, meaning that the content of the Up Antenna Eccentricity data field in the RINEX file will not be changed.</p>"));
252 _reqcOldReceiverName->setWhatsThis(tr("<p>Enter old Receiver Name in RINEX Observation file.<p>Default is an empty option field.</p></p>"));
253 _reqcNewReceiverName->setWhatsThis(tr("<p>Enter new Receiver Name in RINEX Observation file.</p><p>If option 'Old Receiver Name' is either left blank or its content is specified as given in the RINEX input file, then the receiver name in the RINEX output file will be specified by 'New Receiver Name'</p><p>Default is an empty option field, meaning that the content of the Receiver Name data field in the RINEX file will not be changed.</p>"));
254 _reqcOldReceiverNumber->setWhatsThis(tr("<p>Enter old Receiver Number in RINEX Observation file.<p>Default is an empty option field.</p></p>"));
255 _reqcNewReceiverNumber->setWhatsThis(tr("<p>Enter new Receiver Number in RINEX Observation file.</p><p>If option 'Old Receiver Number' is either left blank or its content is specified as given in the RINEX input file, then the receiver number in the RINEX output file will be specified by 'New Receiver Number'</p><p>Default is an empty option field, meaning that the content of the Receiver Number data field in the RINEX file will not be changed.</p>"));
256}
257
258// Destructor
259////////////////////////////////////////////////////////////////////////////
260reqcDlg::~reqcDlg() {
261 delete _buttonOK;
262 delete _buttonCancel;
263 delete _buttonWhatsThis;
264}
265
266// Accept the Options
267////////////////////////////////////////////////////////////////////////////
268void reqcDlg::slotOK() {
269 saveOptions();
270 done(0);
271}
272
273// Whats This Help
274////////////////////////////////////////////////////////////////////////////
275void reqcDlg::slotWhatsThis() {
276 QWhatsThis::enterWhatsThisMode();
277}
278
279// Close Dialog gracefully
280////////////////////////////////////////////////////////////////////////////
281void reqcDlg::closeEvent(QCloseEvent* event) {
282
283 int iRet = QMessageBox::question(this, "Close", "Save Options?",
284 QMessageBox::Yes, QMessageBox::No,
285 QMessageBox::Cancel);
286
287 if (iRet == QMessageBox::Cancel) {
288 event->ignore();
289 return;
290 }
291 else if (iRet == QMessageBox::Yes) {
292 saveOptions();
293 }
294
295 QDialog::closeEvent(event);
296}
297
298// Save Selected Options
299////////////////////////////////////////////////////////////////////////////
300void reqcDlg::saveOptions() {
301
302 bncSettings settings;
303
304 settings.setValue("reqcRnxVersion" , _reqcRnxVersion->currentText());
305 settings.setValue("reqcSampling" , _reqcSampling->value());
306 settings.setValue("reqcV2Priority" , _reqcV2Priority->text());
307 settings.setValue("reqcStartDateTime" , _reqcStartDateTime->dateTime().toString(Qt::ISODate));
308 settings.setValue("reqcEndDateTime" , _reqcEndDateTime->dateTime().toString(Qt::ISODate));
309 settings.setValue("reqcRunBy" , _reqcRunBy->text());
310 settings.setValue("reqcUseObsTypes" , _reqcUseObsTypes->text());
311 settings.setValue("reqcComment" , _reqcComment->text());
312 settings.setValue("reqcOldMarkerName" , _reqcOldMarkerName->text());
313 settings.setValue("reqcNewMarkerName" , _reqcNewMarkerName->text());
314 settings.setValue("reqcOldAntennaName" , _reqcOldAntennaName->text());
315 settings.setValue("reqcNewAntennaName" , _reqcNewAntennaName->text());
316 settings.setValue("reqcOldAntennaNumber" , _reqcOldAntennaNumber->text());
317 settings.setValue("reqcNewAntennaNumber" , _reqcNewAntennaNumber->text());
318 settings.setValue("reqcOldAntennadN" , _reqcOldAntennadN->text());
319 settings.setValue("reqcNewAntennadN" , _reqcNewAntennadN->text());
320 settings.setValue("reqcOldAntennadE" , _reqcOldAntennadE->text());
321 settings.setValue("reqcNewAntennadE" , _reqcNewAntennadE->text());
322 settings.setValue("reqcOldAntennadU" , _reqcOldAntennadU->text());
323 settings.setValue("reqcNewAntennadU" , _reqcNewAntennadU->text());
324 settings.setValue("reqcNewAntennaNumber" , _reqcNewAntennaNumber->text());
325 settings.setValue("reqcOldReceiverName" , _reqcOldReceiverName->text());
326 settings.setValue("reqcNewReceiverName" , _reqcNewReceiverName->text());
327 settings.setValue("reqcOldReceiverNumber", _reqcOldReceiverNumber->text());
328 settings.setValue("reqcNewReceiverNumber", _reqcNewReceiverNumber->text());
329}
330
331// Reqc Text Changed
332////////////////////////////////////////////////////////////////////////////
333void reqcDlg::slotReqcTextChanged(){
334
335 const static QPalette paletteWhite(QColor(255, 255, 255));
336 const static QPalette paletteGray(QColor(230, 230, 230));
337
338 if (sender() == 0 || sender() == _reqcRnxVersion) {
339 if (_reqcRnxVersion->currentText() == "2") {
340 _reqcV2Priority->setPalette(paletteWhite);
341 _reqcV2Priority->setEnabled(true);
342 }
343 else {
344 _reqcV2Priority->setPalette(paletteGray);
345 _reqcV2Priority->setEnabled(false);
346 }
347 }
348}
349
Note: See TracBrowser for help on using the repository browser.