1 /* extcap_argument.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #include <extcap_argument.h>
11 
12 #include <QObject>
13 #include <QWidget>
14 #include <QLabel>
15 #include <QLineEdit>
16 #include <QDateTimeEdit>
17 #include <QIntValidator>
18 #include <QDoubleValidator>
19 #include <QCheckBox>
20 #include <QButtonGroup>
21 #include <QBoxLayout>
22 #include <QRadioButton>
23 #include <QComboBox>
24 #include <QPushButton>
25 #include <QMargins>
26 #include <QVariant>
27 #include <QAbstractItemModel>
28 #include <QStringList>
29 #include <QStandardItem>
30 #include <QStandardItemModel>
31 #include <QItemSelectionModel>
32 #include <QRegExp>
33 
34 #include <glib.h>
35 
36 #include <extcap.h>
37 #include <epan/prefs.h>
38 #include <epan/prefs-int.h>
39 #include <wsutil/wslog.h>
40 #include <ui/qt/utils/color_utils.h>
41 
42 #include <extcap_parser.h>
43 #include <extcap_argument_file.h>
44 #include <extcap_argument_multiselect.h>
45 
46 #include <ui/qt/extcap_options_dialog.h>
47 
ExtArgTimestamp(extcap_arg * argument,QObject * parent)48 ExtArgTimestamp::ExtArgTimestamp(extcap_arg * argument, QObject * parent) :
49     ExtcapArgument(argument, parent) {}
50 
createEditor(QWidget * parent)51 QWidget * ExtArgTimestamp::createEditor(QWidget * parent)
52 {
53     QDateTimeEdit * tsBox;
54     QString text = defaultValue();
55 
56     if (_argument->pref_valptr && *_argument->pref_valptr)
57     {
58         QString storeValue(*_argument->pref_valptr);
59 
60         if (storeValue.length() > 0 && storeValue.compare(text) != 0)
61             text = storeValue.trimmed();
62     }
63 
64 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
65     ts = QDateTime::fromSecsSinceEpoch(text.toInt());
66 #else
67     ts = QDateTime::fromTime_t(text.toInt());
68 #endif
69     tsBox = new QDateTimeEdit(ts, parent);
70     tsBox->setDisplayFormat(QLocale::system().dateTimeFormat());
71     tsBox->setCalendarPopup(true);
72     tsBox->setAutoFillBackground(true);
73 
74     if (_argument->tooltip != NULL)
75         tsBox->setToolTip(QString().fromUtf8(_argument->tooltip));
76 
77     connect(tsBox, SIGNAL(dateTimeChanged(QDateTime)), SLOT(onDateTimeChanged(QDateTime)));
78 
79     return tsBox;
80 }
81 
onDateTimeChanged(QDateTime t)82 void ExtArgTimestamp::onDateTimeChanged(QDateTime t)
83 {
84     ts = t;
85     emit valueChanged();
86 }
87 
defaultValue()88 QString ExtArgTimestamp::defaultValue()
89 {
90 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
91     return QString::number(QDateTime::currentDateTime().toSecsSinceEpoch());
92 #else
93     return QString::number(QDateTime::currentDateTime().toTime_t());
94 #endif
95 }
96 
isValid()97 bool ExtArgTimestamp::isValid()
98 {
99     bool valid = true;
100 
101     if (value().length() == 0 && isRequired())
102         valid = false;
103 
104     return valid;
105 }
106 
value()107 QString ExtArgTimestamp::value()
108 {
109 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
110     return QString::number(ts.toSecsSinceEpoch());
111 #else
112     return QString::number(ts.toTime_t());
113 #endif
114 }
115 
prefValue()116 QString ExtArgTimestamp::prefValue()
117 {
118     return value();
119 }
120 
ExtArgSelector(extcap_arg * argument,QObject * parent)121 ExtArgSelector::ExtArgSelector(extcap_arg * argument, QObject * parent) :
122         ExtcapArgument(argument, parent), boxSelection(0) {}
123 
createEditor(QWidget * parent)124 QWidget * ExtArgSelector::createEditor(QWidget * parent)
125 {
126     int counter = 0;
127     int selected = -1;
128     const char *prefval = _argument->pref_valptr ? *_argument->pref_valptr : NULL;
129     QString stored(prefval ? prefval : "");
130 
131     QWidget * editor = new QWidget(parent);
132     QHBoxLayout * layout = new QHBoxLayout();
133     QMargins margins = layout->contentsMargins();
134     layout->setContentsMargins(0, margins.top(), 0, margins.bottom());
135 
136     boxSelection = new QComboBox(parent);
137     layout->addWidget(boxSelection);
138 
139     if (values.length() > 0)
140     {
141         ExtcapValueList::const_iterator iter = values.constBegin();
142 
143         while (iter != values.constEnd())
144         {
145             boxSelection->addItem((*iter).value(), (*iter).call());
146 
147             if (!prefval && (*iter).isDefault())
148                 selected = counter;
149             else if (prefval && stored.compare((*iter).call()) == 0)
150                 selected = counter;
151 
152             counter++;
153             ++iter;
154         }
155 
156         if (selected > -1 && selected < boxSelection->count())
157             boxSelection->setCurrentIndex(selected);
158     }
159 
160     if (reload())
161     {
162         QString btnText(tr("Reload data"));
163         if (_argument->placeholder)
164             btnText = QString(_argument->placeholder);
165 
166         QPushButton * reloadButton = new QPushButton(btnText, editor);
167         layout->addWidget(reloadButton);
168         reloadButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
169         boxSelection->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
170 
171         connect(reloadButton, SIGNAL(clicked()), this, SLOT(onReloadTriggered()));
172     }
173 
174     connect (boxSelection, SIGNAL(currentIndexChanged(int)), SLOT(onIntChanged(int)));
175 
176     editor->setLayout(layout);
177 
178     return editor;
179 }
180 
onReloadTriggered()181 void ExtArgSelector::onReloadTriggered()
182 {
183     int counter = 0;
184     int selected = -1;
185 
186     QString call = boxSelection->currentData().toString();
187     const char *prefval = _argument->pref_valptr ? *_argument->pref_valptr : NULL;
188     QString stored(prefval ? prefval : "");
189     if (call != stored)
190         stored = call;
191 
192     if (reloadValues() && values.length() > 0)
193     {
194         boxSelection->clear();
195 
196         ExtcapValueList::const_iterator iter = values.constBegin();
197 
198         while (iter != values.constEnd())
199         {
200             boxSelection->addItem((*iter).value(), (*iter).call());
201 
202             if (stored.compare((*iter).call()) == 0)
203                 selected = counter;
204             else if ((*iter).isDefault() && selected == -1)
205                 selected = counter;
206 
207             counter++;
208             ++iter;
209         }
210 
211         if (selected > -1 && selected < boxSelection->count())
212             boxSelection->setCurrentIndex(selected);
213     }
214 }
215 
isValid()216 bool ExtArgSelector::isValid()
217 {
218     bool valid = true;
219 
220     if (value().length() == 0 && isRequired())
221         valid = false;
222 
223     if (boxSelection)
224     {
225         QString lblInvalidColor = ColorUtils::fromColorT(prefs.gui_text_invalid).name();
226         QString cmbBoxStyle("QComboBox { background-color: %1; } ");
227         boxSelection->setStyleSheet(cmbBoxStyle.arg(valid ? QString("") : lblInvalidColor));
228     }
229 
230     return valid;
231 }
232 
value()233 QString ExtArgSelector::value()
234 {
235     if (boxSelection == 0)
236         return QString();
237 
238     QVariant data = boxSelection->currentData();
239 
240     return data.toString();
241 }
242 
ExtArgRadio(extcap_arg * argument,QObject * parent)243 ExtArgRadio::ExtArgRadio(extcap_arg * argument, QObject * parent) :
244         ExtcapArgument(argument, parent), selectorGroup(0), callStrings(0) {}
245 
createEditor(QWidget * parent)246 QWidget * ExtArgRadio::createEditor(QWidget * parent)
247 {
248 
249     int count = 0;
250     bool anyChecked = false;
251 
252     selectorGroup = new QButtonGroup(parent);
253     QWidget * radioButtons = new QWidget;
254     QVBoxLayout * vrLayout = new QVBoxLayout();
255     QMargins margins = vrLayout->contentsMargins();
256     vrLayout->setContentsMargins(0, 0, 0, margins.bottom());
257     if (callStrings != 0)
258         delete callStrings;
259 
260     callStrings = new QList<QString>();
261 
262     if (values.length() > 0  )
263     {
264         ExtcapValueList::const_iterator iter = values.constBegin();
265 
266         while (iter != values.constEnd())
267         {
268             QRadioButton * radio = new QRadioButton((*iter).value());
269             QString callString = (*iter).call();
270             callStrings->append(callString);
271 
272             if ((*iter).isDefault())
273             {
274                 radio->setChecked(true);
275                 anyChecked = true;
276             }
277 
278             connect(radio, SIGNAL(clicked(bool)), SLOT(onBoolChanged(bool)));
279             selectorGroup->addButton(radio, count);
280 
281             vrLayout->addWidget(radio);
282             count++;
283 
284             ++iter;
285         }
286     }
287 
288     /* No default was provided, and not saved value exists */
289     if (anyChecked == false && count > 0)
290         ((QRadioButton*)(selectorGroup->button(0)))->setChecked(true);
291 
292     radioButtons->setLayout(vrLayout);
293 
294     return radioButtons;
295 }
296 
value()297 QString ExtArgRadio::value()
298 {
299     int idx = 0;
300     if (selectorGroup == 0 || callStrings == 0)
301         return QString();
302 
303     idx = selectorGroup->checkedId();
304     if (idx > -1 && callStrings->length() > idx)
305         return callStrings->takeAt(idx);
306 
307     return QString();
308 }
309 
isValid()310 bool ExtArgRadio::isValid()
311 {
312     bool valid = true;
313     int idx = 0;
314 
315     if (isRequired())
316     {
317         if (selectorGroup == 0 || callStrings == 0)
318             valid = false;
319         else
320         {
321             idx = selectorGroup->checkedId();
322             if (idx == -1 || callStrings->length() <= idx)
323                 valid = false;
324         }
325     }
326 
327     /* If nothing is selected, but a selection is required, the only thing that
328      * can be marked is the label */
329     QString lblInvalidColor = ColorUtils::fromColorT(prefs.gui_text_invalid).name();
330     _label->setStyleSheet (label_style.arg(valid ? QString("") : lblInvalidColor));
331 
332     return valid;
333 }
334 
ExtArgBool(extcap_arg * argument,QObject * parent)335 ExtArgBool::ExtArgBool(extcap_arg * argument, QObject * parent) :
336         ExtcapArgument(argument, parent), boolBox(0) {}
337 
createLabel(QWidget * parent)338 QWidget * ExtArgBool::createLabel(QWidget * parent)
339 {
340     return new QWidget(parent);
341 }
342 
createEditor(QWidget * parent)343 QWidget * ExtArgBool::createEditor(QWidget * parent)
344 {
345     bool state = defaultBool();
346 
347     boolBox = new QCheckBox(QString().fromUtf8(_argument->display), parent);
348     if (_argument->tooltip != NULL)
349         boolBox->setToolTip(QString().fromUtf8(_argument->tooltip));
350 
351     const char *prefval = _argument->pref_valptr ? *_argument->pref_valptr : NULL;
352     if (prefval)
353     {
354         QRegExp regexp(EXTCAP_BOOLEAN_REGEX);
355 
356         bool savedstate = (regexp.indexIn(QString(prefval[0]), 0) != -1);
357         if (savedstate != state)
358             state = savedstate;
359     }
360 
361     boolBox->setCheckState(state ? Qt::Checked : Qt::Unchecked);
362 
363     connect (boolBox, SIGNAL(stateChanged(int)), SLOT(onIntChanged(int)));
364 
365     return boolBox;
366 }
367 
call()368 QString ExtArgBool::call()
369 {
370     if (boolBox == NULL)
371         return QString("");
372 
373     if (_argument->arg_type == EXTCAP_ARG_BOOLEAN)
374         return ExtcapArgument::call();
375 
376     return QString(boolBox->checkState() == Qt::Checked ? _argument->call : "");
377 }
378 
value()379 QString ExtArgBool::value()
380 {
381     if (boolBox == NULL || _argument->arg_type == EXTCAP_ARG_BOOLFLAG)
382         return QString();
383     return QString(boolBox->checkState() == Qt::Checked ? "true" : "false");
384 }
385 
prefValue()386 QString ExtArgBool::prefValue()
387 {
388     if (boolBox == NULL)
389         return QString("false");
390     return QString(boolBox->checkState() == Qt::Checked ? "true" : "false");
391 }
392 
isValid()393 bool ExtArgBool::isValid()
394 {
395     /* A bool is allways valid, but the base function checks on string length,
396      * which will fail with boolflags */
397     return true;
398 }
399 
defaultBool()400 bool ExtArgBool::defaultBool()
401 {
402     bool result = false;
403 
404     if (_argument)
405     {
406         if (extcap_complex_get_bool(_argument->default_complex) == (gboolean)TRUE)
407             result = true;
408     }
409 
410     return result;
411 }
412 
defaultValue()413 QString ExtArgBool::defaultValue()
414 {
415     return defaultBool() ? QString("true") : QString("false");
416 }
417 
ExtArgText(extcap_arg * argument,QObject * parent)418 ExtArgText::ExtArgText(extcap_arg * argument, QObject * parent) :
419     ExtcapArgument(argument, parent), textBox(0)
420 {
421 }
422 
createEditor(QWidget * parent)423 QWidget * ExtArgText::createEditor(QWidget * parent)
424 {
425     QString text = defaultValue();
426 
427     if (_argument->pref_valptr && *_argument->pref_valptr)
428     {
429         QString storeValue(*_argument->pref_valptr);
430 
431         if (storeValue.length() > 0 && storeValue.compare(text) != 0)
432             text = storeValue.trimmed();
433     }
434 
435     textBox = new QLineEdit(text, parent);
436 
437     if (_argument->tooltip != NULL)
438         textBox->setToolTip(QString().fromUtf8(_argument->tooltip));
439 
440     if (_argument->placeholder != NULL)
441         textBox->setPlaceholderText(QString().fromUtf8(_argument->placeholder));
442 
443     if (_argument->arg_type == EXTCAP_ARG_PASSWORD)
444         textBox->setEchoMode(QLineEdit::Password);
445 
446     connect(textBox , SIGNAL(textChanged(QString)), SLOT(onStringChanged(QString)));
447 
448     return textBox;
449 }
450 
value()451 QString ExtArgText::value()
452 {
453     if (textBox == 0)
454         return QString();
455 
456     return textBox->text();
457 }
458 
isValid()459 bool ExtArgText::isValid()
460 {
461     bool valid = true;
462 
463     if (isRequired() && value().length() == 0)
464         valid = false;
465 
466     /* Does the validator, if any, consider the value valid?
467      *
468      * If it considers it an "intermediate" value, rather than an "invalid"
469      * value, the user will be able to transfer the input focus to another
470      * widget, and, as long as all widgets have values for which isValid()
471      * is true, they wil be able to click the "Start" button.
472      *
473      * For QIntValidator(), used for integral fields with minimum and
474      * maximum values, a value that's larger than the maximum but has
475      * the same number of digits as the maximum is "intermediate" rather
476      * than "invalid", so the user will be able to cause that value to
477      * be passed to the extcap module; see bug 16510.
478      *
479      * So we explicitly call the hasAcceptableInput() method on the
480      * text box; that returns false if the value is not "valid", and
481      * that includes "intermediate" values.
482      *
483      * This way, 1) non-colorblind users are informed that the value
484      * is invalid by the text box background being red (perhaps the
485      * user isn't fully colorblind, or perhaps the background is a
486      * noticeably different grayscale), and 2) the user won't be able
487      * to start the capture until they fix the problem.
488      *
489      * XXX - it might be nice to have some way of indicating to the
490      * user what the problem is with the value - alert box?  Tooltip? */
491     if (!textBox->hasAcceptableInput())
492         valid = false;
493 
494     /* validation should only be checked if there is a value. if the argument
495      * must be present (isRequired) the check above will handle that */
496     if (valid && _argument->regexp != NULL && value().length() > 0)
497     {
498         QString regexp = QString().fromUtf8(_argument->regexp);
499         if (regexp.length() > 0)
500         {
501             QRegExp expr(regexp);
502             if (! expr.isValid() || expr.indexIn(value(), 0) == -1)
503                 valid = false;
504         }
505     }
506 
507     QString lblInvalidColor = ColorUtils::fromColorT(prefs.gui_text_invalid).name();
508     QString txtStyle("QLineEdit { background-color: %1; } ");
509     textBox->setStyleSheet(txtStyle.arg(valid ? QString("") : lblInvalidColor));
510 
511     return valid;
512 }
513 
ExtArgNumber(extcap_arg * argument,QObject * parent)514 ExtArgNumber::ExtArgNumber(extcap_arg * argument, QObject * parent) :
515         ExtArgText(argument, parent) {}
516 
createEditor(QWidget * parent)517 QWidget * ExtArgNumber::createEditor(QWidget * parent)
518 {
519     QString text = defaultValue();
520 
521     if (_argument->pref_valptr && *_argument->pref_valptr)
522     {
523         QString storeValue(*_argument->pref_valptr);
524 
525         if (storeValue.length() > 0 && storeValue.compare(text) != 0)
526             text = storeValue;
527     }
528 
529     textBox = (QLineEdit *)ExtArgText::createEditor(parent);
530     textBox->disconnect(SIGNAL(textChanged(QString)));
531 
532     if (_argument->arg_type == EXTCAP_ARG_INTEGER || _argument->arg_type == EXTCAP_ARG_UNSIGNED)
533     {
534         QIntValidator * textValidator = new QIntValidator(parent);
535         if (_argument->range_start != NULL)
536         {
537             int val = 0;
538             if (_argument->arg_type == EXTCAP_ARG_INTEGER)
539                 val = extcap_complex_get_int(_argument->range_start);
540             else if (_argument->arg_type == EXTCAP_ARG_UNSIGNED)
541             {
542                 guint tmp = extcap_complex_get_uint(_argument->range_start);
543                 if (tmp > G_MAXINT)
544                 {
545                     ws_log(LOG_DOMAIN_CAPTURE, LOG_LEVEL_DEBUG, "Defined value for range_start of %s exceeds valid integer range", _argument->call);
546                     val = G_MAXINT;
547                 }
548                 else
549                     val = (gint)tmp;
550             }
551 
552             textValidator->setBottom(val);
553         }
554         if (_argument->arg_type == EXTCAP_ARG_UNSIGNED && textValidator->bottom() < 0)
555         {
556             ws_log(LOG_DOMAIN_CAPTURE, LOG_LEVEL_DEBUG, "%s sets negative bottom range for unsigned value, setting to 0", _argument->call);
557             textValidator->setBottom(0);
558         }
559 
560         if (_argument->range_end != NULL)
561         {
562             int val = 0;
563             if (_argument->arg_type == EXTCAP_ARG_INTEGER)
564                 val = extcap_complex_get_int(_argument->range_end);
565             else if (_argument->arg_type == EXTCAP_ARG_UNSIGNED)
566             {
567                 guint tmp = extcap_complex_get_uint(_argument->range_end);
568                 if (tmp > G_MAXINT)
569                 {
570                     ws_log(LOG_DOMAIN_CAPTURE, LOG_LEVEL_DEBUG, "Defined value for range_end of %s exceeds valid integer range", _argument->call);
571                     val = G_MAXINT;
572                 }
573                 else
574                     val = (gint)tmp;
575             }
576 
577             textValidator->setTop(val);
578         }
579         textBox->setValidator(textValidator);
580     }
581     else if (_argument->arg_type == EXTCAP_ARG_DOUBLE)
582     {
583         QDoubleValidator * textValidator = new QDoubleValidator(parent);
584         if (_argument->range_start != NULL)
585             textValidator->setBottom(extcap_complex_get_double(_argument->range_start));
586         if (_argument->range_end != NULL)
587             textValidator->setTop(extcap_complex_get_double(_argument->range_end));
588 
589         textBox->setValidator(textValidator);
590     }
591 
592     textBox->setText(text.trimmed());
593 
594     connect(textBox, SIGNAL(textChanged(QString)), SLOT(onStringChanged(QString)));
595 
596     return textBox;
597 }
598 
defaultValue()599 QString ExtArgNumber::defaultValue()
600 {
601     QString result;
602 
603     if (_argument != 0)
604     {
605         if (_argument->arg_type == EXTCAP_ARG_DOUBLE)
606             result = QString::number(extcap_complex_get_double(_argument->default_complex));
607         else if (_argument->arg_type == EXTCAP_ARG_INTEGER)
608             result = QString::number(extcap_complex_get_int(_argument->default_complex));
609         else if (_argument->arg_type == EXTCAP_ARG_UNSIGNED)
610             result = QString::number(extcap_complex_get_uint(_argument->default_complex));
611         else if (_argument->arg_type == EXTCAP_ARG_LONG)
612             result = QString::number(extcap_complex_get_long(_argument->default_complex));
613         else
614         {
615             QString defValue = ExtcapArgument::defaultValue();
616             result = defValue.length() > 0 ? defValue : QString();
617         }
618     }
619 
620     return result;
621 }
622 
~ExtcapValue()623 ExtcapValue::~ExtcapValue() {}
624 
setChildren(ExtcapValueList children)625 void ExtcapValue::setChildren(ExtcapValueList children)
626 {
627     ExtcapValueList::iterator iter = children.begin();
628     while (iter != children.end())
629     {
630         (*iter)._depth = _depth + 1;
631         ++iter;
632     }
633 
634     _children.append(children);
635 }
636 
ExtcapArgument(QObject * parent)637 ExtcapArgument::ExtcapArgument(QObject *parent) :
638         QObject(parent), _argument(0), _label(0), _number(0),
639         label_style(QString("QLabel { color: %1; }"))
640 {
641 }
642 
ExtcapArgument(extcap_arg * argument,QObject * parent)643 ExtcapArgument::ExtcapArgument(extcap_arg * argument, QObject *parent) :
644         QObject(parent), _argument(argument), _label(0),
645         label_style(QString("QLabel { color: %1; }"))
646 {
647     _number = argument->arg_num;
648 
649     if (_argument->values != 0)
650     {
651         ExtcapValueList elements = loadValues(QString(""));
652         if (elements.length() > 0)
653             values.append(elements);
654     }
655 }
656 
ExtcapArgument(const ExtcapArgument & obj)657 ExtcapArgument::ExtcapArgument(const ExtcapArgument &obj) :
658         QObject(obj.parent()), _argument(obj._argument), _label(0),
659         label_style(QString("QLabel { color: %1; }"))
660 {
661     _number = obj._argument->arg_num;
662 
663     if (_argument->values != 0)
664     {
665         ExtcapValueList elements = loadValues(QString(""));
666         if (elements.length() > 0)
667             values.append(elements);
668     }
669 }
670 
loadValues(QString parent)671 ExtcapValueList ExtcapArgument::loadValues(QString parent)
672 {
673     if (_argument == 0 || _argument->values == 0)
674         return ExtcapValueList();
675 
676     GList * walker = 0;
677     extcap_value * v;
678     ExtcapValueList elements;
679 
680     for (walker = g_list_first((GList *)(_argument->values)); walker != NULL ; walker = walker->next)
681     {
682         v = (extcap_value *) walker->data;
683         if (v == NULL || v->display == NULL || v->call == NULL)
684             break;
685 
686         QString valParent = QString().fromUtf8(v->parent);
687 
688         if (parent.compare(valParent) == 0)
689         {
690 
691             QString display = QString().fromUtf8(v->display);
692             QString call = QString().fromUtf8(v->call);
693 
694             ExtcapValue element = ExtcapValue(display, call,
695                             v->enabled == (gboolean)TRUE, v->is_default == (gboolean)TRUE);
696 
697             if (!call.isEmpty())
698                 element.setChildren(this->loadValues(call));
699 
700             elements.append(element);
701         }
702     }
703 
704     return elements;
705 }
706 
reloadValues()707 bool ExtcapArgument::reloadValues()
708 {
709     if (! qobject_cast<ExtcapOptionsDialog*> (parent()) )
710         return false;
711 
712     ExtcapOptionsDialog * dialog = qobject_cast<ExtcapOptionsDialog*>(parent());
713     ExtcapValueList list = dialog->loadValuesFor(_argument->arg_num, _argument->call);
714 
715     if (list.size() > 0)
716     {
717         values.clear();
718         values << list;
719 
720         return true;
721     }
722 
723     return false;
724 }
725 
~ExtcapArgument()726 ExtcapArgument::~ExtcapArgument() {
727 }
728 
createLabel(QWidget * parent)729 QWidget * ExtcapArgument::createLabel(QWidget * parent)
730 {
731     if (_argument == 0 || _argument->display == 0)
732         return 0;
733 
734     QString lblInvalidColor = ColorUtils::fromColorT(prefs.gui_text_invalid).name();
735 
736     QString text = QString().fromUtf8(_argument->display);
737 
738     if (_label == 0)
739         _label = new QLabel(text, parent);
740     else
741         _label->setText(text);
742 
743     _label->setProperty("isRequired", QString(isRequired() ? "true" : "false"));
744 
745     _label->setStyleSheet (label_style.arg(QString("")));
746 
747     if (_argument->tooltip != 0)
748         _label->setToolTip(QString().fromUtf8(_argument->tooltip));
749 
750     return (QWidget *)_label;
751 }
752 
createEditor(QWidget *)753 QWidget * ExtcapArgument::createEditor(QWidget *)
754 {
755     return 0;
756 }
757 
call()758 QString ExtcapArgument::call()
759 {
760     return QString(_argument->call);
761 }
762 
value()763 QString ExtcapArgument::value()
764 {
765     return QString();
766 }
767 
prefValue()768 QString ExtcapArgument::prefValue()
769 {
770     return value();
771 }
772 
resetValue()773 void ExtcapArgument::resetValue()
774 {
775     if (_argument->pref_valptr) {
776         g_free(*_argument->pref_valptr);
777         *_argument->pref_valptr = g_strdup("");
778     }
779 }
780 
isValid()781 bool ExtcapArgument::isValid()
782 {
783     /* Unrequired arguments are always valid, except if validity checks fail,
784      * which must be checked in an derived class, not here */
785     if (! isRequired())
786         return true;
787 
788     return value().length() > 0;
789 }
790 
defaultValue()791 QString ExtcapArgument::defaultValue()
792 {
793     if (_argument != 0 && _argument->default_complex != 0)
794     {
795         gchar * str = extcap_get_complex_as_string(_argument->default_complex);
796         if (str != 0)
797             return QString(str);
798     }
799     return QString();
800 }
801 
group() const802 QString ExtcapArgument::group() const
803 {
804     if (_argument != 0 && _argument->group != 0)
805         return QString(_argument->group);
806 
807     return QString();
808 }
809 
argNr() const810 int ExtcapArgument::argNr() const
811 {
812     return _number;
813 }
814 
prefKey(const QString & device_name)815 QString ExtcapArgument::prefKey(const QString & device_name)
816 {
817     struct preference * pref = NULL;
818 
819     if (_argument == 0 || ! _argument->save)
820         return QString();
821 
822     pref = extcap_pref_for_argument(device_name.toStdString().c_str(), _argument);
823     if (pref != NULL)
824         return QString(prefs_get_name(pref));
825 
826     return QString();
827 }
828 
isRequired()829 bool ExtcapArgument::isRequired()
830 {
831     if (_argument != NULL)
832         return _argument->is_required;
833 
834     return FALSE;
835 }
836 
reload()837 bool ExtcapArgument::reload()
838 {
839     if (_argument != NULL)
840         return _argument->reload;
841 
842     return false;
843 }
844 
fileExists()845 bool ExtcapArgument::fileExists()
846 {
847     if (_argument != NULL)
848         return _argument->fileexists;
849 
850     return FALSE;
851 }
852 
isDefault()853 bool ExtcapArgument::isDefault()
854 {
855     if (value().compare(defaultValue()) == 0)
856         return true;
857 
858     return false;
859 }
860 
create(extcap_arg * argument,QObject * parent)861 ExtcapArgument * ExtcapArgument::create(extcap_arg * argument, QObject *parent)
862 {
863     if (argument == 0 || argument->display == 0)
864         return 0;
865 
866     ExtcapArgument * result = 0;
867 
868     if (argument->arg_type == EXTCAP_ARG_STRING || argument->arg_type == EXTCAP_ARG_PASSWORD)
869         result = new ExtArgText(argument, parent);
870     else if (argument->arg_type == EXTCAP_ARG_INTEGER || argument->arg_type == EXTCAP_ARG_LONG ||
871             argument->arg_type == EXTCAP_ARG_UNSIGNED || argument->arg_type == EXTCAP_ARG_DOUBLE)
872         result = new ExtArgNumber(argument, parent);
873     else if (argument->arg_type == EXTCAP_ARG_BOOLEAN || argument->arg_type == EXTCAP_ARG_BOOLFLAG)
874         result = new ExtArgBool(argument, parent);
875     else if (argument->arg_type == EXTCAP_ARG_SELECTOR)
876         result = new ExtArgSelector(argument, parent);
877     else if (argument->arg_type == EXTCAP_ARG_RADIO)
878         result = new ExtArgRadio(argument, parent);
879     else if (argument->arg_type == EXTCAP_ARG_FILESELECT)
880         result = new ExtcapArgumentFileSelection(argument, parent);
881     else if (argument->arg_type == EXTCAP_ARG_MULTICHECK)
882         result = new ExtArgMultiSelect(argument, parent);
883     else if (argument->arg_type == EXTCAP_ARG_TIMESTAMP)
884         result = new ExtArgTimestamp(argument, parent);
885     else
886     {
887         /* For everything else, we just print the label */
888         result = new ExtcapArgument(argument, parent);
889     }
890 
891     return result;
892 }
893 
894 /* The following is a necessity, because Q_Object does not do well with multiple inheritances */
onStringChanged(QString)895 void ExtcapArgument::onStringChanged(QString)
896 {
897     emit valueChanged();
898 }
899 
onIntChanged(int)900 void ExtcapArgument::onIntChanged(int)
901 {
902     if (isValid())
903         emit valueChanged();
904 }
905 
onBoolChanged(bool)906 void ExtcapArgument::onBoolChanged(bool)
907 {
908     emit valueChanged();
909 }
910