confgui: using the shared code had slightly broken the local parameters management. Fix it

This commit is contained in:
Jean-Francois Dockes 2019-10-06 12:03:51 +02:00
parent d0bd639b34
commit 5d8a66884a
3 changed files with 234 additions and 98 deletions

View File

@ -92,7 +92,6 @@ void ConfTabsW::hideButtons()
void ConfTabsW::acceptChanges()
{
cerr << "ConfTabsW::acceptChanges()\n";
for (auto& entry : m_panels) {
entry->storeValues();
}
@ -106,7 +105,6 @@ void ConfTabsW::acceptChanges()
void ConfTabsW::rejectChanges()
{
cerr << "ConfTabsW::rejectChanges()\n";
reloadPanels();
if (!buttonBox->isHidden())
close();
@ -147,6 +145,30 @@ void ConfTabsW::setCurrentIndex(int idx)
}
}
QWidget *ConfTabsW::addBlurb(int tabindex, const QString& txt)
{
ConfPanelW *panel = (ConfPanelW*)tabWidget->widget(tabindex);
if (panel == 0) {
return 0;
}
QFrame *line = new QFrame(panel);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
panel->addWidget(line);
QLabel *explain = new QLabel(panel);
explain->setWordWrap(true);
explain->setText(txt);
panel->addWidget(explain);
line = new QFrame(panel);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
panel->addWidget(line);
return explain;
}
ConfParamW *ConfTabsW::addParam(
int tabindex, ParamType tp, const QString& varname,
const QString& label, const QString& tooltip,
@ -190,36 +212,29 @@ ConfParamW *ConfTabsW::addParam(
cp = new ConfParamCSLW(varname, this, lnk, label, tooltip, *sl);
break;
}
panel->addWidget(cp);
m_params.push_back(cp);
panel->addParam(cp);
return cp;
}
ConfParamW *ConfTabsW::findParamW(const QString& varname)
{
for (const auto& param : m_params) {
if (!varname.compare(param->getVarName())) {
return param;
}
for (const auto& panel : m_panels) {
ConfParamW *w = panel->findParamW(varname);
if (w)
return w;
}
return 0;
return nullptr;
}
void ConfTabsW::endOfList(int tabindex)
{
ConfPanelW *panel = (ConfPanelW*)tabWidget->widget(tabindex);
if (panel == 0)
if (nullptr == panel)
return;
panel->endOfList();
}
bool ConfTabsW::enableLink(ConfParamW* boolw, ConfParamW* otherw, bool revert)
{
if (std::find(m_params.begin(), m_params.end(), boolw) == m_params.end() ||
std::find(m_params.begin(), m_params.end(), otherw) ==
m_params.end()) {
cerr << "ConfTabsW::enableLink: param not found\n";
return false;
}
ConfParamBoolW *bw = dynamic_cast<ConfParamBoolW*>(boolw);
if (bw == 0) {
cerr << "ConfTabsW::enableLink: not a boolw\n";
@ -245,10 +260,25 @@ ConfPanelW::ConfPanelW(QWidget *parent)
m_vboxlayout->setContentsMargins(margin);
}
void ConfPanelW::addParam(ConfParamW *w)
{
m_vboxlayout->addWidget(w);
m_params.push_back(w);
}
void ConfPanelW::addWidget(QWidget *w)
{
m_vboxlayout->addWidget(w);
m_widgets.push_back(w);
}
ConfParamW *ConfPanelW::findParamW(const QString& varname)
{
for (const auto& param : m_params) {
if (!varname.compare(param->getVarName())) {
return param;
}
}
return nullptr;
}
void ConfPanelW::endOfList()
@ -258,15 +288,15 @@ void ConfPanelW::endOfList()
void ConfPanelW::storeValues()
{
for (auto& widgetp : m_widgets) {
((ConfParamW*)widgetp)->storeValue();
for (auto& widgetp : m_params) {
widgetp->storeValue();
}
}
void ConfPanelW::loadValues()
{
for (auto& widgetp : m_widgets) {
((ConfParamW*)widgetp)->loadValue();
for (auto& widgetp : m_params) {
widgetp->loadValue();
}
}
@ -397,6 +427,12 @@ void ConfParamIntW::loadValue()
}
}
void ConfParamIntW::setImmediate()
{
connect(m_sb, SIGNAL(valueChanged(int)),
this, SLOT(setValue(int)));
}
ConfParamStrW::ConfParamStrW(
const QString& varnm, QWidget *parent, ConfLink cflink,
const QString& lbltxt, const QString& tltptxt)
@ -432,6 +468,12 @@ void ConfParamStrW::loadValue()
}
}
void ConfParamStrW::setImmediate()
{
connect(m_le, SIGNAL(textChanged(const QString&)),
this, SLOT(setValue(const QString&)));
}
ConfParamCStrW::ConfParamCStrW(
const QString& varnm, QWidget *parent, ConfLink cflink,
const QString& lbltxt, const QString& tltptxt, const QStringList& sl)
@ -485,6 +527,12 @@ void ConfParamCStrW::loadValue()
m_origvalue = cs;
}
void ConfParamCStrW::setImmediate()
{
connect(m_cmb, SIGNAL(activated(const QString&)),
this, SLOT(setValue(const QString&)));
}
ConfParamBoolW::ConfParamBoolW(
const QString& varnm, QWidget *parent, ConfLink cflink,
const QString& lbltxt, const QString& tltptxt, bool deflt)
@ -525,6 +573,12 @@ void ConfParamBoolW::loadValue()
m_cb->setChecked(m_origvalue);
}
void ConfParamBoolW::setImmediate()
{
connect(m_cb, SIGNAL(toggled(bool)), this, SLOT(setValue(bool)));
}
ConfParamFNW::ConfParamFNW(
const QString& varnm, QWidget *parent, ConfLink cflink,
const QString& lbltxt, const QString& tltptxt, bool isdir)
@ -576,6 +630,12 @@ void ConfParamFNW::showBrowserDialog()
}
}
void ConfParamFNW::setImmediate()
{
connect(m_le, SIGNAL(textChanged(const QString&)),
this, SLOT(setValue(const QString&)));
}
class SmallerListWidget: public QListWidget {
public:
SmallerListWidget(QWidget *parent)
@ -644,6 +704,9 @@ ConfParamSLW::ConfParamSLW(
m_lb = new SmallerListWidget(this);
m_lb->setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(m_lb, SIGNAL(currentTextChanged(const QString&)),
this, SIGNAL(currentTextChanged(const QString&)));
setSzPol(m_lb, QSizePolicy::Preferred, QSizePolicy::Preferred, 1, 1);
m_hl->addWidget(m_lb);
@ -660,7 +723,7 @@ void ConfParamSLW::setEditable(bool onoff)
}
}
void ConfParamSLW::storeValue()
string ConfParamSLW::listToString()
{
vector<string> ls;
for (int i = 0; i < m_lb->count(); i++) {
@ -676,6 +739,12 @@ void ConfParamSLW::storeValue()
}
string s;
stringsToString(ls, s);
return s;
}
void ConfParamSLW::storeValue()
{
string s = listToString();
if (s.compare(m_origvalue)) {
m_cflink->set(s);
}
@ -702,20 +771,34 @@ void ConfParamSLW::loadValue()
void ConfParamSLW::showInputDialog()
{
bool ok;
QString s = QInputDialog::getText(this,
"", // title
"", // label,
QLineEdit::Normal, // EchoMode mode
"", // const QString & text
&ok);
QString s = QInputDialog::getText(this, "", "", QLineEdit::Normal, "", &ok);
if (!ok || s.isEmpty()) {
return;
}
if (ok && !s.isEmpty()) {
QList<QListWidgetItem *>items =
m_lb->findItems(s, Qt::MatchFixedString | Qt::MatchCaseSensitive);
if (items.empty()) {
m_lb->insertItem(0, s);
m_lb->sortItems();
}
performInsert(s);
}
void ConfParamSLW::performInsert(const QString& s)
{
QList<QListWidgetItem *> existing =
m_lb->findItems(s, Qt::MatchFixedString | Qt::MatchCaseSensitive);
if (!existing.empty()) {
m_lb->setCurrentItem(existing[0]);
return;
}
m_lb->insertItem(0, s);
m_lb->sortItems();
existing = m_lb->findItems(s, Qt::MatchFixedString | Qt::MatchCaseSensitive);
if (existing.empty()) {
cerr << "Item not found after insertion!" << endl;
return;
}
m_lb->setCurrentItem(existing[0], QItemSelectionModel::ClearAndSelect);
if (m_immediate) {
string nv = listToString();
m_cflink->set(nv);
}
}
@ -743,6 +826,13 @@ void ConfParamSLW::deleteSelected()
emit entryDeleted(item->text());
delete item;
}
if (m_immediate) {
string nv = listToString();
m_cflink->set(nv);
}
if (m_lb->count()) {
m_lb->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
}
}
void ConfParamSLW::editSelected()
@ -754,6 +844,10 @@ void ConfParamSLW::editSelected()
this, "", "", QLineEdit::Normal, m_lb->item(i)->text(), &ok);
if (ok && !s.isEmpty()) {
m_lb->item(i)->setText(s);
if (m_immediate) {
string nv = listToString();
m_cflink->set(nv);
}
}
}
}
@ -763,46 +857,24 @@ void ConfParamSLW::editSelected()
void ConfParamDNLW::showInputDialog()
{
QString s = myGetFileName(true);
if (!s.isEmpty()) {
QList<QListWidgetItem *>items =
m_lb->findItems(s, Qt::MatchFixedString | Qt::MatchCaseSensitive);
if (items.empty()) {
m_lb->insertItem(0, s);
m_lb->sortItems();
QList<QListWidgetItem *>items =
m_lb->findItems(s, Qt::MatchFixedString|Qt::MatchCaseSensitive);
if (m_lb->selectionMode() == QAbstractItemView::SingleSelection &&
!items.empty()) {
m_lb->setCurrentItem(*items.begin());
}
}
if (s.isEmpty()) {
return;
}
performInsert(s);
}
// "Add entry" dialog for a constrained string list
void ConfParamCSLW::showInputDialog()
{
bool ok;
QString s = QInputDialog::getItem(this, // parent
"", // title
"", // label,
m_sl, // items,
0, // current = 0
false, // editable = true,
&ok);
if (ok && !s.isEmpty()) {
QList<QListWidgetItem *>items =
m_lb->findItems(s, Qt::MatchFixedString | Qt::MatchCaseSensitive);
if (items.empty()) {
m_lb->insertItem(0, s);
m_lb->sortItems();
}
QString s = QInputDialog::getItem(this, "", "", m_sl, 0, false, &ok);
if (!ok || s.isEmpty()) {
return;
}
performInsert(s);
}
#ifdef ENABLE_XMLCONF
static QString u8s2qs(const std::string us)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2018 J.F.Dockes
/* Copyright (C) 2007-2019 J.F.Dockes
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
@ -17,33 +17,48 @@
#ifndef _confgui_h_included_
#define _confgui_h_included_
/**
* This file defines a number of simple classes (virtual base: ConfParamW)
* which let the user input configuration parameters.
* Utilities for a configuration/preferences settings user interface.
*
* This file declares a number of data input Qt widgets (virtual base:
* ConfParamW), with a well defined virtual interface to configuration storage,
* which may be QSettings or something else (e.g. conftree).
*
* Subclasses are defined for entering different kind of data, ie a string,
* Subclasses are defined for entering different kind of data, e.g. a string,
* a file name, an integer, etc.
*
* Each configuration gui object is linked to the configuration data through
* Each GUI object is linked to the configuration data through
* a "link" object which knows the details of interacting with the actual
* configuration data, like the parameter name, the actual config object,
* the method to call etc.
* configuration data, like the parameter name, the actual
* configuration interface, etc.
*
* The link object is set when the input widget is created and cannot be
* changed.
*
* The widgets are typically linked to a temporary configuration object, which
* is then copied to the actual configuration if the data is accepted, or
* destroyed and recreated as a copy if Cancel is pressed (you have to
* delete/recreate the widgets in this case as the links are no longer valid).
* The link object get() methods are called for reading the initial data.
*
* The set() methods of the link objects are only called if the
* current value() differs from the value obtained by get() when the
* object was initialized. This can be used to avoid cluttering the
* output with values which are unmodified from the defaults.
* The set() methods for all the objects are normally called when the
* user clicks "Accept", only if the current value() differs from the
* value obtained by get() when the object was initialized. This can
* be used to avoid cluttering the output with values which are
* unmodified from the defaults.
*
* The setImmediate() method can be called on the individial controls
* to ensure that set() is inconditionnaly called whenever the user
* changes the related value. This can be especially useful if the
* configuration state can't be fully represented in the GUI (for
* example if the same parameter name can exist in different sections
* depending on the value of another parameter). It allows using local
* storage for the values, and flushing, for example, when
* sig_prefsChanged() is emitted after the user clicks accept.
*
* The file also defines a multi-tabbed dialog container for the
* parameter objects, with simple interface methods to create/add
* panels and elements.
* parameter objects, with simple interface methods to add tabs and add
* configuration elements to them.
*
* Some of the tab widgets can be defined as "foreign", with specific internals.
* They just need to implement a loadValues() to be called at
* initialisation and a storeValues(), called when the user commits
* the changes.
*/
#include <string>
@ -80,7 +95,7 @@ public:
typedef std::shared_ptr<ConfLinkRep> ConfLink;
// May be used to store/manage data which has no direct representation
// in the config
// in the stored configuration.
class ConfLinkNullRep : public ConfLinkRep {
public:
virtual ~ConfLinkNullRep() {}
@ -90,13 +105,15 @@ public:
virtual bool get(std::string& val) {val = ""; return true;}
};
/** Link maker class */
/** Link maker class. Will be called back by addParam() to create the link */
class ConfLinkFact {
public:
virtual ~ConfLinkFact() {}
virtual ConfLink operator()(const QString& nm) = 0;
};
/** Interface for "foreign" panels. The object must also be a QWidget, which
* we don't express by inheriting here to avoid qt issues */
class ConfPanelWIF {
public:
virtual ~ConfPanelWIF() {}
@ -115,8 +132,10 @@ class ConfTabsW : public QDialog {
public:
ConfTabsW(QWidget *parent, const QString& title, ConfLinkFact *linkfact);
enum ParamType {CFPT_BOOL, CFPT_INT, CFPT_STR, CFPT_CSTR, CFPT_FN,
CFPT_STRL, CFPT_DNL, CFPT_CSTRL
enum ParamType {CFPT_BOOL, CFPT_INT, CFPT_STR,
CFPT_CSTR, // Constrained string: from list
CFPT_FN, // File/directory
CFPT_STRL, CFPT_DNL, CFPT_CSTRL // lists of the same
};
/** Add tab and return its identifier / index */
@ -127,11 +146,22 @@ public:
int addForeignPanel(ConfPanelWIF* w, const QString& title);
/** Add parameter setter to specified tab */
ConfParamW *addParam(int tabindex, ParamType tp,
const QString& varname, const QString& label,
const QString& tooltip, int isdirorminval = 0,
int maxval = 0, const QStringList* sl = 0);
ConfParamW *addParam(
int tabindex, ParamType tp, const QString& varname, const QString& label,
const QString& tooltip,
int isdirorminval = 0, /* Dep. on type: directory flag or min value */
int maxval = 0, const QStringList* sl = 0);
/** Add explanatory text between 2 horizontal lines */
QWidget *addBlurb(int tabindex, const QString& txt);
/** Enable link between bool value and another parameter: the control will
* be enabled depending on the boolean value (with possible inversion). Can
* be called multiple times for the same bool to enable/disable
* several controls */
bool enableLink(ConfParamW* boolw, ConfParamW* otherw, bool revert = false);
/** Call this when you are done filling up a tab */
void endOfList(int tabindex);
/** Find param widget associated with given variable name */
@ -152,11 +182,12 @@ signals:
private:
ConfLinkFact *m_makelink{nullptr};
// All ConfPanelW managed panels. Each has a load/store interface
// and an internal list of controls
std::vector<ConfPanelW *> m_panels;
// "Foreign" panels
// "Foreign" panels. Just implement load/store
std::vector<ConfPanelWIF *> m_widgets;
// All params
std::vector<ConfParamW *> m_params;
QTabWidget *tabWidget{nullptr};
QDialogButtonBox *buttonBox{nullptr};
};
@ -171,13 +202,16 @@ class ConfPanelW : public QWidget {
Q_OBJECT
public:
ConfPanelW(QWidget *parent);
void addParam(ConfParamW *w);
void addWidget(QWidget *w);
void storeValues();
void loadValues();
void endOfList();
/** Find param widget associated with given variable name */
ConfParamW *findParamW(const QString& varname);
private:
QVBoxLayout *m_vboxlayout;
std::vector<QWidget *> m_widgets;
std::vector<ConfParamW *> m_params;
};
/** Config panel element: manages one configuration
@ -191,6 +225,10 @@ public:
m_cflink(cflink), m_fsencoding(false) {
}
virtual void loadValue() = 0;
// Call setValue() each time the control changes, instead of on accept.
virtual void setImmediate() = 0;
virtual void setFsEncoding(bool onoff) {
m_fsencoding = onoff;
}
@ -201,6 +239,11 @@ public slots:
virtual void setEnabled(bool) = 0;
virtual void storeValue() = 0;
protected slots:
void setValue(const QString& newvalue);
void setValue(int newvalue);
void setValue(bool newvalue);
protected:
QString m_varname;
ConfLink m_cflink;
@ -209,9 +252,6 @@ protected:
// are encoded as utf-8
bool m_fsencoding;
virtual bool createCommon(const QString& lbltxt, const QString& tltptxt);
void setValue(const QString& newvalue);
void setValue(int newvalue);
void setValue(bool newvalue);
};
//////// Widgets for setting the different types of configuration parameters:
@ -225,6 +265,7 @@ public:
const QString& tltptxt, bool deflt = false);
virtual void loadValue();
virtual void storeValue();
virtual void setImmediate();
public slots:
virtual void setEnabled(bool i) {
if (m_cb) {
@ -251,6 +292,7 @@ public:
int defaultvalue = 0);
virtual void loadValue();
virtual void storeValue();
virtual void setImmediate();
public slots:
virtual void setEnabled(bool i) {
if (m_sb) {
@ -272,6 +314,7 @@ public:
const QString& tltptxt);
virtual void loadValue();
virtual void storeValue();
virtual void setImmediate();
public slots:
virtual void setEnabled(bool i) {
if (m_le) {
@ -293,6 +336,7 @@ public:
virtual void loadValue();
virtual void storeValue();
virtual void setList(const QStringList& sl);
virtual void setImmediate();
public slots:
virtual void setEnabled(bool i) {
if (m_cmb) {
@ -313,6 +357,7 @@ public:
const QString& tltptxt, bool isdir = false);
virtual void loadValue();
virtual void storeValue();
virtual void setImmediate();
protected slots:
void showBrowserDialog();
public slots:
@ -344,6 +389,9 @@ public:
return m_lb;
}
virtual void setEditable(bool onoff);
virtual void setImmediate() {
m_immediate = true;
}
public slots:
virtual void setEnabled(bool i) {
@ -355,13 +403,16 @@ protected slots:
virtual void showInputDialog();
void deleteSelected();
void editSelected();
void performInsert(const QString&);
signals:
void entryDeleted(QString);
void currentTextChanged(const QString&);
protected:
QListWidget *m_lb;
void listToConf();
std::string listToString();
std::string m_origvalue;
QPushButton *m_pbE;
bool m_immediate{false};
};
// Dir name list

View File

@ -61,6 +61,8 @@ public:
virtual bool set(const string& val) {
if (!m_conf || !*m_conf)
return false;
LOGDEB("ConfLinkRclRep: set " << m_nm << " -> " << val << " sk " <<
getSk() << std::endl);
bool ret = (*m_conf)->set(m_nm, val, getSk());
if (!ret)
LOGERR("Value set failed\n" );
@ -70,7 +72,7 @@ public:
if (!m_conf || !*m_conf)
return false;
bool ret = (*m_conf)->get(m_nm, val, getSk());
LOGDEB1("ConfLinkRcl::get: [" << m_nm << "] sk [" <<
LOGDEB("ConfLinkRcl::get: [" << m_nm << "] sk [" <<
getSk() << "] -> [" << (ret ? val : "no value") << "]\n");
return ret;
}
@ -463,6 +465,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
QObject::tr("These are patterns for file or directory "
" names which should not be indexed."));
eskn->setFsEncoding(true);
eskn->setImmediate();
m_widgets.push_back(eskn);
gl1->addWidget(eskn, gridy, 0);
@ -478,6 +481,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
tr("Only mime types"),
tr("An exclusive list of indexed mime types.<br>Nothing "
"else will be indexed. Normally empty and inactive"), amimesq);
eincm->setImmediate();
m_widgets.push_back(eincm);
gl1->addWidget(eincm, gridy++, 1);
@ -486,6 +490,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
ConfLink(new ConfLinkRclRep(config, "excludedmimetypes", &m_sk)),
tr("Exclude mime types"),
tr("Mime types not to be indexed"), amimesq);
eexcm->setImmediate();
m_widgets.push_back(eexcm);
gl1->addWidget(eexcm, gridy, 0);
@ -498,6 +503,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
QObject::tr("These are file name endings for files which will be "
"indexed by name only \n(no MIME type identification "
"attempt, no decompression, no content indexing)."));
encs->setImmediate();
encs->setFsEncoding(true);
m_widgets.push_back(encs);
gl1->addWidget(encs, gridy++, 1);
@ -530,6 +536,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
"The default value is empty, "
"and the value from the NLS environnement is used."
), charsets);
e21->setImmediate();
m_widgets.push_back(e21);
gl1->addWidget(e21, gridy++, 0);
@ -540,6 +547,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
QObject::tr("Follow symbolic links while "
"indexing. The default is no, "
"to avoid duplicate indexing"));
e3->setImmediate();
m_widgets.push_back(e3);
gl1->addWidget(e3, gridy, 0);
@ -550,6 +558,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
QObject::tr("Index the names of files for which the contents "
"cannot be identified or processed (no or "
"unsupported mime type). Default true"));
eafln->setImmediate();
m_widgets.push_back(eafln);
gl1->addWidget(eafln, gridy++, 1);
@ -560,6 +569,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
tr("This value sets a threshold beyond which compressed"
"files will not be processed. Set to -1 for no "
"limit, to 0 for no decompression ever."), -1, 1000000, -1);
ezfmaxkbs->setImmediate();
m_widgets.push_back(ezfmaxkbs);
gl1->addWidget(ezfmaxkbs, gridy, 0);
@ -571,6 +581,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
"files will not be processed. Set to -1 for no "
"limit. \nThis is for excluding monster "
"log files from the index."), -1, 1000000);
etxtmaxmbs->setImmediate();
m_widgets.push_back(etxtmaxmbs);
gl1->addWidget(etxtmaxmbs, gridy++, 1);
@ -582,6 +593,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
"files will be split in chunks of this size for "
"indexing.\nThis will help searching very big text "
" files (ie: log files)."), -1, 1000000);
etxtpagekbs->setImmediate();
m_widgets.push_back(etxtpagekbs);
gl1->addWidget(etxtpagekbs, gridy, 0);
@ -593,6 +605,7 @@ ConfSubPanelW::ConfSubPanelW(QWidget *parent, ConfNull **config,
"aborted. This is for the rare case (ie: postscript) "
"where a document could cause a filter to loop. "
"Set to -1 for no limit.\n"), -1, 10000);
efiltmaxsecs->setImmediate();
m_widgets.push_back(efiltmaxsecs);
gl1->addWidget(efiltmaxsecs, gridy++, 1);