--- a
+++ b/cfgui/confgui.h
@@ -0,0 +1,435 @@
+/* Copyright (C) 2007-2018 J.F.Dockes
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#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.
+ *
+ * Subclasses are defined for entering different kind of data, ie a string,
+ * a file name, an integer, etc.
+ *
+ * Each configuration 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.
+ *
+ * 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 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 file also defines a multi-tabbed dialog container for the
+ * parameter objects, with simple interface methods to create/add
+ * panels and elements.
+ */
+
+#include <string>
+#include <limits.h>
+
+#include <memory>
+#include <vector>
+#include <string>
+
+#include <QString>
+#include <QWidget>
+#include <QDialog>
+
+class ConfNull;
+class QCheckBox;
+class QComboBox;
+class QDialogButtonBox;
+class QHBoxLayout;
+class QLineEdit;
+class QListWidget;
+class QPushButton;
+class QSpinBox;
+class QTabWidget;
+class QVBoxLayout;
+
+namespace confgui {
+
+/** Interface between the GUI widget and the config storage mechanism: */
+class ConfLinkRep {
+public:
+ virtual ~ConfLinkRep() {}
+ virtual bool set(const std::string& val) = 0;
+ virtual bool get(std::string& val) = 0;
+};
+typedef std::shared_ptr<ConfLinkRep> ConfLink;
+
+/** Link maker class */
+class ConfLinkFact {
+public:
+ virtual ~ConfLinkFact() {}
+ virtual ConfLink operator()(const QString& nm) = 0;
+};
+
+class ConfPanelWIF {
+public:
+ virtual ~ConfPanelWIF() {}
+ virtual void storeValues() = 0;
+ virtual void loadValues() = 0;
+};
+
+class ConfPanelW;
+class ConfParamW;
+
+/** The top level widget has tabs, each tab/panel has multiple widgets
+ * for setting parameter values */
+class ConfTabsW : public QDialog {
+ Q_OBJECT;
+
+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
+ };
+
+ /** Add tab and return its identifier / index */
+ int addPanel(const QString& title);
+
+ /** Add foreign tab where we only know to call loadvalues/storevalues.
+ * The object has to derive from QWidget */
+ 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);
+ bool enableLink(ConfParamW* boolw, ConfParamW* otherw, bool revert = false);
+ void endOfList(int tabindex);
+
+ /** Find param widget associated with given variable name */
+ ConfParamW *findParamW(const QString& varname);
+
+ void hideButtons();
+
+public slots:
+ void acceptChanges();
+ void rejectChanges();
+ void reloadPanels();
+ void setCurrentIndex(int);
+
+signals:
+ /** This is emitted when acceptChanges() is called, after the
+ * values have been stored */
+ void sig_prefsChanged();
+
+private:
+ ConfLinkFact *m_makelink{nullptr};
+ std::vector<ConfPanelW *> m_panels;
+ // "Foreign" panels
+ std::vector<ConfPanelWIF *> m_widgets;
+ // All params
+ std::vector<ConfParamW *> m_params;
+ QTabWidget *tabWidget{nullptr};
+ QDialogButtonBox *buttonBox{nullptr};
+};
+
+/////////////////////////////////////////////////
+// The rest of the class definitions are only useful if you need to
+// access a specific element for customisation (use findParamW() and a
+// dynamic cast).
+
+/** A panel/tab contains multiple controls for parameters */
+class ConfPanelW : public QWidget {
+ Q_OBJECT
+public:
+ ConfPanelW(QWidget *parent);
+ void addWidget(QWidget *w);
+ void storeValues();
+ void loadValues();
+ void endOfList();
+private:
+ QVBoxLayout *m_vboxlayout;
+ std::vector<QWidget *> m_widgets;
+};
+
+/** Config panel element: manages one configuration
+ * parameter. Subclassed for specific parameter types.
+ */
+class ConfParamW : public QWidget {
+ Q_OBJECT
+public:
+ ConfParamW(const QString& varnm, QWidget *parent, ConfLink cflink)
+ : QWidget(parent), m_varname(varnm),
+ m_cflink(cflink), m_fsencoding(false) {
+ }
+ virtual void loadValue() = 0;
+ virtual void setFsEncoding(bool onoff) {
+ m_fsencoding = onoff;
+ }
+ const QString& getVarName() {
+ return m_varname;
+ }
+public slots:
+ virtual void setEnabled(bool) = 0;
+ virtual void storeValue() = 0;
+
+protected:
+ QString m_varname;
+ ConfLink m_cflink;
+ QHBoxLayout *m_hl;
+ // File names are encoded as local8bit in the config files. Other
+ // 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:
+
+/** Boolean */
+class ConfParamBoolW : public ConfParamW {
+ Q_OBJECT
+public:
+ ConfParamBoolW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt, bool deflt = false);
+ virtual void loadValue();
+ virtual void storeValue();
+public slots:
+ virtual void setEnabled(bool i) {
+ if (m_cb) {
+ ((QWidget*)m_cb)->setEnabled(i);
+ }
+ }
+public:
+ QCheckBox *m_cb;
+ bool m_dflt;
+ bool m_origvalue;
+};
+
+// Int
+class ConfParamIntW : public ConfParamW {
+ Q_OBJECT
+public:
+ // The default value is only used if none exists in the sample
+ // configuration file. Defaults are normally set in there.
+ ConfParamIntW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt,
+ int minvalue = INT_MIN,
+ int maxvalue = INT_MAX,
+ int defaultvalue = 0);
+ virtual void loadValue();
+ virtual void storeValue();
+public slots:
+ virtual void setEnabled(bool i) {
+ if (m_sb) {
+ ((QWidget*)m_sb)->setEnabled(i);
+ }
+ }
+protected:
+ QSpinBox *m_sb;
+ int m_defaultvalue;
+ int m_origvalue;
+};
+
+// Arbitrary string
+class ConfParamStrW : public ConfParamW {
+ Q_OBJECT
+public:
+ ConfParamStrW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt);
+ virtual void loadValue();
+ virtual void storeValue();
+public slots:
+ virtual void setEnabled(bool i) {
+ if (m_le) {
+ ((QWidget*)m_le)->setEnabled(i);
+ }
+ }
+protected:
+ QLineEdit *m_le;
+ QString m_origvalue;
+};
+
+// Constrained string: choose from list
+class ConfParamCStrW : public ConfParamW {
+ Q_OBJECT
+public:
+ ConfParamCStrW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt, const QStringList& sl);
+ virtual void loadValue();
+ virtual void storeValue();
+ virtual void setList(const QStringList& sl);
+public slots:
+ virtual void setEnabled(bool i) {
+ if (m_cmb) {
+ ((QWidget*)m_cmb)->setEnabled(i);
+ }
+ }
+protected:
+ QComboBox *m_cmb;
+ QString m_origvalue;
+};
+
+// File name
+class ConfParamFNW : public ConfParamW {
+ Q_OBJECT
+public:
+ ConfParamFNW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt, bool isdir = false);
+ virtual void loadValue();
+ virtual void storeValue();
+protected slots:
+ void showBrowserDialog();
+public slots:
+ virtual void setEnabled(bool i) {
+ if (m_le) {
+ ((QWidget*)m_le)->setEnabled(i);
+ }
+ if (m_pb) {
+ ((QWidget*)m_pb)->setEnabled(i);
+ }
+ }
+protected:
+ QLineEdit *m_le;
+ QPushButton *m_pb;
+ bool m_isdir;
+ QString m_origvalue;
+};
+
+// String list
+class ConfParamSLW : public ConfParamW {
+ Q_OBJECT
+public:
+ ConfParamSLW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt);
+ virtual void loadValue();
+ virtual void storeValue();
+ QListWidget *getListBox() {
+ return m_lb;
+ }
+
+public slots:
+ virtual void setEnabled(bool i) {
+ if (m_lb) {
+ ((QWidget*)m_lb)->setEnabled(i);
+ }
+ }
+protected slots:
+ virtual void showInputDialog();
+ void deleteSelected();
+signals:
+ void entryDeleted(QString);
+protected:
+ QListWidget *m_lb;
+ void listToConf();
+ std::string m_origvalue;
+};
+
+// Dir name list
+class ConfParamDNLW : public ConfParamSLW {
+ Q_OBJECT
+public:
+ ConfParamDNLW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt)
+ : ConfParamSLW(varnm, parent, cflink, lbltxt, tltptxt) {
+ m_fsencoding = true;
+ }
+protected slots:
+ virtual void showInputDialog();
+};
+
+// Constrained string list (chose from predefined)
+class ConfParamCSLW : public ConfParamSLW {
+ Q_OBJECT
+public:
+ ConfParamCSLW(const QString& varnm, QWidget *parent, ConfLink cflink,
+ const QString& lbltxt,
+ const QString& tltptxt,
+ const QStringList& sl)
+ : ConfParamSLW(varnm, parent, cflink, lbltxt, tltptxt), m_sl(sl) {
+ }
+protected slots:
+ virtual void showInputDialog();
+protected:
+ const QStringList m_sl;
+};
+
+#ifdef ENABLE_XMLCONF
+/**
+ * Interpret an XML string and create a configuration interface. XML sample:
+ *
+ * <confcomments>
+ * <filetitle>Configuration file parameters for upmpdcli</filetitle>
+ * <grouptitle>MPD parameters</grouptitle>
+ * <var name="mpdhost" type="string">
+ * <brief>Host MPD runs on.</brief>
+ * <descr>Defaults to localhost. This can also be specified as -h</descr>
+ * </var>
+ * mpdhost = default-host
+ * <var name="mpdport" type="int" values="0 65635 6600">
+ * <brief>IP port used by MPD</brief>.
+ * <descr>Can also be specified as -p port. Defaults to the...</descr>
+ * </var>
+ * mpdport = defport
+ * <var name="ownqueue" type="bool" values="1">
+ * <brief>Set if we own the MPD queue.</brief>
+ * <descr>If this is set (on by default), we own the MPD...</descr>
+ * </var>
+ * ownqueue =
+ * </confcomments>
+ *
+ * <grouptitle> creates a panel in which the following <var> are set.
+ * The <var> attributes should be self-explanatory. "values"
+ * is used for different things depending on the var type
+ * (min/max, default, str list). Check the code about this.
+ * type values: "bool" "int" "string" "cstr" "cstrl" "fn" "dfn" "strl" "dnl"
+ *
+ * The XML would typically exist as comments inside a reference configuration
+ * file (ConfSimple can extract such comments).
+ *
+ * This means that the reference configuration file can generate both
+ * the documentation and the GUI interface.
+ *
+ * @param xml the input xml
+ * @param[output] toptxt the top level XML text (text not inside <var>,
+ * normally commented variable assignments). This will be evaluated
+ * as a config for default values.
+ * @lnkf factory to create the objects which link the GUI to the
+ * storage mechanism.
+ */
+extern ConfTabsW *xmlToConfGUI(const std::string& xml,
+ std::string& toptxt,
+ ConfLinkFact* lnkf,
+ QWidget *parent);
+#endif
+
+}
+
+#endif /* _confgui_h_included_ */