diff --git a/python/core/additions/qgssettingsentry.py b/python/core/additions/qgssettingsentry.py index 1a74f56dbd5..4b119a69d18 100644 --- a/python/core/additions/qgssettingsentry.py +++ b/python/core/additions/qgssettingsentry.py @@ -132,7 +132,7 @@ class PyQgsSettingsEntryEnumFlag(QgsSettingsEntryBase): elif dynamicKeyPart is None: dynamicKeyPart = [] - return super().setVariantValuePrivate(enum_flag_key, dynamicKeyPart) + return super().setVariantValue(enum_flag_key, dynamicKeyPart) def settingsType(self): """ diff --git a/python/core/auto_generated/settings/qgssettingsentry.sip.in b/python/core/auto_generated/settings/qgssettingsentry.sip.in index 22e600491d0..407a9f3a302 100644 --- a/python/core/auto_generated/settings/qgssettingsentry.sip.in +++ b/python/core/auto_generated/settings/qgssettingsentry.sip.in @@ -12,6 +12,8 @@ + + class QgsSettingsEntryBase { %Docstring(signature="appended") @@ -93,6 +95,14 @@ Constructor for QgsSettingsEntryBase. virtual ~QgsSettingsEntryBase(); + virtual QString typeId() const; +%Docstring +Returns the id of the type of settings +This can be re-implemented in a custom implementation of a setting + +.. versionadded:: 3.32 +%End + QString name() const; %Docstring Returns the name of the settings @@ -191,26 +201,21 @@ Returns settings section. The settings section of the parent group is returned i the key is entirely self-defined %End - virtual bool setVariantValue( const QVariant &value, const QString &dynamicKeyPart = QString() ) const /Deprecated/; + bool setVariantValue( const QVariant &value, const QString &dynamicKeyPart = QString() ) const; %Docstring Set settings value. :param value: specifies the value to set. :param dynamicKeyPart: specifies the dynamic part of the settings key. - -.. deprecated:: QGIS 3.26 - use setVariantValuePrivate or an implementation setValue instead %End - virtual bool setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const /Deprecated/; + bool setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const; %Docstring Set settings value. +This should be called from any implementation as it takes care of actually calling QSettings :param value: specifies the value to set. :param dynamicKeyPartList: specifies the list of dynamic parts of the settings key. - -.. deprecated:: QGIS 3.26 - use setVariantValuePrivate or an implementation setValue instead %End QVariant valueAsVariant( const QString &dynamicKeyPart = QString() ) const; @@ -330,31 +335,23 @@ Returns the parent tree element .. versionadded:: 3.30 %End - protected: - - bool setVariantValuePrivate( const QVariant &value, const QStringList &dynamicKeyPartList = QStringList() ) const; + virtual bool checkValueVariant( const QVariant &value ) const; %Docstring -Sets the settings value with a variant value. -This should be called from any implementation as it takes care of actually calling QSettings - -.. versionadded:: 3.26 +Returns ``True`` if the given ``value`` is valid towards the setting definition %End }; - template -class QgsSettingsEntryByReference : QgsSettingsEntryBase +class QgsSettingsEntryBaseTemplate : QgsSettingsEntryBase { %Docstring(signature="appended") -Base abstract class for settings entry which are passed by reference +Base abstract class for settings entries with typed get and set methods .. seealso:: :py:class:`QgsSettingsEntryBase` -.. seealso:: :py:class:`QgsSettingsEntryByValue` - -.. versionadded:: 3.26 +.. versionadded:: 3.32 %End %TypeHeaderCode @@ -362,13 +359,13 @@ Base abstract class for settings entry which are passed by reference %End public: - QgsSettingsEntryByReference( const QString &name, - QgsSettingsTreeNode *parent, - const T &defaultValue, - const QString &description = QString(), - Qgis::SettingsOptions options = Qgis::SettingsOptions() ); + QgsSettingsEntryBaseTemplate( const QString &name, + QgsSettingsTreeNode *parent, + const QVariant &defaultValue, + const QString &description = QString(), + Qgis::SettingsOptions options = Qgis::SettingsOptions() ); %Docstring -Constructor for QgsSettingsEntryByReference. +Constructor for :py:class:`QgsSettingsEntryByReference`. :param name: specifies the key of the settings. :param parent: specifies the parent in the tree of settings. @@ -381,13 +378,13 @@ Constructor for QgsSettingsEntryByReference. .. versionadded:: 3.30 %End - QgsSettingsEntryByReference( const QString &key, - const QString §ion, - const T &defaultValue, - const QString &description = QString(), - Qgis::SettingsOptions options = Qgis::SettingsOptions() ); + QgsSettingsEntryBaseTemplate( const QString &key, + const QString §ion, + const QVariant &defaultValue, + const QString &description = QString(), + Qgis::SettingsOptions options = Qgis::SettingsOptions() ); %Docstring -Constructor for QgsSettingsEntryByReference. +Constructor for :py:class:`QgsSettingsEntryByReference`. :param key: specifies the key of the settings. :param section: specifies the section. @@ -424,22 +421,6 @@ Returns the settings value with a ``defaultValueOverride`` and with an optional Returns the settings value with a ``defaultValueOverride`` for the ``dynamicKeyPartList`` %End - T value( const QString &dynamicKeyPart, bool useDefaultValueOverride, const T &defaultValueOverride ) const /Deprecated/; -%Docstring -Returns the settings value for the ``dynamicKeyPart`` and with a ``defaultValueOverride`` - -.. deprecated:: QGIS 3.26 - use valueAsVariantWithDefaultOverride instead -%End - - T value( const QStringList &dynamicKeyPartList, bool useDefaultValueOverride, const T &defaultValueOverride ) const /Deprecated/; -%Docstring -Returns the settings value for the ``dynamicKeyPartList`` and with a ``defaultValueOverride`` - -.. deprecated:: QGIS 3.26 - use valueAsVariantWithDefaultOverride instead -%End - bool setValue( const T &value, const QString &dynamicKeyPart = QString() ) const; %Docstring Set settings value. @@ -473,15 +454,17 @@ Returns the former value Returns the current value (or default) if there is no former value. %End - protected: - bool setValuePrivate( const T &value, const QStringList &dynamicKeyPartList ) const; -%Docstring -Sets the settings value with an optional list of dynamic parts -%End + virtual bool checkValueVariant( const QVariant &value ) const; virtual T convertFromVariant( const QVariant &value ) const = 0; %Docstring Converts the variant value to the value type of the setting +%End + + protected: + virtual bool setValuePrivate( const T &value, const QStringList &dynamicKeyPartList ) const; +%Docstring +Sets the settings value with an optional list of dynamic parts %End virtual QVariant convertToVariant( const T &value ) const; @@ -489,152 +472,13 @@ Converts the variant value to the value type of the setting Converts the value to a variant %End - virtual bool checkValue( const T &value ) const; + virtual bool checkValuePrivate( const T &value ) const; %Docstring Check if the value is valid %End }; -template -class QgsSettingsEntryByValue : QgsSettingsEntryBase -{ -%Docstring(signature="appended") - -Base abstract class for settings entry which are passed by value - -.. seealso:: :py:class:`QgsSettingsEntryBase` - -.. seealso:: :py:class:`QgsSettingsEntryByReference` - -.. versionadded:: 3.26 -%End - -%TypeHeaderCode -#include "qgssettingsentry.h" -%End - public: - - QgsSettingsEntryByValue( const QString &key, QgsSettingsTreeNode *parent, QVariant defaultValue, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ); -%Docstring -Constructor for QgsSettingsEntryByValue. - -:param key: specifies the key of the settings. -:param parent: specifies the parent in the tree of settings. -:param defaultValue: specifies the default value for the settings entry. -:param description: specifies a description for the settings entry. -:param options: specifies the options for the settings entry. - -:raises QgsSettingsException: if the number of given parent named items doesn't match the complete key definition -%End - - QgsSettingsEntryByValue( const QString &key, const QString §ion, QVariant defaultValue, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ); -%Docstring -Constructor for QgsSettingsEntryByValue. - -:param key: specifies the key of the settings. -:param section: specifies the section. -:param defaultValue: specifies the default value for the settings entry. -:param description: specifies a description for the settings entry. -:param options: specifies the options for the settings entry. -%End - - virtual Qgis::SettingsType settingsType() const = 0; - - T value( const QString &dynamicKeyPart = QString() ) const; -%Docstring -Returns settings value. - -:param dynamicKeyPart: specifies the dynamic part of the settings key. -%End - - T value( const QStringList &dynamicKeyPartList ) const; -%Docstring -Returns settings value. - -:param dynamicKeyPartList: specifies the list of dynamic parts of the settings key. -%End - - T valueWithDefaultOverride( T defaultValueOverride, const QString &dynamicKeyPart = QString() ) const; -%Docstring -Returns the settings value with a ``defaultValueOverride`` and with an optional ``dynamicKeyPart`` -%End - - T valueWithDefaultOverride( T defaultValueOverride, const QStringList &dynamicKeyPartList ) const; -%Docstring -Returns the settings value with a ``defaultValueOverride`` for the ``dynamicKeyPartList`` -%End - - T value( const QString &dynamicKeyPart, bool useDefaultValueOverride, T defaultValueOverride ) const /Deprecated/; -%Docstring -Returns the settings value for the ``dynamicKeyPart`` and with a ``defaultValueOverride`` - -.. deprecated:: QGIS 3.26 - use valueWithDefaultOverride instead -%End - - T value( const QStringList &dynamicKeyPartList, bool useDefaultValueOverride, T defaultValueOverride ) const /Deprecated/; -%Docstring -Returns the settings value for the ``dynamicKeyPartList`` and with a ``defaultValueOverride`` - -.. deprecated:: QGIS 3.26 - use valueWithDefaultOverride instead -%End - - bool setValue( T value, const QString &dynamicKeyPart = QString() ) const; -%Docstring -Set settings value. - -:param value: specifies the value to set. -:param dynamicKeyPart: specifies the dynamic part of the settings key. -%End - - bool setValue( T value, const QStringList &dynamicKeyPartList ) const; -%Docstring -Set settings value. - -:param value: specifies the value to set. -:param dynamicKeyPartList: specifies the list of dynamic parts of the settings key. -%End - - T defaultValue() const; -%Docstring -Returns settings default value. -%End - - T formerValue( const QString &dynamicKeyPart = QString() ) const; -%Docstring -Returns the former value -Returns the current value (or default) if there is no former value. -%End - - T formerValue( const QStringList &dynamicKeyPartList ) const; -%Docstring -Returns the former value -Returns the current value (or default) if there is no former value. -%End - - protected: - virtual bool setValuePrivate( T value, const QStringList &dynamicKeyPartList ) const; -%Docstring -Sets the settings value with an optional list of dynamic parts -%End - - virtual T convertFromVariant( const QVariant &value ) const = 0; -%Docstring -Converts the variant value to the value type of the setting -%End - - virtual QVariant convertToVariant( T value ) const; -%Docstring -Converts the value to a variant -%End - - virtual bool checkValue( T value ) const; -%Docstring -Check if the value is valid -%End -}; /************************************************************************ diff --git a/python/core/auto_generated/settings/qgssettingsentryimpl.sip.in b/python/core/auto_generated/settings/qgssettingsentryimpl.sip.in index d0e0480be7a..0b465263daf 100644 --- a/python/core/auto_generated/settings/qgssettingsentryimpl.sip.in +++ b/python/core/auto_generated/settings/qgssettingsentryimpl.sip.in @@ -10,9 +10,9 @@ -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQVariantBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQVariantBase; -class QgsSettingsEntryVariant : QgsSettingsEntryByReferenceQVariantBase +class QgsSettingsEntryVariant : QgsSettingsEntryBaseTemplateQVariantBase { %Docstring(signature="appended") @@ -24,7 +24,7 @@ A variant settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQVariantBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQVariantBase; %End public: @@ -107,14 +107,13 @@ Returns settings value. virtual Qgis::SettingsType settingsType() const; - private: virtual QVariant convertFromVariant( const QVariant &value ) const; }; -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQStringBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQStringBase; -class QgsSettingsEntryString : QgsSettingsEntryByReferenceQStringBase +class QgsSettingsEntryString : QgsSettingsEntryBaseTemplateQStringBase { %Docstring(signature="appended") @@ -126,7 +125,7 @@ A string settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQStringBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQStringBase; %End public: @@ -203,18 +202,19 @@ Returns the string minimum length. Returns the string maximum length. By -1 there is no limitation. %End - private: - virtual bool checkValue( const QString &value ) const; - virtual QString convertFromVariant( const QVariant &value ) const; + + private: + virtual bool checkValuePrivate( const QString &value ) const; + }; -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQStringListBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQStringListBase; -class QgsSettingsEntryStringList : QgsSettingsEntryByReferenceQStringListBase +class QgsSettingsEntryStringList : QgsSettingsEntryBaseTemplateQStringListBase { %Docstring(signature="appended") @@ -226,7 +226,7 @@ A string list settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQStringListBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQStringListBase; %End public: @@ -284,16 +284,15 @@ This constructor is intended to be used from plugins. virtual Qgis::SettingsType settingsType() const; - private: virtual QStringList convertFromVariant( const QVariant &value ) const; }; -typedef QgsSettingsEntryByValue QgsSettingsEntryByValueboolBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateboolBase; -class QgsSettingsEntryBool : QgsSettingsEntryByValueboolBase +class QgsSettingsEntryBool : QgsSettingsEntryBaseTemplateboolBase { %Docstring(signature="appended") @@ -305,7 +304,7 @@ A boolean settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByValue QgsSettingsEntryByValueboolBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateboolBase; %End public: @@ -363,16 +362,15 @@ This constructor is intended to be used from plugins. virtual Qgis::SettingsType settingsType() const; - private: virtual bool convertFromVariant( const QVariant &value ) const; }; -typedef QgsSettingsEntryByValue QgsSettingsEntryByValueintBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateintBase; -class QgsSettingsEntryInteger : QgsSettingsEntryByValueintBase +class QgsSettingsEntryInteger : QgsSettingsEntryBaseTemplateintBase { %Docstring(signature="appended") @@ -384,7 +382,7 @@ An integer settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByValue QgsSettingsEntryByValueintBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateintBase; %End public: @@ -463,18 +461,19 @@ Returns the minimum value. Returns the maximum value. %End - private: - virtual bool checkValue( int value ) const; - virtual int convertFromVariant( const QVariant &value ) const; + + private: + virtual bool checkValuePrivate( const int &value ) const; + }; -typedef QgsSettingsEntryByValue QgsSettingsEntryByValuedoubleBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplatedoubleBase; -class QgsSettingsEntryDouble : QgsSettingsEntryByValuedoubleBase +class QgsSettingsEntryDouble : QgsSettingsEntryBaseTemplatedoubleBase { %Docstring(signature="appended") @@ -486,7 +485,7 @@ A double settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByValue QgsSettingsEntryByValuedoubleBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplatedoubleBase; %End public: @@ -586,19 +585,20 @@ displayHintDecimals The number of decimals that should be shown in the Gui. Returns how much decimals should be shown in the Gui. %End - private: - virtual bool checkValue( double value ) const; - virtual double convertFromVariant( const QVariant &value ) const; + + private: + virtual bool checkValuePrivate( const double &value ) const; + }; -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQColorBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQColorBase; -class QgsSettingsEntryColor : QgsSettingsEntryByReferenceQColorBase +class QgsSettingsEntryColor : QgsSettingsEntryBaseTemplateQColorBase { %Docstring(signature="appended") @@ -610,7 +610,7 @@ A color settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQColorBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQColorBase; %End public: @@ -681,18 +681,18 @@ Returns ``True`` if transparency is allowed for the color - - private: virtual QColor convertFromVariant( const QVariant &value ) const; - virtual bool checkValue( const QColor &value ) const; + + private: + virtual bool checkValuePrivate( const QColor &value ) const; }; -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQVariantMapBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQVariantMapBase; -class QgsSettingsEntryVariantMap : QgsSettingsEntryByReferenceQVariantMapBase +class QgsSettingsEntryVariantMap : QgsSettingsEntryBaseTemplateQVariantMapBase { %Docstring(signature="appended") @@ -704,7 +704,7 @@ A string list settings entry. %TypeHeaderCode #include "qgssettingsentryimpl.h" #include "qgssettingsentry.h" -typedef QgsSettingsEntryByReference QgsSettingsEntryByReferenceQVariantMapBase; +typedef QgsSettingsEntryBaseTemplate QgsSettingsEntryBaseTemplateQVariantMapBase; %End public: @@ -762,11 +762,11 @@ This constructor is intended to be used from plugins. virtual Qgis::SettingsType settingsType() const; - private: virtual QVariantMap convertFromVariant( const QVariant &value ) const; }; + /************************************************************************ * This file has been generated automatically from * * * diff --git a/python/gui/auto_additions/qgssettingstreemodel.py b/python/gui/auto_additions/qgssettingstreemodel.py new file mode 100644 index 00000000000..c0416ba40a5 --- /dev/null +++ b/python/gui/auto_additions/qgssettingstreemodel.py @@ -0,0 +1,7 @@ +# The following has been generated automatically from src/gui/settings/qgssettingstreemodel.h +# monkey patching scoped based enum +QgsSettingsTreeModel.Column.Name.__doc__ = "Name" +QgsSettingsTreeModel.Column.Value.__doc__ = "Value" +QgsSettingsTreeModel.Column.Description.__doc__ = "Description" +QgsSettingsTreeModel.Column.__doc__ = 'Columns\n\n' + '* ``Name``: ' + QgsSettingsTreeModel.Column.Name.__doc__ + '\n' + '* ``Value``: ' + QgsSettingsTreeModel.Column.Value.__doc__ + '\n' + '* ``Description``: ' + QgsSettingsTreeModel.Column.Description.__doc__ +# -- diff --git a/python/gui/auto_generated/qgsgui.sip.in b/python/gui/auto_generated/qgsgui.sip.in index 6907c2f9a46..dc59e717514 100644 --- a/python/gui/auto_generated/qgsgui.sip.in +++ b/python/gui/auto_generated/qgsgui.sip.in @@ -10,7 +10,6 @@ - class QgsGui : QObject { %Docstring(signature="appended") @@ -167,6 +166,13 @@ Returns the global relation widget registry, used for managing all known relatio Returns the global history provider registry, used for tracking history providers. .. versionadded:: 3.24 +%End + + static QgsSettingsEditorWidgetRegistry *settingsEditorWidgetRegistry() /KeepReference/; +%Docstring +Returns the registry of settings editors. + +.. versionadded:: 3.32 %End static void enableAutoGeometryRestore( QWidget *widget, const QString &key = QString() ); diff --git a/python/gui/auto_generated/qgsoptionsdialoghighlightwidget.sip.in b/python/gui/auto_generated/qgsoptionsdialoghighlightwidget.sip.in index 36bbfca9ad9..b2d3895f8ab 100644 --- a/python/gui/auto_generated/qgsoptionsdialoghighlightwidget.sip.in +++ b/python/gui/auto_generated/qgsoptionsdialoghighlightwidget.sip.in @@ -9,7 +9,9 @@ -class QgsOptionsDialogHighlightWidget : QObject + + +class QgsOptionsDialogHighlightWidget { %Docstring(signature="appended") Container for a widget to be used to search text in the option dialog @@ -34,6 +36,8 @@ For instance a :py:class:`QgsOptionsDialogHighlightButton` for button. for the given widget. %End + virtual ~QgsOptionsDialogHighlightWidget(); + bool isValid(); %Docstring Returns if it valid: if the widget type is handled and if the widget is not still available @@ -51,11 +55,6 @@ search for a text pattern and highlight the widget if the text is found Returns the widget %End - - virtual bool eventFilter( QObject *obj, QEvent *event ); - - - protected: virtual bool searchText( const QString &text ) = 0; diff --git a/python/gui/auto_generated/settings/qgssettingseditorwidgetregistry.sip.in b/python/gui/auto_generated/settings/qgssettingseditorwidgetregistry.sip.in new file mode 100644 index 00000000000..ac0c8882e21 --- /dev/null +++ b/python/gui/auto_generated/settings/qgssettingseditorwidgetregistry.sip.in @@ -0,0 +1,55 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingseditorwidgetregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + +class QgsSettingsEditorWidgetRegistry +{ +%Docstring(signature="appended") +This class manages editor widgets for settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetregistry.h" +%End + public: + QgsSettingsEditorWidgetRegistry(); +%Docstring +Constructor +%End + ~QgsSettingsEditorWidgetRegistry(); + + bool addWrapper( QgsSettingsEditorWidgetWrapper *wrapper /Transfer/ ); +%Docstring +Adds an editor widget ``wrapper`` to the registry +Returns ``False`` if an editor widget with same id already exists. +%End + + QgsSettingsEditorWidgetWrapper *createWrapper( const QString &id, QObject *parent ) const; +%Docstring +Returns a new instance of the editor widget for the given ``id`` +%End + + QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent = 0 ) const /Factory/; +%Docstring +Creates an editor widget for the given ``setting`` using the corresponding registered wrapper +%End + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingseditorwidgetregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/settings/qgssettingseditorwidgetwrapper.sip.in b/python/gui/auto_generated/settings/qgssettingseditorwidgetwrapper.sip.in new file mode 100644 index 00000000000..6d55ca21645 --- /dev/null +++ b/python/gui/auto_generated/settings/qgssettingseditorwidgetwrapper.sip.in @@ -0,0 +1,107 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingseditorwidgetwrapper.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + +class QgsSettingsEditorWidgetWrapper : QObject +{ +%Docstring(signature="appended") +Base class for settings editor wrappers + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetwrapper.h" +%End + public: + static QgsSettingsEditorWidgetWrapper *fromWidget( const QWidget *widget ) /Factory/; +%Docstring +Creates a wrapper from the definition stored in a ``widget`` created by :py:func:`~QgsSettingsEditorWidgetWrapper.createEditor` +%End + + QgsSettingsEditorWidgetWrapper( QObject *parent = 0 ); +%Docstring +Constructor +%End + + virtual ~QgsSettingsEditorWidgetWrapper(); + + virtual QString id() const = 0; +%Docstring +This id of the type of settings it handles + +.. note:: + + This mostly correspond to the content of :py:class:`Qgis`.SettingsType but it's a string since custom Python implementation are possible. +%End + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const = 0; +%Docstring +Creates a new instance of the editor wrapper so it can be configured for a widget and a setting +%End + + QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList(), QWidget *parent = 0 ); +%Docstring +Creates the editor widget for the given ``setting`` +%End + + bool configureEditor( QWidget *editor, const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList() ); +%Docstring +Configures the ``editor`` according the setting +%End + + virtual bool setWidgetFromSetting() const = 0; +%Docstring +Sets the widget value from the setting value +The wrapper must be configured before calling this medthod +%End + + virtual bool setSettingFromWidget() const = 0; +%Docstring +Sets the setting value from the widget value +The wrapper must be configured before calling this medthod +%End + + virtual QVariant variantValueFromWidget() const = 0; +%Docstring +Returns the value from the widget as a variant +The wrapper must be configured before calling this medthod +%End + + virtual void setWidgetFromVariant( const QVariant &value ) const = 0; +%Docstring +Sets the ``value`` of the widget +The wrapper must be configured before calling this medthod +%End + + + protected: + virtual QWidget *createEditorPrivate( QWidget *parent = 0 ) const = 0; +%Docstring +Creates the widgets +%End + + virtual bool configureEditorPrivate( QWidget *editor, const QgsSettingsEntryBase *setting ) = 0; +%Docstring +Configures an existing ``editor`` widget +%End + +}; + + + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingseditorwidgetwrapper.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/settings/qgssettingseditorwidgetwrapperimpl.sip.in b/python/gui/auto_generated/settings/qgssettingseditorwidgetwrapperimpl.sip.in new file mode 100644 index 00000000000..0fdf25d3540 --- /dev/null +++ b/python/gui/auto_generated/settings/qgssettingseditorwidgetwrapperimpl.sip.in @@ -0,0 +1,275 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingseditorwidgetwrapperimpl.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + + + + +template +class QgsSettingsEditorWidgetWrapperTemplate : QgsSettingsEditorWidgetWrapper +{ +%Docstring(signature="appended") +This class is a base factory of editor for settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetwrapperimpl.h" +%End + public: + QgsSettingsEditorWidgetWrapperTemplate( QObject *parent = 0 ); +%Docstring +Constructor +%End + virtual QString id() const = 0; + + virtual bool setWidgetFromSetting() const; + + virtual bool setSettingFromWidget() const = 0; + + virtual void setWidgetFromVariant( const QVariant &value ) const; + + virtual bool setWidgetValue( const U &value ) const = 0; +%Docstring +Sets the widget value +%End + + virtual QVariant variantValueFromWidget() const; + + virtual U valueFromWidget() const = 0; +%Docstring +Returns the widget value +%End + + V *editor() const; +%Docstring +Returns the editor +%End + + const T *setting() const; +%Docstring +Returns the setting +%End + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const = 0; + + protected: + virtual QWidget *createEditorPrivate( QWidget *parent = 0 ) const; + + virtual bool configureEditorPrivate( QWidget *editor, const QgsSettingsEntryBase *setting ); + + virtual void configureEditorPrivateImplementation(); +%Docstring +To be re-implemented to implemeent type specific configuration (e.g. opacity for colors) +%End + +}; + + + +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryStringQLineEditQStringBase; + +class QgsSettingsStringEditorWidgetWrapper : QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryStringQLineEditQStringBase +{ +%Docstring(signature="appended") +This class is a factory of editor for string settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetwrapperimpl.h" +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryStringQLineEditQStringBase; +%End + public: + QgsSettingsStringEditorWidgetWrapper( QObject *parent = 0 ); +%Docstring +Constructor +%End + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const; + + virtual QString id() const; + + + virtual bool setSettingFromWidget() const; + + + virtual QString valueFromWidget() const; + + + virtual bool setWidgetValue( const QString &value ) const; + +}; + + +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryBoolQCheckBoxboolBase; + +class QgsSettingsBoolEditorWidgetWrapper : QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryBoolQCheckBoxboolBase +{ +%Docstring(signature="appended") +This class is a factory of editor for boolean settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetwrapperimpl.h" +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryBoolQCheckBoxboolBase; +%End + public: + QgsSettingsBoolEditorWidgetWrapper( QObject *parent = 0 ); +%Docstring +Constructor +%End + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const; + + virtual QString id() const; + + + virtual bool setSettingFromWidget() const; + + + virtual bool valueFromWidget() const; + + + virtual bool setWidgetValue( const bool &value ) const; + +}; + + +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryIntegerQSpinBoxintBase; + +class QgsSettingsIntegerEditorWidgetWrapper : QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryIntegerQSpinBoxintBase +{ +%Docstring(signature="appended") +This class is a factory of editor for integer settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetwrapperimpl.h" +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryIntegerQSpinBoxintBase; +%End + public: + QgsSettingsIntegerEditorWidgetWrapper( QObject *parent = 0 ); +%Docstring +Constructor +%End + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const; + + virtual QString id() const; + + + virtual bool setSettingFromWidget() const; + + + virtual int valueFromWidget() const; + + + virtual bool setWidgetValue( const int &value ) const; + +}; + + + +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryDoubleQDoubleSpinBoxdoubleBase; + +class QgsSettingsDoubleEditorWidgetWrapper : QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryDoubleQDoubleSpinBoxdoubleBase +{ +%Docstring(signature="appended") +This class is a factory of editor for double settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetwrapperimpl.h" +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryDoubleQDoubleSpinBoxdoubleBase; +%End + public: + QgsSettingsDoubleEditorWidgetWrapper( QObject *parent = 0 ); +%Docstring +Constructor +%End + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const; + + virtual QString id() const; + + + virtual bool setSettingFromWidget() const; + + + virtual double valueFromWidget() const; + + + virtual bool setWidgetValue( const double &value ) const; + +}; + + + +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryColorQgsColorButtonQColorBase; + +class QgsSettingsColorEditorWidgetWrapper : QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryColorQgsColorButtonQColorBase +{ +%Docstring(signature="appended") +This class is a factory of editor for color settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingseditorwidgetwrapperimpl.h" +typedef QgsSettingsEditorWidgetWrapperTemplate QgsSettingsEditorWidgetWrapperTemplateQgsSettingsEntryColorQgsColorButtonQColorBase; +%End + public: + QgsSettingsColorEditorWidgetWrapper( QObject *parent = 0 ); +%Docstring +Constructor +%End + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const; + + virtual QString id() const; + + + virtual bool setSettingFromWidget() const; + + + virtual QColor valueFromWidget() const; + + + virtual bool setWidgetValue( const QColor &value ) const; + + + virtual void configureEditorPrivateImplementation(); + +}; + + + + + + + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingseditorwidgetwrapperimpl.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/settings/qgssettingstreemodel.sip.in b/python/gui/auto_generated/settings/qgssettingstreemodel.sip.in new file mode 100644 index 00000000000..f16d6bf0250 --- /dev/null +++ b/python/gui/auto_generated/settings/qgssettingstreemodel.sip.in @@ -0,0 +1,111 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingstreemodel.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + + + + +class QgsSettingsTreeModel : QAbstractItemModel +{ +%Docstring(signature="appended") +:py:class:`QgsSettingsTreeModel` is a tree model for the settings tree. + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingstreemodel.h" +%End + public: + + enum class Column + { + Name, + Value, + Description, + }; + + QgsSettingsTreeModel( QgsSettingsTreeNode *rootNode = 0, QObject *parent = 0 ); +%Docstring +Constructor +%End + + ~QgsSettingsTreeModel(); + + void applyChanges(); +%Docstring +Apply pending changes in the model to the corresponding settings +%End + + + + + virtual QModelIndex index( int row, int column, const QModelIndex &parent ) const; + + virtual QModelIndex parent( const QModelIndex &child ) const; + + virtual int rowCount( const QModelIndex &parent ) const; + + virtual int columnCount( const QModelIndex &parent ) const; + + virtual QVariant data( const QModelIndex &index, int role ) const; + + virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const; + + virtual Qt::ItemFlags flags( const QModelIndex &index ) const; + + virtual bool setData( const QModelIndex &index, const QVariant &value, int role ); + + +}; + +class QgsSettingsTreeProxyModel : QSortFilterProxyModel +{ +%Docstring(signature="appended") +:py:class:`QgsSettingsTreeProxyModel` allows filtering the settings tree + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingstreemodel.h" +%End + public: + QgsSettingsTreeProxyModel( QgsSettingsTreeNode *rootNode = 0, QObject *parent = 0 ); +%Docstring +Constructor +%End + + void applyChanges(); +%Docstring +Apply pending changes in the model to the corresponding settings +%End + + public slots: + void setFilterText( const QString &filterText = QString() ); +%Docstring +Sets the filter text +%End + + + protected: + virtual bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const; + + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingstreemodel.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/settings/qgssettingstreewidget.sip.in b/python/gui/auto_generated/settings/qgssettingstreewidget.sip.in new file mode 100644 index 00000000000..2027bf167cb --- /dev/null +++ b/python/gui/auto_generated/settings/qgssettingstreewidget.sip.in @@ -0,0 +1,53 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingstreewidget.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + + + +class QgsSettingsTreeWidget : QWidget, QgsOptionsDialogHighlightWidget +{ +%Docstring(signature="appended") +:py:class:`QgsSettingsTreeWidget` is a widget with the settings tree to visualize, search and edit settings + +.. versionadded:: 3.32 +%End + +%TypeHeaderCode +#include "qgssettingstreewidget.h" +%End + public: + explicit QgsSettingsTreeWidget( QWidget *parent = 0 ); +%Docstring +Constructor +%End + + + void applyChanges() const; +%Docstring +Apply changes to settings value +%End + + protected: + virtual bool searchText( const QString &text ); + + virtual bool highlightText( const QString &text ); + + virtual void reset(); + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/settings/qgssettingstreewidget.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/gui_auto.sip b/python/gui/gui_auto.sip index f3e3b246549..ce2f6c1db7f 100644 --- a/python/gui/gui_auto.sip +++ b/python/gui/gui_auto.sip @@ -487,7 +487,12 @@ %Include auto_generated/symbology/qgsvectorfieldsymbollayerwidget.sip %Include auto_generated/sensor/qgssensorguiregistry.sip %Include auto_generated/sensor/qgssensorwidget.sip +%Include auto_generated/settings/qgssettingseditorwidgetwrapper.sip +%Include auto_generated/settings/qgssettingseditorwidgetwrapperimpl.sip +%Include auto_generated/settings/qgssettingseditorwidgetregistry.sip %Include auto_generated/settings/qgssettingsregistrygui.sip +%Include auto_generated/settings/qgssettingstreemodel.sip +%Include auto_generated/settings/qgssettingstreewidget.sip %Include auto_generated/tableeditor/qgstableeditordialog.sip %Include auto_generated/tableeditor/qgstableeditorwidget.sip %Include auto_generated/vectortile/qgsvectortilelayerproperties.sip diff --git a/python/sipify.yaml b/python/sipify.yaml index 3f3f683c5b7..608a7e54336 100644 --- a/python/sipify.yaml +++ b/python/sipify.yaml @@ -2,8 +2,7 @@ class_headerfile: QgsAbstractFeatureIteratorFromSource: qgsfeatureiterator.h - QgsSettingsEntryByReference: qgssettingsentry.h - QgsSettingsEntryByValue: qgssettingsentry.h + QgsSettingsEntryBaseTemplate: qgssettingsentry.h no_export_macro: diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 418ff028531..07bf411ee3f 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -284,7 +284,7 @@ set(QGIS_APP_SRCS pluginmanager/qgspluginsortfilterproxymodel.cpp pluginmanager/qgspluginitemdelegate.cpp - qgssettingstreewidget.cpp + qgssettingstreewidgetold.cpp qgssettingsregistryapp.cpp qgsvariantdelegate.cpp qgscrashhandler.cpp @@ -536,6 +536,7 @@ target_include_directories(qgis_app PUBLIC ${CMAKE_SOURCE_DIR}/src/app/locator ${CMAKE_SOURCE_DIR}/src/app/options ${CMAKE_SOURCE_DIR}/src/app/pointcloud + ${CMAKE_SOURCE_DIR}/src/app/settings ${CMAKE_SOURCE_DIR}/src/app/vectortile ${CMAKE_SOURCE_DIR}/src/plugins ${CMAKE_SOURCE_DIR}/src/python diff --git a/src/app/options/qgsadvancedoptions.cpp b/src/app/options/qgsadvancedoptions.cpp index 0b248e5bea8..1e4b650e3b1 100644 --- a/src/app/options/qgsadvancedoptions.cpp +++ b/src/app/options/qgsadvancedoptions.cpp @@ -14,26 +14,47 @@ ***************************************************************************/ #include "qgsadvancedoptions.h" +#include "qgssettingstreewidget.h" +#include "qgssettingstreewidgetold.h" #include "qgsapplication.h" -#include "qgssettings.h" #include "qgis.h" // // QgsAdvancedSettingsWidget // +const QgsSettingsEntryBool *QgsAdvancedSettingsWidget::settingsUseNewTreeWidget = new QgsSettingsEntryBool( QStringLiteral( "use-new-widget" ), sTreeSettings, true, QStringLiteral( "Use new settings widget" ) ); +const QgsSettingsEntryBool *QgsAdvancedSettingsWidget::settingsShowWarning = new QgsSettingsEntryBool( QStringLiteral( "show-warning" ), sTreeSettings, true, QStringLiteral( "Show warning before opening the settings tree" ) ); + QgsAdvancedSettingsWidget::QgsAdvancedSettingsWidget( QWidget *parent ) : QgsOptionsPageWidget( parent ) { setupUi( this ); + mUseNewSettingsTree->setChecked( settingsUseNewTreeWidget->value() ); + layout()->setContentsMargins( 0, 0, 0, 0 ); - connect( mAdvancedSettingsEnableButton, &QPushButton::clicked, this, [ = ] + if ( !settingsShowWarning->value() ) { - mAdvancedSettingsEditor->show(); mAdvancedSettingsWarning->hide(); - } ); + bool newTree = settingsUseNewTreeWidget->value(); + createSettingsTreeWidget( newTree, !newTree, false ); + } + else + { + createSettingsTreeWidget( true, true, true ); + + connect( mAdvancedSettingsEnableButton, &QPushButton::clicked, this, [ = ] + { + settingsUseNewTreeWidget->setValue( mUseNewSettingsTree->isChecked() ); + mAdvancedSettingsWarning->hide(); + if ( settingsUseNewTreeWidget->value() ) + mTreeWidget->show(); + else + mTreeWidgetOld->show(); + } ); + } } QgsAdvancedSettingsWidget::~QgsAdvancedSettingsWidget() @@ -42,12 +63,30 @@ QgsAdvancedSettingsWidget::~QgsAdvancedSettingsWidget() void QgsAdvancedSettingsWidget::apply() { -// nothing to do -- mAdvancedSettingsEditor applies changes immediately + // the old settings editor applies changes immediately + // new settings tree is performing changes on apply + if ( mTreeWidget ) + mTreeWidget->applyChanges(); + } -QgsSettingsTreeWidget *QgsAdvancedSettingsWidget::settingsTree() +void QgsAdvancedSettingsWidget::createSettingsTreeWidget( bool newWidget, bool oldWidget, bool hide ) { - return mAdvancedSettingsEditor; + if ( newWidget ) + { + mTreeWidget = new QgsSettingsTreeWidget( this ); + mGroupBox->layout()->addWidget( mTreeWidget ); + if ( hide ) + mTreeWidget->hide(); + } + + if ( oldWidget ) + { + mTreeWidgetOld = new QgsSettingsTreeWidgetOld( this ); + mGroupBox->layout()->addWidget( mTreeWidgetOld ); + if ( hide ) + mTreeWidgetOld->hide(); + } } // diff --git a/src/app/options/qgsadvancedoptions.h b/src/app/options/qgsadvancedoptions.h index 239d9925031..856c7b43cb4 100644 --- a/src/app/options/qgsadvancedoptions.h +++ b/src/app/options/qgsadvancedoptions.h @@ -17,8 +17,11 @@ #include "ui_qgsadvancedsettingswidget.h" #include "qgsoptionswidgetfactory.h" -#include "qgssettings.h" -#include "qgssettingstreewidget.h" +#include "qgssettingstree.h" +#include "qgssettingsentryimpl.h" + +class QgsSettingsTreeWidget; +class QgsSettingsTreeWidgetOld; /** * \ingroup app @@ -33,6 +36,11 @@ class QgsAdvancedSettingsWidget : public QgsOptionsPageWidget, private Ui::QgsAd public: + static inline QgsSettingsTreeNode *sTreeSettings = QgsSettingsTree::sTreeApp->createChildNode( QStringLiteral( "settings" ) ); + static const QgsSettingsEntryBool *settingsUseNewTreeWidget; + static const QgsSettingsEntryBool *settingsShowWarning; + + /** * Constructor for QgsAdvancedSettingsWidget with the specified \a parent widget. */ @@ -40,11 +48,11 @@ class QgsAdvancedSettingsWidget : public QgsOptionsPageWidget, private Ui::QgsAd ~QgsAdvancedSettingsWidget() override; void apply() override; - QgsSettingsTreeWidget *settingsTree(); - private: + void createSettingsTreeWidget( bool newWidget, bool oldWidget, bool hide ); - QgsSettings mSettings; + QgsSettingsTreeWidget *mTreeWidget = nullptr; + QgsSettingsTreeWidgetOld *mTreeWidgetOld = nullptr; }; diff --git a/src/app/options/qgsoptions.cpp b/src/app/options/qgsoptions.cpp index b4a0ecae825..ecf63b938aa 100644 --- a/src/app/options/qgsoptions.cpp +++ b/src/app/options/qgsoptions.cpp @@ -1182,11 +1182,6 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QListtitle(), factory->title(), factory->icon(), page, factory->path(), factory->key() ); else insertPage( factory->title(), factory->title(), factory->icon(), page, beforePage, factory->path(), factory->key() ); - - if ( QgsAdvancedSettingsWidget *advancedPage = qobject_cast< QgsAdvancedSettingsWidget * >( page ) ) - { - advancedPage->settingsTree()->setSettingsObject( mSettings ); - } } if ( mOptTreeView ) diff --git a/src/app/qgssettingstreewidget.cpp b/src/app/qgssettingstreewidgetold.cpp similarity index 80% rename from src/app/qgssettingstreewidget.cpp rename to src/app/qgssettingstreewidgetold.cpp index 891deef5abd..f9359e6613e 100644 --- a/src/app/qgssettingstreewidget.cpp +++ b/src/app/qgssettingstreewidgetold.cpp @@ -41,7 +41,7 @@ #include #include -#include "qgssettingstreewidget.h" +#include "qgssettingstreewidgetold.h" #include "qgsvariantdelegate.h" #include "qgslogger.h" #include "qgssettings.h" @@ -51,7 +51,7 @@ #include #include -QgsSettingsTreeWidget::QgsSettingsTreeWidget( QWidget *parent ) +QgsSettingsTreeWidgetOld::QgsSettingsTreeWidgetOld( QWidget *parent ) : QTreeWidget( parent ) { setItemDelegate( new QgsVariantDelegate( this ) ); @@ -72,45 +72,25 @@ QgsSettingsTreeWidget::QgsSettingsTreeWidget( QWidget *parent ) setEditTriggers( QAbstractItemView::AllEditTriggers ); - connect( &mRefreshTimer, &QTimer::timeout, this, &QgsSettingsTreeWidget::maybeRefresh ); + connect( &mRefreshTimer, &QTimer::timeout, this, &QgsSettingsTreeWidgetOld::maybeRefresh ); setContextMenuPolicy( Qt::CustomContextMenu ); - connect( this, &QTreeWidget::customContextMenuRequested, this, &QgsSettingsTreeWidget::showContextMenu ); + connect( this, &QTreeWidget::customContextMenuRequested, this, &QgsSettingsTreeWidgetOld::showContextMenu ); mContextMenu = new QMenu( this ); } -void QgsSettingsTreeWidget::setSettingsObject( QgsSettings *settings ) -{ - mSettings = settings; - clear(); - - if ( mSettings ) - { - mSettings->setParent( this ); - if ( isVisible() ) - refresh(); - if ( mAutoRefresh ) - mRefreshTimer.start(); - } - else - { - mRefreshTimer.stop(); - } -} - -QSize QgsSettingsTreeWidget::sizeHint() const +QSize QgsSettingsTreeWidgetOld::sizeHint() const { return QSize( 800, 600 ); } -void QgsSettingsTreeWidget::setAutoRefresh( bool autoRefresh ) +void QgsSettingsTreeWidgetOld::setAutoRefresh( bool autoRefresh ) { mAutoRefresh = autoRefresh; if ( mAutoRefresh ) { maybeRefresh(); - if ( mSettings ) - mRefreshTimer.start(); + mRefreshTimer.start(); } else { @@ -118,29 +98,26 @@ void QgsSettingsTreeWidget::setAutoRefresh( bool autoRefresh ) } } -void QgsSettingsTreeWidget::maybeRefresh() +void QgsSettingsTreeWidgetOld::maybeRefresh() { if ( state() != EditingState ) refresh(); } -void QgsSettingsTreeWidget::refresh() +void QgsSettingsTreeWidgetOld::refresh() { - if ( !mSettings ) - return; - disconnect( this, &QTreeWidget::itemChanged, - this, &QgsSettingsTreeWidget::updateSetting ); + this, &QgsSettingsTreeWidgetOld::updateSetting ); - mSettings->sync(); + mSettings.sync(); // add any settings not in QgsSettings object, so it will show up in the tree view QMap::const_iterator it = mSettingsMap.constBegin(); while ( it != mSettingsMap.constEnd() ) { - if ( ! mSettings->contains( it.key() ) ) + if ( ! mSettings.contains( it.key() ) ) { - mSettings->setValue( it.key(), it.value().at( 3 ) ); + mSettings.setValue( it.key(), it.value().at( 3 ) ); } ++it; } @@ -148,10 +125,10 @@ void QgsSettingsTreeWidget::refresh() updateChildItems( nullptr ); connect( this, &QTreeWidget::itemChanged, - this, &QgsSettingsTreeWidget::updateSetting ); + this, &QgsSettingsTreeWidgetOld::updateSetting ); } -bool QgsSettingsTreeWidget::event( QEvent *event ) +bool QgsSettingsTreeWidgetOld::event( QEvent *event ) { if ( event->type() == QEvent::WindowActivate ) { @@ -161,24 +138,24 @@ bool QgsSettingsTreeWidget::event( QEvent *event ) return QTreeWidget::event( event ); } -void QgsSettingsTreeWidget::showEvent( QShowEvent * ) +void QgsSettingsTreeWidgetOld::showEvent( QShowEvent * ) { const QgsTemporaryCursorOverride waitCursor( Qt::BusyCursor ); refresh(); } -void QgsSettingsTreeWidget::updateSetting( QTreeWidgetItem *item ) +void QgsSettingsTreeWidgetOld::updateSetting( QTreeWidgetItem *item ) { const QString key = itemKey( item ); if ( key.isNull() ) return; - mSettings->setValue( key, item->data( ColumnValue, Qt::UserRole ) ); + mSettings.setValue( key, item->data( ColumnValue, Qt::UserRole ) ); if ( mAutoRefresh ) refresh(); } -void QgsSettingsTreeWidget::showContextMenu( QPoint pos ) +void QgsSettingsTreeWidgetOld::showContextMenu( QPoint pos ) { QTreeWidgetItem *item = itemAt( pos ); if ( !item ) @@ -202,7 +179,7 @@ void QgsSettingsTreeWidget::showContextMenu( QPoint pos ) return; - mSettings->remove( itemPath ); + mSettings.remove( itemPath ); refresh(); } ); @@ -220,7 +197,7 @@ void QgsSettingsTreeWidget::showContextMenu( QPoint pos ) QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes ) return; - mSettings->remove( itemPath ); + mSettings.remove( itemPath ); refresh(); } ); @@ -233,11 +210,11 @@ void QgsSettingsTreeWidget::showContextMenu( QPoint pos ) mContextMenu->exec( mapToGlobal( pos ) ); } -void QgsSettingsTreeWidget::updateChildItems( QTreeWidgetItem *parent ) +void QgsSettingsTreeWidgetOld::updateChildItems( QTreeWidgetItem *parent ) { int dividerIndex = 0; - const auto constChildGroups = mSettings->childGroups(); + const auto constChildGroups = mSettings.childGroups(); for ( const QString &group : constChildGroups ) { QTreeWidgetItem *child = nullptr; @@ -257,12 +234,12 @@ void QgsSettingsTreeWidget::updateChildItems( QTreeWidgetItem *parent ) child->setIcon( ColumnSettings, mGroupIcon ); ++dividerIndex; - mSettings->beginGroup( group ); + mSettings.beginGroup( group ); updateChildItems( child ); - mSettings->endGroup(); + mSettings.endGroup(); } - const auto constChildKeys = mSettings->childKeys(); + const auto constChildKeys = mSettings.childKeys(); for ( const QString &key : constChildKeys ) { QTreeWidgetItem *child = nullptr; @@ -289,7 +266,7 @@ void QgsSettingsTreeWidget::updateChildItems( QTreeWidgetItem *parent ) child = childAt( parent, childIndex ); } - const QVariant value = mSettings->value( key ); + const QVariant value = mSettings.value( key ); if ( value.type() == QVariant::Invalid ) { child->setText( ColumnType, QStringLiteral( "Invalid" ) ); @@ -306,7 +283,7 @@ void QgsSettingsTreeWidget::updateChildItems( QTreeWidgetItem *parent ) delete childAt( parent, dividerIndex ); } -QTreeWidgetItem *QgsSettingsTreeWidget::createItem( const QString &text, +QTreeWidgetItem *QgsSettingsTreeWidgetOld::createItem( const QString &text, QTreeWidgetItem *parent, int index, const bool isGroup ) { QTreeWidgetItem *after = nullptr; @@ -325,7 +302,7 @@ QTreeWidgetItem *QgsSettingsTreeWidget::createItem( const QString &text, item->setData( ColumnSettings, TypeRole, isGroup ? Group : Setting ); - const QString completeSettingsPath = mSettings->group().isEmpty() ? text : mSettings->group() + '/' + text; + const QString completeSettingsPath = mSettings.group().isEmpty() ? text : mSettings.group() + '/' + text; item->setData( ColumnSettings, PathRole, completeSettingsPath ); const QString key = itemKey( item ); @@ -343,7 +320,7 @@ QTreeWidgetItem *QgsSettingsTreeWidget::createItem( const QString &text, return item; } -QString QgsSettingsTreeWidget::itemKey( QTreeWidgetItem *item ) +QString QgsSettingsTreeWidgetOld::itemKey( QTreeWidgetItem *item ) { if ( ! item ) return QString(); @@ -359,7 +336,7 @@ QString QgsSettingsTreeWidget::itemKey( QTreeWidgetItem *item ) return key; } -QTreeWidgetItem *QgsSettingsTreeWidget::childAt( QTreeWidgetItem *parent, int index ) +QTreeWidgetItem *QgsSettingsTreeWidgetOld::childAt( QTreeWidgetItem *parent, int index ) { if ( parent ) return parent->child( index ); @@ -367,7 +344,7 @@ QTreeWidgetItem *QgsSettingsTreeWidget::childAt( QTreeWidgetItem *parent, int in return topLevelItem( index ); } -int QgsSettingsTreeWidget::childCount( QTreeWidgetItem *parent ) +int QgsSettingsTreeWidgetOld::childCount( QTreeWidgetItem *parent ) { if ( parent ) return parent->childCount(); @@ -375,8 +352,8 @@ int QgsSettingsTreeWidget::childCount( QTreeWidgetItem *parent ) return topLevelItemCount(); } -int QgsSettingsTreeWidget::findChild( QTreeWidgetItem *parent, const QString &text, - int startIndex ) +int QgsSettingsTreeWidgetOld::findChild( QTreeWidgetItem *parent, const QString &text, + int startIndex ) { for ( int i = startIndex; i < childCount( parent ); ++i ) { @@ -386,7 +363,7 @@ int QgsSettingsTreeWidget::findChild( QTreeWidgetItem *parent, const QString &te return -1; } -void QgsSettingsTreeWidget::moveItemForward( QTreeWidgetItem *parent, int oldIndex, +void QgsSettingsTreeWidgetOld::moveItemForward( QTreeWidgetItem *parent, int oldIndex, int newIndex ) { for ( int i = 0; i < oldIndex - newIndex; ++i ) diff --git a/src/app/qgssettingstreewidget.h b/src/app/qgssettingstreewidgetold.h similarity index 92% rename from src/app/qgssettingstreewidget.h rename to src/app/qgssettingstreewidgetold.h index b89d0c6a04d..1dff30e8af4 100644 --- a/src/app/qgssettingstreewidget.h +++ b/src/app/qgssettingstreewidgetold.h @@ -38,16 +38,16 @@ ** ****************************************************************************/ -#ifndef QGSSETTINGSTREEWIDGET_H -#define QGSSETTINGSTREEWIDGET_H +#ifndef QGSSETTINGSTREEWIDGETOLD_H +#define QGSSETTINGSTREEWIDGETOLD_H +#include "qgssettings.h" #include #include #include -class QgsSettings; -class QgsSettingsTreeWidget : public QTreeWidget +class QgsSettingsTreeWidgetOld : public QTreeWidget { Q_OBJECT @@ -68,9 +68,8 @@ class QgsSettingsTreeWidget : public QTreeWidget }; Q_ENUM( Type ) - explicit QgsSettingsTreeWidget( QWidget *parent = nullptr ); + explicit QgsSettingsTreeWidgetOld( QWidget *parent = nullptr ); - void setSettingsObject( QgsSettings *mSettings ); QSize sizeHint() const override; void setSettingsMap( QMap< QString, QStringList > &map ) { mSettingsMap = map; } @@ -107,7 +106,7 @@ class QgsSettingsTreeWidget : public QTreeWidget int findChild( QTreeWidgetItem *parent, const QString &text, int startIndex ); void moveItemForward( QTreeWidgetItem *parent, int oldIndex, int newIndex ); - QgsSettings *mSettings = nullptr; + QgsSettings mSettings; QTimer mRefreshTimer; bool mAutoRefresh = false; QIcon mGroupIcon; diff --git a/src/core/settings/qgssettingsentry.cpp b/src/core/settings/qgssettingsentry.cpp index 1b286c117f9..2fd83610740 100644 --- a/src/core/settings/qgssettingsentry.cpp +++ b/src/core/settings/qgssettingsentry.cpp @@ -43,6 +43,11 @@ QgsSettingsEntryBase::~QgsSettingsEntryBase() mParentTreeElement->unregisterChildSetting( this ); } +QString QgsSettingsEntryBase::typeId() const +{ + return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast( settingsType() ) ) ); +} + QString QgsSettingsEntryBase::key( const QString &dynamicKeyPart ) const { @@ -139,15 +144,10 @@ int QgsSettingsEntryBase::section() const bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QString &dynamicKeyPart ) const { - return setVariantValuePrivate( value, dynamicKeyPartToList( dynamicKeyPart ) ); + return setVariantValue( value, dynamicKeyPartToList( dynamicKeyPart ) ); } bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const -{ - return setVariantValuePrivate( value, dynamicKeyPartList ); -} - -bool QgsSettingsEntryBase::setVariantValuePrivate( const QVariant &value, const QStringList &dynamicKeyPartList ) const { if ( mOptions.testFlag( Qgis::SettingsOption::SaveFormerValue ) ) { @@ -243,7 +243,7 @@ bool QgsSettingsEntryBase::copyValueFromKey( const QString &key, const QStringLi if ( settings.contains( oldCompleteKey ) ) { QVariant oldValue = settings.value( oldCompleteKey, mDefaultValue ); - setVariantValuePrivate( oldValue, dynamicKeyPartList ); + setVariantValue( oldValue, dynamicKeyPartList ); if ( removeSettingAtKey ) settings.remove( oldCompleteKey ); return true; diff --git a/src/core/settings/qgssettingsentry.h b/src/core/settings/qgssettingsentry.h index cb02fb189f9..3c04924a106 100644 --- a/src/core/settings/qgssettingsentry.h +++ b/src/core/settings/qgssettingsentry.h @@ -28,6 +28,9 @@ class QgsSettingsTreeNode; +static const inline QMetaEnum sSettingsTypeMetaEnum = QMetaEnum::fromType() SIP_SKIP; + + /** * \ingroup core * \class QgsSettingsEntryBase @@ -118,6 +121,13 @@ class CORE_EXPORT QgsSettingsEntryBase */ virtual ~QgsSettingsEntryBase(); + /** + * Returns the id of the type of settings + * This can be re-implemented in a custom implementation of a setting + * \since QGIS 3.32 + */ + virtual QString typeId() const; + /** * Returns the name of the settings * \since QGIS 3.30 @@ -213,18 +223,16 @@ class CORE_EXPORT QgsSettingsEntryBase * * \param value specifies the value to set. * \param dynamicKeyPart specifies the dynamic part of the settings key. - * \deprecated since QGIS 3.26 use setVariantValuePrivate or an implementation setValue instead */ - Q_DECL_DEPRECATED virtual bool setVariantValue( const QVariant &value, const QString &dynamicKeyPart = QString() ) const SIP_DEPRECATED; + bool setVariantValue( const QVariant &value, const QString &dynamicKeyPart = QString() ) const; /** * Set settings value. - * - * \param value specifies the value to set. + * This should be called from any implementation as it takes care of actually calling QSettings + * \param value specifies the value to set. * \param dynamicKeyPartList specifies the list of dynamic parts of the settings key. - * \deprecated since QGIS 3.26 use setVariantValuePrivate or an implementation setValue instead */ - Q_DECL_DEPRECATED virtual bool setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const SIP_DEPRECATED; + bool setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const; //! Returns settings value with \param dynamicKeyPart specifying the dynamic part of the settings key. QVariant valueAsVariant( const QString &dynamicKeyPart = QString() ) const; @@ -323,14 +331,12 @@ class CORE_EXPORT QgsSettingsEntryBase */ QgsSettingsTreeNode *parent() const {return mParentTreeElement;} - protected: - - /** - * Sets the settings value with a variant value. - * This should be called from any implementation as it takes care of actually calling QSettings - * \since QGIS 3.26 - */ - bool setVariantValuePrivate( const QVariant &value, const QStringList &dynamicKeyPartList = QStringList() ) const; + //! Returns TRUE if the given \a value is valid towards the setting definition + virtual bool checkValueVariant( const QVariant &value ) const + { + Q_UNUSED( value ) + return true; + } private: QString formerValuekey( const QStringList &dynamicKeyPartList ) const; @@ -345,19 +351,17 @@ class CORE_EXPORT QgsSettingsEntryBase Qgis::SettingsOptions mOptions; }; - /** * \ingroup core - * \class QgsSettingsEntryByReference + * \class QgsSettingsEntryBaseTemplate * - * \brief Base abstract class for settings entry which are passed by reference + * \brief Base abstract class for settings entries with typed get and set methods * \see QgsSettingsEntryBase - * \see QgsSettingsEntryByValue * - * \since QGIS 3.26 + * \since QGIS 3.32 */ template -class QgsSettingsEntryByReference : public QgsSettingsEntryBase +class QgsSettingsEntryBaseTemplate : public QgsSettingsEntryBase { public: @@ -373,11 +377,11 @@ class QgsSettingsEntryByReference : public QgsSettingsEntryBase * * \since QGIS 3.30 */ - QgsSettingsEntryByReference( const QString &name, - QgsSettingsTreeNode *parent, - const T &defaultValue, - const QString &description = QString(), - Qgis::SettingsOptions options = Qgis::SettingsOptions() ) + QgsSettingsEntryBaseTemplate( const QString &name, + QgsSettingsTreeNode *parent, + const QVariant &defaultValue, + const QString &description = QString(), + Qgis::SettingsOptions options = Qgis::SettingsOptions() ) : QgsSettingsEntryBase( name, parent, defaultValue, description, options ) {} @@ -390,11 +394,11 @@ class QgsSettingsEntryByReference : public QgsSettingsEntryBase * \param description specifies a description for the settings entry. * \param options specifies the options for the settings entry. */ - QgsSettingsEntryByReference( const QString &key, - const QString §ion, - const T &defaultValue, - const QString &description = QString(), - Qgis::SettingsOptions options = Qgis::SettingsOptions() ) + QgsSettingsEntryBaseTemplate( const QString &key, + const QString §ion, + const QVariant &defaultValue, + const QString &description = QString(), + Qgis::SettingsOptions options = Qgis::SettingsOptions() ) : QgsSettingsEntryBase( key, section, defaultValue, description, options ) {} @@ -428,30 +432,6 @@ class QgsSettingsEntryByReference : public QgsSettingsEntryBase return this->convertFromVariant( valueAsVariantWithDefaultOverride( convertToVariant( defaultValueOverride ), dynamicKeyPartList ) ); } - /** - * Returns the settings value for the \a dynamicKeyPart and with a \a defaultValueOverride - * \deprecated since QGIS 3.26 use valueAsVariantWithDefaultOverride instead - */ - Q_DECL_DEPRECATED T value( const QString &dynamicKeyPart, bool useDefaultValueOverride, const T &defaultValueOverride ) const SIP_DEPRECATED - { - if ( useDefaultValueOverride ) - return this->convertFromVariant( valueAsVariantWithDefaultOverride( defaultValueOverride, dynamicKeyPart ) ); - else - return this->convertFromVariant( valueAsVariant( dynamicKeyPart ) ); - } - - /** - * Returns the settings value for the \a dynamicKeyPartList and with a \a defaultValueOverride - * \deprecated since QGIS 3.26 use valueAsVariantWithDefaultOverride instead - */ - Q_DECL_DEPRECATED T value( const QStringList &dynamicKeyPartList, bool useDefaultValueOverride, const T &defaultValueOverride ) const SIP_DEPRECATED - { - if ( useDefaultValueOverride ) - return this->convertFromVariant( valueAsVariantWithDefaultOverride( defaultValueOverride, dynamicKeyPartList ) ); - else - return this->convertFromVariant( valueAsVariant( dynamicKeyPartList ) ); - } - /** * Set settings value. * @@ -489,19 +469,24 @@ class QgsSettingsEntryByReference : public QgsSettingsEntryBase */ T formerValue( const QStringList &dynamicKeyPartList ) const {return convertFromVariant( formerValueAsVariant( dynamicKeyPartList ) );} - protected: - //! Sets the settings value with an optional list of dynamic parts - bool setValuePrivate( const T &value, const QStringList &dynamicKeyPartList ) const + bool checkValueVariant( const QVariant &value ) const override { - if ( checkValue( value ) ) - return QgsSettingsEntryBase::setVariantValuePrivate( convertToVariant( value ), dynamicKeyPartList ); - else - return false; + return checkValuePrivate( convertFromVariant( value ) ); } //! Converts the variant value to the value type of the setting virtual T convertFromVariant( const QVariant &value ) const = 0; + protected: + //! Sets the settings value with an optional list of dynamic parts + virtual bool setValuePrivate( const T &value, const QStringList &dynamicKeyPartList ) const + { + if ( checkValuePrivate( value ) ) + return QgsSettingsEntryBase::setVariantValue( convertToVariant( value ), dynamicKeyPartList ); + else + return false; + } + //! Converts the value to a variant virtual QVariant convertToVariant( const T &value ) const { @@ -509,7 +494,7 @@ class QgsSettingsEntryByReference : public QgsSettingsEntryBase } //! Check if the value is valid - virtual bool checkValue( const T &value ) const + virtual bool checkValuePrivate( const T &value ) const { Q_UNUSED( value ) return true; @@ -517,163 +502,6 @@ class QgsSettingsEntryByReference : public QgsSettingsEntryBase }; -/** - * \ingroup core - * \class QgsSettingsEntryByValue - * - * \brief Base abstract class for settings entry which are passed by value - * \see QgsSettingsEntryBase - * \see QgsSettingsEntryByReference - * - * \since QGIS 3.26 - */ -template -class QgsSettingsEntryByValue : public QgsSettingsEntryBase -{ - public: - - /** - * Constructor for QgsSettingsEntryByValue. - * - * \param key specifies the key of the settings. - * \param parent specifies the parent in the tree of settings. - * \param defaultValue specifies the default value for the settings entry. - * \param description specifies a description for the settings entry. - * \param options specifies the options for the settings entry. - * \throws QgsSettingsException if the number of given parent named items doesn't match the complete key definition - */ - QgsSettingsEntryByValue( const QString &key, QgsSettingsTreeNode *parent, QVariant defaultValue, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) - : QgsSettingsEntryBase( key, parent, defaultValue, description, options ) - {} - - /** - * Constructor for QgsSettingsEntryByValue. - * - * \param key specifies the key of the settings. - * \param section specifies the section. - * \param defaultValue specifies the default value for the settings entry. - * \param description specifies a description for the settings entry. - * \param options specifies the options for the settings entry. - */ - QgsSettingsEntryByValue( const QString &key, const QString §ion, QVariant defaultValue, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) - : QgsSettingsEntryBase( key, section, defaultValue, description, options ) - {} - - virtual Qgis::SettingsType settingsType() const override = 0; - - /** - * Returns settings value. - * - * \param dynamicKeyPart specifies the dynamic part of the settings key. - */ - T value( const QString &dynamicKeyPart = QString() ) const { return this->convertFromVariant( valueAsVariant( dynamicKeyPart ) );} - - /** - * Returns settings value. - * - * \param dynamicKeyPartList specifies the list of dynamic parts of the settings key. - */ - T value( const QStringList &dynamicKeyPartList ) const { return this->convertFromVariant( valueAsVariant( dynamicKeyPartList ) );} - - //! Returns the settings value with a \a defaultValueOverride and with an optional \a dynamicKeyPart - inline T valueWithDefaultOverride( T defaultValueOverride, const QString &dynamicKeyPart = QString() ) const - { - return this->convertFromVariant( valueAsVariantWithDefaultOverride( convertToVariant( defaultValueOverride ), dynamicKeyPart ) ); - } - - //! Returns the settings value with a \a defaultValueOverride for the \a dynamicKeyPartList - inline T valueWithDefaultOverride( T defaultValueOverride, const QStringList &dynamicKeyPartList ) const - { - return this->convertFromVariant( valueAsVariantWithDefaultOverride( convertToVariant( defaultValueOverride ), dynamicKeyPartList ) ); - } - - /** - * Returns the settings value for the \a dynamicKeyPart and with a \a defaultValueOverride - * \deprecated since QGIS 3.26 use valueWithDefaultOverride instead - */ - Q_DECL_DEPRECATED T value( const QString &dynamicKeyPart, bool useDefaultValueOverride, T defaultValueOverride ) const SIP_DEPRECATED - { - if ( useDefaultValueOverride ) - return this->convertFromVariant( valueAsVariantWithDefaultOverride( defaultValueOverride, dynamicKeyPart ) ); - else - return this->convertFromVariant( valueAsVariant( dynamicKeyPart ) ); - } - - /** - * Returns the settings value for the \a dynamicKeyPartList and with a \a defaultValueOverride - * \deprecated since QGIS 3.26 use valueWithDefaultOverride instead - */ - Q_DECL_DEPRECATED T value( const QStringList &dynamicKeyPartList, bool useDefaultValueOverride, T defaultValueOverride ) const SIP_DEPRECATED - { - if ( useDefaultValueOverride ) - return this->convertFromVariant( valueAsVariantWithDefaultOverride( defaultValueOverride, dynamicKeyPartList ) ); - else - return this->convertFromVariant( valueAsVariant( dynamicKeyPartList ) ); - } - - /** - * Set settings value. - * - * \param value specifies the value to set. - * \param dynamicKeyPart specifies the dynamic part of the settings key. - */ - bool setValue( T value, const QString &dynamicKeyPart = QString() ) const - { - return setValuePrivate( value, dynamicKeyPartToList( dynamicKeyPart ) ); - } - - /** - * Set settings value. - * - * \param value specifies the value to set. - * \param dynamicKeyPartList specifies the list of dynamic parts of the settings key. - */ - bool setValue( T value, const QStringList &dynamicKeyPartList ) const - { - return setValuePrivate( value, dynamicKeyPartList ); - } - - //! Returns settings default value. - T defaultValue() const {return convertFromVariant( defaultValueAsVariant() );} - - /** - * Returns the former value - * Returns the current value (or default) if there is no former value. - */ - T formerValue( const QString &dynamicKeyPart = QString() ) const {return convertFromVariant( formerValueAsVariant( dynamicKeyPart ) );} - - /** - * Returns the former value - * Returns the current value (or default) if there is no former value. - */ - T formerValue( const QStringList &dynamicKeyPartList ) const {return convertFromVariant( formerValueAsVariant( dynamicKeyPartList ) );} - - protected: - //! Sets the settings value with an optional list of dynamic parts - virtual bool setValuePrivate( T value, const QStringList &dynamicKeyPartList ) const - { - if ( checkValue( value ) ) - return QgsSettingsEntryBase::setVariantValuePrivate( convertToVariant( value ), dynamicKeyPartList ); - else - return false; - } - - //! Converts the variant value to the value type of the setting - virtual T convertFromVariant( const QVariant &value ) const = 0; - - //! Converts the value to a variant - virtual QVariant convertToVariant( T value ) const - { - return QVariant::fromValue( value ); - } - - //! Check if the value is valid - virtual bool checkValue( T value ) const - { - Q_UNUSED( value ) - return true; - } -}; #endif // QGSSETTINGSENTRY_H diff --git a/src/core/settings/qgssettingsentryenumflag.h b/src/core/settings/qgssettingsentryenumflag.h index 1ba281cb664..ca3401bb074 100644 --- a/src/core/settings/qgssettingsentryenumflag.h +++ b/src/core/settings/qgssettingsentryenumflag.h @@ -32,7 +32,7 @@ * \since QGIS 3.20 */ template -class QgsSettingsEntryEnumFlag : public QgsSettingsEntryByValue +class QgsSettingsEntryEnumFlag : public QgsSettingsEntryBaseTemplate { public: @@ -50,11 +50,11 @@ class QgsSettingsEntryEnumFlag : public QgsSettingsEntryByValue * \since QGIS 3.30 */ QgsSettingsEntryEnumFlag( const QString &name, QgsSettingsTreeNode *parent, T defaultValue, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) - : QgsSettingsEntryByValue( name, - parent, - QMetaEnum::fromType().isFlag() ? qgsFlagValueToKeys( defaultValue ) : qgsEnumValueToKey( defaultValue ), - description, - options ) + : QgsSettingsEntryBaseTemplate( name, + parent, + QMetaEnum::fromType().isFlag() ? qgsFlagValueToKeys( defaultValue ) : qgsEnumValueToKey( defaultValue ), + description, + options ) { mMetaEnum = QMetaEnum::fromType(); Q_ASSERT( mMetaEnum.isValid() ); @@ -75,11 +75,11 @@ class QgsSettingsEntryEnumFlag : public QgsSettingsEntryByValue * \note for Python bindings, a custom implementation is achieved in Python directly */ QgsSettingsEntryEnumFlag( const QString &key, const QString §ion, T defaultValue, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) - : QgsSettingsEntryByValue( key, - section, - QVariant::fromValue( defaultValue ), - description, - options ) + : QgsSettingsEntryBaseTemplate( key, + section, + QMetaEnum::fromType().isFlag() ? qgsFlagValueToKeys( defaultValue ) : qgsEnumValueToKey( defaultValue ), + description, + options ) { mMetaEnum = QMetaEnum::fromType(); Q_ASSERT( mMetaEnum.isValid() ); @@ -87,7 +87,7 @@ class QgsSettingsEntryEnumFlag : public QgsSettingsEntryByValue QgsDebugMsg( QStringLiteral( "Invalid metaenum. Enum/Flag probably misses Q_ENUM/Q_FLAG declaration. Settings key: '%1'" ).arg( this->key() ) ); } - QVariant convertToVariant( T value ) const override + QVariant convertToVariant( const T &value ) const override { if ( mMetaEnum.isFlag() ) return qgsFlagValueToKeys( value ); @@ -129,7 +129,7 @@ class QgsSettingsEntryEnumFlag : public QgsSettingsEntryByValue * The \a value to set. * The \a dynamicKeyParts argument specifies the list of dynamic parts of the settings key. */ - bool setValuePrivate( T value, const QStringList &dynamicKeyPartList ) const override + bool setValuePrivate( const T &value, const QStringList &dynamicKeyPartList ) const override { if ( !mMetaEnum.isValid() ) { @@ -153,7 +153,7 @@ class QgsSettingsEntryEnumFlag : public QgsSettingsEntryByValue } if ( ok ) - return this->setVariantValuePrivate( variantValue, dynamicKeyPartList ); + return this->setVariantValue( variantValue, dynamicKeyPartList ); else return false; } diff --git a/src/core/settings/qgssettingsentryimpl.cpp b/src/core/settings/qgssettingsentryimpl.cpp index d9d5403378f..3fa8cf92f1a 100644 --- a/src/core/settings/qgssettingsentryimpl.cpp +++ b/src/core/settings/qgssettingsentryimpl.cpp @@ -24,7 +24,7 @@ Qgis::SettingsType QgsSettingsEntryVariant::settingsType() const } -bool QgsSettingsEntryString::checkValue( const QString &value ) const +bool QgsSettingsEntryString::checkValuePrivate( const QString &value ) const { if ( value.length() < mMinLength ) { @@ -89,7 +89,7 @@ Qgis::SettingsType QgsSettingsEntryBool::settingsType() const } -bool QgsSettingsEntryInteger::checkValue( int value ) const +bool QgsSettingsEntryInteger::checkValuePrivate( const int &value ) const { if ( value < mMinValue ) { @@ -130,7 +130,7 @@ int QgsSettingsEntryInteger::minValue() const return mMaxValue; } -bool QgsSettingsEntryInteger64::checkValue( qlonglong value ) const +bool QgsSettingsEntryInteger64::checkValuePrivate( const qlonglong &value ) const { if ( value < mMinValue ) { @@ -173,7 +173,7 @@ qlonglong QgsSettingsEntryInteger64::minValue() const -bool QgsSettingsEntryDouble::checkValue( double value ) const +bool QgsSettingsEntryDouble::checkValuePrivate( const double &value ) const { if ( value < mMinValue ) { @@ -233,7 +233,7 @@ Qgis::SettingsType QgsSettingsEntryColor::settingsType() const return Qgis::SettingsType::Color; } -bool QgsSettingsEntryColor::checkValue( const QColor &value ) const +bool QgsSettingsEntryColor::checkValuePrivate( const QColor &value ) const { if ( !mAllowAlpha && value.alpha() != 255 ) { @@ -263,7 +263,7 @@ bool QgsSettingsEntryColor::copyValueFromKeys( const QString &redKey, const QStr settings.remove( alphaKey ); } - setVariantValuePrivate( oldValue ); + setVariantValue( oldValue ); return true; } return false; diff --git a/src/core/settings/qgssettingsentryimpl.h b/src/core/settings/qgssettingsentryimpl.h index 0bdeb43789c..be7a51fc917 100644 --- a/src/core/settings/qgssettingsentryimpl.h +++ b/src/core/settings/qgssettingsentryimpl.h @@ -26,7 +26,7 @@ * \brief A variant settings entry. * \since QGIS 3.20 */ -class CORE_EXPORT QgsSettingsEntryVariant : public QgsSettingsEntryByReference +class CORE_EXPORT QgsSettingsEntryVariant : public QgsSettingsEntryBaseTemplate { public: @@ -46,7 +46,7 @@ class CORE_EXPORT QgsSettingsEntryVariant : public QgsSettingsEntryByReference +class CORE_EXPORT QgsSettingsEntryString : public QgsSettingsEntryBaseTemplate { public: @@ -147,7 +146,7 @@ class CORE_EXPORT QgsSettingsEntryString : public QgsSettingsEntryByReference( name, parent, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( name, parent, defaultValue, description, options ) , mMinLength( minLength ) , mMaxLength( maxLength ) {} @@ -170,7 +169,7 @@ class CORE_EXPORT QgsSettingsEntryString : public QgsSettingsEntryByReference( key, section, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( key, section, defaultValue, description, options ) , mMinLength( minLength ) , mMaxLength( maxLength ) {} @@ -211,10 +210,11 @@ class CORE_EXPORT QgsSettingsEntryString : public QgsSettingsEntryByReference +class CORE_EXPORT QgsSettingsEntryStringList : public QgsSettingsEntryBaseTemplate { public: @@ -246,7 +246,7 @@ class CORE_EXPORT QgsSettingsEntryStringList : public QgsSettingsEntryByReferenc const QStringList &defaultValue = QStringList(), const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER - : QgsSettingsEntryByReference( name, parent, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( name, parent, defaultValue, description, options ) {} /** @@ -263,7 +263,7 @@ class CORE_EXPORT QgsSettingsEntryStringList : public QgsSettingsEntryByReferenc const QStringList &defaultValue = QStringList(), const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER SIP_MAKE_PRIVATE - : QgsSettingsEntryByReference( key, section, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( key, section, defaultValue, description, options ) {} @@ -291,9 +291,7 @@ class CORE_EXPORT QgsSettingsEntryStringList : public QgsSettingsEntryByReferenc virtual Qgis::SettingsType settingsType() const override; - private: QStringList convertFromVariant( const QVariant &value ) const override SIP_FORCE; - }; @@ -304,7 +302,7 @@ class CORE_EXPORT QgsSettingsEntryStringList : public QgsSettingsEntryByReferenc * \brief A boolean settings entry. * \since QGIS 3.20 */ -class CORE_EXPORT QgsSettingsEntryBool : public QgsSettingsEntryByValue +class CORE_EXPORT QgsSettingsEntryBool : public QgsSettingsEntryBaseTemplate { public: @@ -322,7 +320,7 @@ class CORE_EXPORT QgsSettingsEntryBool : public QgsSettingsEntryByValue bool defaultValue = false, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER - : QgsSettingsEntryByValue( name, parent, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( name, parent, defaultValue, description, options ) {} /** @@ -339,7 +337,7 @@ class CORE_EXPORT QgsSettingsEntryBool : public QgsSettingsEntryByValue bool defaultValue = false, const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER SIP_MAKE_PRIVATE - : QgsSettingsEntryByValue( key, section, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( key, section, defaultValue, description, options ) {} #ifdef SIP_RUN @@ -367,7 +365,6 @@ class CORE_EXPORT QgsSettingsEntryBool : public QgsSettingsEntryByValue virtual Qgis::SettingsType settingsType() const override; - private: bool convertFromVariant( const QVariant &value ) const override SIP_FORCE; }; @@ -379,7 +376,7 @@ class CORE_EXPORT QgsSettingsEntryBool : public QgsSettingsEntryByValue * \brief An integer settings entry. * \since QGIS 3.20 */ -class CORE_EXPORT QgsSettingsEntryInteger : public QgsSettingsEntryByValue +class CORE_EXPORT QgsSettingsEntryInteger : public QgsSettingsEntryBaseTemplate { public: @@ -401,7 +398,7 @@ class CORE_EXPORT QgsSettingsEntryInteger : public QgsSettingsEntryByValue Qgis::SettingsOptions options = Qgis::SettingsOptions(), int minValue = std::numeric_limits::min(), int maxValue = std::numeric_limits::max() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER - : QgsSettingsEntryByValue( name, parent, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( name, parent, defaultValue, description, options ) , mMinValue( minValue ) , mMaxValue( maxValue ) { } @@ -424,7 +421,7 @@ class CORE_EXPORT QgsSettingsEntryInteger : public QgsSettingsEntryByValue Qgis::SettingsOptions options = Qgis::SettingsOptions(), int minValue = std::numeric_limits::min(), int maxValue = std::numeric_limits::max() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER SIP_MAKE_PRIVATE - : QgsSettingsEntryByValue( key, section, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( key, section, defaultValue, description, options ) , mMinValue( minValue ) , mMaxValue( maxValue ) { } @@ -467,9 +464,10 @@ class CORE_EXPORT QgsSettingsEntryInteger : public QgsSettingsEntryByValue */ int maxValue() const; - private: - bool checkValue( int value ) const override SIP_FORCE; int convertFromVariant( const QVariant &value ) const override SIP_FORCE; + + private: + bool checkValuePrivate( const int &value ) const override SIP_FORCE; int mMinValue; int mMaxValue; }; @@ -484,7 +482,7 @@ class CORE_EXPORT QgsSettingsEntryInteger : public QgsSettingsEntryByValue * \brief A 64 bits integer (long long) settings entry. * \since QGIS 3.30 */ -class CORE_EXPORT QgsSettingsEntryInteger64 : public QgsSettingsEntryByValue +class CORE_EXPORT QgsSettingsEntryInteger64 : public QgsSettingsEntryBaseTemplate { public: @@ -506,7 +504,7 @@ class CORE_EXPORT QgsSettingsEntryInteger64 : public QgsSettingsEntryByValue::min(), qlonglong maxValue = std::numeric_limits::max() ) SIP_THROW( QgsSettingsException ) - : QgsSettingsEntryByValue( name, parent, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( name, parent, defaultValue, description, options ) , mMinValue( minValue ) , mMaxValue( maxValue ) { } @@ -529,7 +527,7 @@ class CORE_EXPORT QgsSettingsEntryInteger64 : public QgsSettingsEntryByValue::min(), qlonglong maxValue = std::numeric_limits::max() ) - : QgsSettingsEntryByValue( key, section, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( key, section, defaultValue, description, options ) , mMinValue( minValue ) , mMaxValue( maxValue ) { } @@ -546,9 +544,10 @@ class CORE_EXPORT QgsSettingsEntryInteger64 : public QgsSettingsEntryByValue +class CORE_EXPORT QgsSettingsEntryDouble : public QgsSettingsEntryBaseTemplate { public: @@ -586,7 +585,7 @@ class CORE_EXPORT QgsSettingsEntryDouble : public QgsSettingsEntryByValue::lowest(), double maxValue = std::numeric_limits::max(), int displayDecimals = 1 ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER - : QgsSettingsEntryByValue( name, parent, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( name, parent, defaultValue, description, options ) , mMinValue( minValue ) , mMaxValue( maxValue ) , mDisplayHintDecimals( displayDecimals ) @@ -613,7 +612,7 @@ class CORE_EXPORT QgsSettingsEntryDouble : public QgsSettingsEntryByValue::lowest(), double maxValue = std::numeric_limits::max(), int displayDecimals = 1 ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER SIP_MAKE_PRIVATE - : QgsSettingsEntryByValue( key, section, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( key, section, defaultValue, description, options ) , mMinValue( minValue ) , mMaxValue( maxValue ) , mDisplayHintDecimals( displayDecimals ) @@ -672,9 +671,10 @@ class CORE_EXPORT QgsSettingsEntryDouble : public QgsSettingsEntryByValue +class CORE_EXPORT QgsSettingsEntryColor : public QgsSettingsEntryBaseTemplate { public: @@ -711,7 +711,7 @@ class CORE_EXPORT QgsSettingsEntryColor : public QgsSettingsEntryByReference +class CORE_EXPORT QgsSettingsEntryVariantMap : public QgsSettingsEntryBaseTemplate { public: @@ -812,7 +812,7 @@ class CORE_EXPORT QgsSettingsEntryVariantMap : public QgsSettingsEntryByReferenc const QVariantMap &defaultValue = QVariantMap(), const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER - : QgsSettingsEntryByReference( name, parent, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( name, parent, defaultValue, description, options ) { } @@ -830,7 +830,7 @@ class CORE_EXPORT QgsSettingsEntryVariantMap : public QgsSettingsEntryByReferenc const QVariantMap &defaultValue = QVariantMap(), const QString &description = QString(), Qgis::SettingsOptions options = Qgis::SettingsOptions() ) SIP_THROW( QgsSettingsException ) SIP_TRANSFER SIP_MAKE_PRIVATE - : QgsSettingsEntryByReference( key, section, defaultValue, description, options ) + : QgsSettingsEntryBaseTemplate( key, section, defaultValue, description, options ) { } @@ -858,9 +858,8 @@ class CORE_EXPORT QgsSettingsEntryVariantMap : public QgsSettingsEntryByReferenc virtual Qgis::SettingsType settingsType() const override; - private: QVariantMap convertFromVariant( const QVariant &value ) const override SIP_FORCE; - }; + #endif // QGSSETTINGSENTRYIMPL_H diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 72ade84c32f..e4f9b8452a9 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -441,7 +441,12 @@ set(QGIS_GUI_SRCS sensor/qgssensorguiregistry.cpp sensor/qgssensorwidget.cpp + settings/qgssettingseditorwidgetwrapper.cpp + settings/qgssettingseditorwidgetwrapperimpl.cpp + settings/qgssettingseditorwidgetregistry.cpp settings/qgssettingsregistrygui.cpp + settings/qgssettingstreemodel.cpp + settings/qgssettingstreewidget.cpp tableeditor/qgstableeditordialog.cpp tableeditor/qgstableeditorformattingwidget.cpp @@ -1436,7 +1441,12 @@ set(QGIS_GUI_HDRS sensor/qgssensorguiregistry.h sensor/qgssensorwidget.h + settings/qgssettingseditorwidgetwrapper.h + settings/qgssettingseditorwidgetwrapperimpl.h + settings/qgssettingseditorwidgetregistry.h settings/qgssettingsregistrygui.h + settings/qgssettingstreemodel.h + settings/qgssettingstreewidget.h tableeditor/qgstableeditordialog.h tableeditor/qgstableeditorformattingwidget.h diff --git a/src/gui/qgsgui.cpp b/src/gui/qgsgui.cpp index a0c9574e89f..73cfd784d80 100644 --- a/src/gui/qgsgui.cpp +++ b/src/gui/qgsgui.cpp @@ -63,6 +63,9 @@ #include "qgssensorguiregistry.h" #include "qgshistoryentry.h" +#include "qgssettingseditorwidgetregistry.h" + + #include #include @@ -182,6 +185,11 @@ QgsHistoryProviderRegistry *QgsGui::historyProviderRegistry() return instance()->mHistoryProviderRegistry; } +QgsSettingsEditorWidgetRegistry *QgsGui::settingsEditorWidgetRegistry() +{ + return instance()->mSettingsEditorRegistry; +} + void QgsGui::enableAutoGeometryRestore( QWidget *widget, const QString &key ) { if ( widget->objectName().isEmpty() ) @@ -238,6 +246,7 @@ QgsGui::~QgsGui() delete mRelationEditorRegistry; delete mSettingsRegistryGui; delete mSensorGuiRegistry; + delete mSettingsEditorRegistry; } QColor QgsGui::sampleColor( QPoint point ) @@ -288,6 +297,8 @@ QgsGui::QgsGui() mSettingsRegistryGui = new QgsSettingsRegistryGui(); + mSettingsEditorRegistry = new QgsSettingsEditorWidgetRegistry(); + mCodeEditorColorSchemeRegistry = new QgsCodeEditorColorSchemeRegistry(); // provider gui registry initialize QgsProviderRegistry too diff --git a/src/gui/qgsgui.h b/src/gui/qgsgui.h index 4329b1eeb9b..0c5850bc80e 100644 --- a/src/gui/qgsgui.h +++ b/src/gui/qgsgui.h @@ -48,7 +48,7 @@ class QgsRelationWidgetRegistry; class QgsMapToolShapeRegistry; class QgsHistoryProviderRegistry; class QgsSensorGuiRegistry; - +class QgsSettingsEditorWidgetRegistry; /** * \ingroup gui @@ -213,6 +213,12 @@ class GUI_EXPORT QgsGui : public QObject */ static QgsHistoryProviderRegistry *historyProviderRegistry() SIP_KEEPREFERENCE; + /** + * Returns the registry of settings editors. + * \since QGIS 3.32 + */ + static QgsSettingsEditorWidgetRegistry *settingsEditorWidgetRegistry() SIP_KEEPREFERENCE; + /** * Register the widget to allow its position to be automatically saved and restored when open and closed. * Use this to avoid needing to call saveGeometry() and restoreGeometry() on your widget. @@ -322,6 +328,7 @@ class GUI_EXPORT QgsGui : public QObject QgsMapToolShapeRegistry *mShapeMapToolRegistry = nullptr; QgsHistoryProviderRegistry *mHistoryProviderRegistry = nullptr; QgsSensorGuiRegistry *mSensorGuiRegistry = nullptr; + QgsSettingsEditorWidgetRegistry *mSettingsEditorRegistry = nullptr; std::unique_ptr< QgsWindowManagerInterface > mWindowManager; #ifdef SIP_RUN diff --git a/src/gui/qgsoptionsdialogbase.cpp b/src/gui/qgsoptionsdialogbase.cpp index 49c2c9bf867..576d80a434e 100644 --- a/src/gui/qgsoptionsdialogbase.cpp +++ b/src/gui/qgsoptionsdialogbase.cpp @@ -33,7 +33,6 @@ #include #include "qgsfilterlineedit.h" -#include "qgsmessagebaritem.h" #include "qgslogger.h" #include "qgsoptionsdialoghighlightwidget.h" #include "qgsoptionswidgetfactory.h" @@ -652,31 +651,34 @@ void QgsOptionsDialogBase::registerTextSearchWidgets() for ( int i = 0; i < mOptStackedWidget->count(); i++ ) { - const QList< QWidget * > widgets = mOptStackedWidget->widget( i )->findChildren(); - for ( QWidget *w : widgets ) + for ( QWidget *widget : widgets ) { - // get custom highlight widget in user added pages - QHash customHighlightWidgets; - QgsOptionsPageWidget *opw = qobject_cast( mOptStackedWidget->widget( i ) ); - if ( opw ) + // see if the widget also inherits QgsOptionsDialogHighlightWidget + QgsOptionsDialogHighlightWidget *shw = dynamic_cast( widget ); + if ( !shw ) { - customHighlightWidgets = opw->registeredHighlightWidgets(); - } - QgsOptionsDialogHighlightWidget *shw = nullptr; - // take custom if exists - if ( customHighlightWidgets.contains( w ) ) - { - shw = customHighlightWidgets.value( w ); + // get custom highlight widget in user added pages + QHash customHighlightWidgets; + QgsOptionsPageWidget *opw = qobject_cast( mOptStackedWidget->widget( i ) ); + if ( opw ) + { + customHighlightWidgets = opw->registeredHighlightWidgets(); + } + // take custom if exists + if ( customHighlightWidgets.contains( widget ) ) + { + shw = customHighlightWidgets.value( widget ); + } } // try to construct one otherwise if ( !shw || !shw->isValid() ) { - shw = QgsOptionsDialogHighlightWidget::createWidget( w ); + shw = QgsOptionsDialogHighlightWidget::createWidget( widget ); } if ( shw && shw->isValid() ) { - QgsDebugMsgLevel( QStringLiteral( "Registering: %1" ).arg( w->objectName() ), 4 ); + QgsDebugMsgLevel( QStringLiteral( "Registering: %1" ).arg( widget->objectName() ), 4 ); mRegisteredSearchWidgets.append( qMakePair( shw, i ) ); } else diff --git a/src/gui/qgsoptionsdialoghighlightwidget.cpp b/src/gui/qgsoptionsdialoghighlightwidget.cpp index 8727d2bcf0f..3a3bab10286 100644 --- a/src/gui/qgsoptionsdialoghighlightwidget.cpp +++ b/src/gui/qgsoptionsdialoghighlightwidget.cpp @@ -33,8 +33,7 @@ QgsOptionsDialogHighlightWidget::QgsOptionsDialogHighlightWidget( QWidget *widget ) - : QObject( widget ) - , mWidget( widget ) + : mWidget( widget ) {} QgsOptionsDialogHighlightWidget *QgsOptionsDialogHighlightWidget::createWidget( QWidget *widget ) @@ -52,6 +51,11 @@ QgsOptionsDialogHighlightWidget *QgsOptionsDialogHighlightWidget::createWidget( } } + if ( dynamic_cast( widget ) ) + { + return dynamic_cast( widget ); + } + if ( qobject_cast( widget ) ) { return new QgsOptionsDialogHighlightLabel( qobject_cast( widget ) ); @@ -97,15 +101,16 @@ bool QgsOptionsDialogHighlightWidget::searchHighlight( const QString &text ) mChangedStyle = false; } - if ( mInstalledFilter ) + if ( mEventFilter ) { - mWidget->removeEventFilter( this ); - mInstalledFilter = false; + mWidget->removeEventFilter( mEventFilter ); + delete mEventFilter; + mEventFilter = nullptr; } if ( !text.isEmpty() ) { - found = searchText( text ); + found = searchText( mSearchText ); } if ( found ) @@ -113,30 +118,38 @@ bool QgsOptionsDialogHighlightWidget::searchHighlight( const QString &text ) if ( !mWidget->isVisible() ) { - mWidget->installEventFilter( this ); - mInstalledFilter = true; + mEventFilter = new QgsOptionsDialogHighlightWidgetEventFilter( this ); + mWidget->installEventFilter( mEventFilter ); } else { - mChangedStyle = highlightText( text ); + mChangedStyle = highlightText( mSearchText ); } } return found; } -bool QgsOptionsDialogHighlightWidget::eventFilter( QObject *obj, QEvent *event ) + + +///@cond PRIVATE + +QgsOptionsDialogHighlightWidgetEventFilter::QgsOptionsDialogHighlightWidgetEventFilter( QgsOptionsDialogHighlightWidget *highlightWidget ) + : QObject( highlightWidget->widget() ) + , mHighlightWidget( highlightWidget ) +{} + +bool QgsOptionsDialogHighlightWidgetEventFilter::eventFilter( QObject *obj, QEvent *event ) { - if ( mInstalledFilter && event->type() == QEvent::Show && obj == mWidget ) + if ( event->type() == QEvent::Show && obj == mHighlightWidget->widget() ) { - mWidget->removeEventFilter( this ); - mInstalledFilter = false; + mHighlightWidget->widget()->removeEventFilter( this ); // instead of catching the event and calling show again // it might be better to use a timer to change the style // after the widget is shown #if 1 - mWidget->show(); - mChangedStyle = highlightText( mSearchText ); + mHighlightWidget->widget()->show(); + mHighlightWidget->mChangedStyle = mHighlightWidget->highlightText( mHighlightWidget->mSearchText ); return true; #else QTimer::singleShot( 500, this, [ = ] @@ -148,5 +161,6 @@ bool QgsOptionsDialogHighlightWidget::eventFilter( QObject *obj, QEvent *event ) return QObject::eventFilter( obj, event ); } +///@endcond diff --git a/src/gui/qgsoptionsdialoghighlightwidget.h b/src/gui/qgsoptionsdialoghighlightwidget.h index 7576b203374..36435fbf7e7 100644 --- a/src/gui/qgsoptionsdialoghighlightwidget.h +++ b/src/gui/qgsoptionsdialoghighlightwidget.h @@ -23,6 +23,34 @@ #include "qgis_gui.h" #include "qgis_sip.h" +class QgsOptionsDialogHighlightWidget; + +#ifndef SIP_RUN + +///@cond PRIVATE + +/** + * \ingroup gui + * \class QgsOptionsDialogHighlightWidgetEventFilter + * \brief QgsOptionsDialogHighlightWidgetEventFilter is an event filter implementation for QgsOptionsDialogHighlightWidget + * \since QGIS 3.32 + */ +class QgsOptionsDialogHighlightWidgetEventFilter : public QObject +{ + Q_OBJECT + public: + //! Constructor + QgsOptionsDialogHighlightWidgetEventFilter( QgsOptionsDialogHighlightWidget *highlightWidget ); + bool eventFilter( QObject *obj, QEvent *event ) override; + private: + QgsOptionsDialogHighlightWidget *mHighlightWidget; + +}; + +///@endcond + +#endif + /** * \ingroup gui * \class QgsOptionsDialogHighlightWidget @@ -32,10 +60,8 @@ * This uses stylesheets. * \since QGIS 3.0 */ -class GUI_EXPORT QgsOptionsDialogHighlightWidget : public QObject +class GUI_EXPORT QgsOptionsDialogHighlightWidget { - - Q_OBJECT public: /** @@ -46,6 +72,8 @@ class GUI_EXPORT QgsOptionsDialogHighlightWidget : public QObject */ static QgsOptionsDialogHighlightWidget *createWidget( QWidget *widget ) SIP_FACTORY; + virtual ~QgsOptionsDialogHighlightWidget() = default; + /** * Returns if it valid: if the widget type is handled and if the widget is not still available */ @@ -62,10 +90,6 @@ class GUI_EXPORT QgsOptionsDialogHighlightWidget : public QObject */ QWidget *widget() {return mWidget;} - - bool eventFilter( QObject *obj, QEvent *event ) override; - - protected: /** @@ -94,9 +118,11 @@ class GUI_EXPORT QgsOptionsDialogHighlightWidget : public QObject QPointer< QWidget > mWidget; private: + friend class QgsOptionsDialogHighlightWidgetEventFilter; + QString mSearchText = QString(); bool mChangedStyle = false; - bool mInstalledFilter = false; + QgsOptionsDialogHighlightWidgetEventFilter *mEventFilter = nullptr; }; #endif // QGSOPTIONSDIALOGHIGHLIGHTWIDGET_H diff --git a/src/gui/qgsoptionsdialoghighlightwidgetsimpl.cpp b/src/gui/qgsoptionsdialoghighlightwidgetsimpl.cpp index 5af4f561fd0..c0d4e456ba6 100644 --- a/src/gui/qgsoptionsdialoghighlightwidgetsimpl.cpp +++ b/src/gui/qgsoptionsdialoghighlightwidgetsimpl.cpp @@ -26,8 +26,6 @@ #include #include "qgsoptionsdialoghighlightwidget.h" -#include "qgsmessagebaritem.h" -#include "qgslogger.h" #include "qgsoptionsdialoghighlightwidgetsimpl.h" diff --git a/src/gui/qgsoptionsdialoghighlightwidgetsimpl.h b/src/gui/qgsoptionsdialoghighlightwidgetsimpl.h index d274accd52c..e7944e66b83 100644 --- a/src/gui/qgsoptionsdialoghighlightwidgetsimpl.h +++ b/src/gui/qgsoptionsdialoghighlightwidgetsimpl.h @@ -43,7 +43,6 @@ class QTableView; */ class GUI_EXPORT QgsOptionsDialogHighlightLabel : public QgsOptionsDialogHighlightWidget { - Q_OBJECT public: //! constructs a highlight widget for a label QgsOptionsDialogHighlightLabel( QLabel *label ); @@ -64,7 +63,6 @@ class GUI_EXPORT QgsOptionsDialogHighlightLabel : public QgsOptionsDialogHighlig */ class GUI_EXPORT QgsOptionsDialogHighlightCheckBox : public QgsOptionsDialogHighlightWidget { - Q_OBJECT public: //! constructs a highlight widget for a checkbox QgsOptionsDialogHighlightCheckBox( QCheckBox *checkBox ); @@ -85,7 +83,6 @@ class GUI_EXPORT QgsOptionsDialogHighlightCheckBox : public QgsOptionsDialogHigh */ class GUI_EXPORT QgsOptionsDialogHighlightButton : public QgsOptionsDialogHighlightWidget { - Q_OBJECT public: //! constructs a highlight widget for a button. QgsOptionsDialogHighlightButton( QAbstractButton *button ); @@ -106,7 +103,6 @@ class GUI_EXPORT QgsOptionsDialogHighlightButton : public QgsOptionsDialogHighli */ class GUI_EXPORT QgsOptionsDialogHighlightGroupBox : public QgsOptionsDialogHighlightWidget { - Q_OBJECT public: //! constructs a highlight widget for a group box. QgsOptionsDialogHighlightGroupBox( QGroupBox *groupBox ); @@ -129,7 +125,6 @@ class GUI_EXPORT QgsOptionsDialogHighlightGroupBox : public QgsOptionsDialogHigh */ class GUI_EXPORT QgsOptionsDialogHighlightTree : public QgsOptionsDialogHighlightWidget { - Q_OBJECT public: //! constructs a highlight widget for a tree view or widget. QgsOptionsDialogHighlightTree( QTreeView *treeView ); @@ -152,7 +147,6 @@ class GUI_EXPORT QgsOptionsDialogHighlightTree : public QgsOptionsDialogHighligh */ class GUI_EXPORT QgsOptionsDialogHighlightTable : public QgsOptionsDialogHighlightWidget { - Q_OBJECT public: //! constructs a highlight widget for a table view or widget. QgsOptionsDialogHighlightTable( QTableView *tableView ); diff --git a/src/gui/settings/qgssettingseditorwidgetregistry.cpp b/src/gui/settings/qgssettingseditorwidgetregistry.cpp new file mode 100644 index 00000000000..a5d11debbe2 --- /dev/null +++ b/src/gui/settings/qgssettingseditorwidgetregistry.cpp @@ -0,0 +1,68 @@ +/*************************************************************************** + qgssettingseditorwidgetregistry.cpp + --------------------- + begin : April 2023 + copyright : (C) 2023 by Denis Rouzaud + email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "qgssettingseditorwidgetregistry.h" + +#include "qgslogger.h" +#include "qgssettingseditorwidgetwrapper.h" +#include "qgssettingseditorwidgetwrapperimpl.h" +#include "qgssettingsentry.h" + +QgsSettingsEditorWidgetRegistry::QgsSettingsEditorWidgetRegistry() +{ + addWrapper( new QgsSettingsStringEditorWidgetWrapper() ); + addWrapper( new QgsSettingsBoolEditorWidgetWrapper() ); + addWrapper( new QgsSettingsIntegerEditorWidgetWrapper() ); + addWrapper( new QgsSettingsDoubleEditorWidgetWrapper() ); + addWrapper( new QgsSettingsColorEditorWidgetWrapper() ); + +} + +QgsSettingsEditorWidgetRegistry::~QgsSettingsEditorWidgetRegistry() +{ + qDeleteAll( mWrappers ); +} + +bool QgsSettingsEditorWidgetRegistry::addWrapper( QgsSettingsEditorWidgetWrapper *wrapper ) +{ + if ( mWrappers.contains( wrapper->id() ) ) + return false; + + mWrappers.insert( wrapper->id(), wrapper ); + return true; +} + +QgsSettingsEditorWidgetWrapper *QgsSettingsEditorWidgetRegistry::createWrapper( const QString &id, QObject *parent ) const +{ + QgsSettingsEditorWidgetWrapper *wrapper = mWrappers.value( id ); + if ( wrapper ) + { + return wrapper->createWrapper( parent ); + } + else + { + QgsDebugMsg( QStringLiteral( "Setting factory was not found for '%1', returning the default string factory" ).arg( id ) ); + return nullptr; + } +} + +QWidget *QgsSettingsEditorWidgetRegistry::createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent ) const +{ + QgsSettingsEditorWidgetWrapper *eww = createWrapper( setting->typeId(), parent ); + if ( eww ) + return eww->createEditor( setting, dynamicKeyPartList, parent ); + else + return nullptr; +} diff --git a/src/gui/settings/qgssettingseditorwidgetregistry.h b/src/gui/settings/qgssettingseditorwidgetregistry.h new file mode 100644 index 00000000000..e3223f79f9c --- /dev/null +++ b/src/gui/settings/qgssettingseditorwidgetregistry.h @@ -0,0 +1,58 @@ +/*************************************************************************** + qgssettingseditorwidgetregistry.h + --------------------- + begin : April 2023 + copyright : (C) 2023 by Denis Rouzaud + email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSSETTINGSEDITORREGISTRY_H +#define QGSSETTINGSEDITORREGISTRY_H + +#include +#include + +#include "qgis_gui.h" +#include "qgis_sip.h" + +class QWidget; +class QgsSettingsEntryBase; +class QgsSettingsEditorWidgetWrapper; + +/** + * \ingroup gui + * \brief This class manages editor widgets for settings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsEditorWidgetRegistry +{ + public: + //! Constructor + QgsSettingsEditorWidgetRegistry(); + ~QgsSettingsEditorWidgetRegistry(); + + /** + * Adds an editor widget \a wrapper to the registry + * Returns FALSE if an editor widget with same id already exists. + */ + bool addWrapper( QgsSettingsEditorWidgetWrapper *wrapper SIP_TRANSFER ); + + //! Returns a new instance of the editor widget for the given \a id + QgsSettingsEditorWidgetWrapper *createWrapper( const QString &id, QObject *parent ) const; + + //! Creates an editor widget for the given \a setting using the corresponding registered wrapper + QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent = nullptr ) const SIP_FACTORY; + + private: + QMap mWrappers; +}; + +#endif // QGSSETTINGSEDITORREGISTRY_H diff --git a/src/gui/settings/qgssettingseditorwidgetwrapper.cpp b/src/gui/settings/qgssettingseditorwidgetwrapper.cpp new file mode 100644 index 00000000000..144ce2f7734 --- /dev/null +++ b/src/gui/settings/qgssettingseditorwidgetwrapper.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + qgssettingseditorwidgetwrapper.cpp + -------------------------------------- + Date : February 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +#include "qgssettingseditorwidgetwrapper.h" + +#include "qgslogger.h" +#include "qgssettingsentry.h" + +#include + + +QgsSettingsEditorWidgetWrapper *QgsSettingsEditorWidgetWrapper::fromWidget( const QWidget *widget ) +{ + QVariant editorDataVariant = widget->property( "SETTING-EDITOR-WIDGET-WRAPPER" ); + if ( editorDataVariant.isValid() ) + { + return editorDataVariant.value(); + } + + return nullptr; +} + +QgsSettingsEditorWidgetWrapper::QgsSettingsEditorWidgetWrapper( QObject *parent ) + : QObject( parent ) +{ +} + +QWidget *QgsSettingsEditorWidgetWrapper::createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent ) +{ + QWidget *editor = createEditorPrivate( parent ); + if ( configureEditor( editor, setting, dynamicKeyPartList ) ) + return editor; + else + QgsDebugMsg( QStringLiteral( "editor could not be configured" ) ); + return nullptr; +} + +bool QgsSettingsEditorWidgetWrapper::configureEditor( QWidget *editor, const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList ) +{ + mDynamicKeyPartList = dynamicKeyPartList; + + bool ok = configureEditorPrivate( editor, setting ); + + if ( ok ) + editor->setProperty( "SETTING-EDITOR-WIDGET-WRAPPER", QVariant::fromValue( this ) ); + + return ok; +} diff --git a/src/gui/settings/qgssettingseditorwidgetwrapper.h b/src/gui/settings/qgssettingseditorwidgetwrapper.h new file mode 100644 index 00000000000..db6b85d49cf --- /dev/null +++ b/src/gui/settings/qgssettingseditorwidgetwrapper.h @@ -0,0 +1,96 @@ +/*************************************************************************** + qgssettingseditorwidgetwrapper.h + -------------------------------------- + Date : February 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSSETTINGSEDITORWIDGETWRAPPER_H +#define QGSSETTINGSEDITORWIDGETWRAPPER_H + +#include + +#include "qgis_sip.h" +#include "qgis_gui.h" + +class QgsSettingsEntryBase; + +/** + * \ingroup gui + * \brief Base class for settings editor wrappers + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsEditorWidgetWrapper : public QObject +{ + Q_OBJECT + public: + //! Creates a wrapper from the definition stored in a \a widget created by createEditor() + static QgsSettingsEditorWidgetWrapper *fromWidget( const QWidget *widget ) SIP_FACTORY; + + //! Constructor + QgsSettingsEditorWidgetWrapper( QObject *parent = nullptr ); + + virtual ~QgsSettingsEditorWidgetWrapper() = default; + + /** + * This id of the type of settings it handles + * \note This mostly correspond to the content of Qgis::SettingsType but it's a string since custom Python implementation are possible. + */ + virtual QString id() const = 0; + + //! Creates a new instance of the editor wrapper so it can be configured for a widget and a setting + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = nullptr ) const = 0; + + //! Creates the editor widget for the given \a setting + QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList(), QWidget *parent = nullptr ); + + //! Configures the \a editor according the setting + bool configureEditor( QWidget *editor, const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList() ); + + /** + * Sets the widget value from the setting value + * The wrapper must be configured before calling this medthod + */ + virtual bool setWidgetFromSetting() const = 0; + + /** + * Sets the setting value from the widget value + * The wrapper must be configured before calling this medthod + */ + virtual bool setSettingFromWidget() const = 0; + + /** + * Returns the value from the widget as a variant + * The wrapper must be configured before calling this medthod + */ + virtual QVariant variantValueFromWidget() const = 0; + + /** + * Sets the \a value of the widget + * The wrapper must be configured before calling this medthod + */ + virtual void setWidgetFromVariant( const QVariant &value ) const = 0; + + + protected: + //! Creates the widgets + virtual QWidget *createEditorPrivate( QWidget *parent = nullptr ) const = 0; + + //! Configures an existing \a editor widget + virtual bool configureEditorPrivate( QWidget *editor, const QgsSettingsEntryBase *setting ) = 0; + + QStringList mDynamicKeyPartList; +}; + + + +#endif // QGSSETTINGSEDITORWIDGETWRAPPER_H diff --git a/src/gui/settings/qgssettingseditorwidgetwrapperimpl.cpp b/src/gui/settings/qgssettingseditorwidgetwrapperimpl.cpp new file mode 100644 index 00000000000..68970ebe2d9 --- /dev/null +++ b/src/gui/settings/qgssettingseditorwidgetwrapperimpl.cpp @@ -0,0 +1,340 @@ +/*************************************************************************** + qgssettingseditorwidgetwrapperimpl.cpp + -------------------------------------- + Date : February 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +#include "qgssettingseditorwidgetwrapperimpl.h" +#include "qgslogger.h" +#include "qgssettingsentryimpl.h" +#include "qgscolorbutton.h" + +#include +#include + + +// ******* +// String +// ******* + +QString QgsSettingsStringEditorWidgetWrapper::id() const +{ + return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast( Qgis::SettingsType::String ) ) ); +} + +bool QgsSettingsStringEditorWidgetWrapper::setWidgetValue( const QString &value ) const +{ + if ( mEditor ) + { + mEditor->setText( value ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +bool QgsSettingsStringEditorWidgetWrapper::setSettingFromWidget() const +{ + if ( mEditor ) + { + mSetting->setValue( mEditor->text(), mDynamicKeyPartList ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +QString QgsSettingsStringEditorWidgetWrapper::valueFromWidget() const +{ + if ( mEditor ) + { + return mEditor->text(); + } + else + { + QgsDebugMsg( QString( "editor is not set, returning a non-existing value" ) ); + } + return QString(); +} + +// ******* +// Boolean +// ******* + +QString QgsSettingsBoolEditorWidgetWrapper::id() const +{ + return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast( Qgis::SettingsType::Bool ) ) ); +} + +bool QgsSettingsBoolEditorWidgetWrapper::setWidgetValue( const bool &value ) const +{ + if ( mEditor ) + { + mEditor->setChecked( value ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +bool QgsSettingsBoolEditorWidgetWrapper::setSettingFromWidget() const +{ + if ( mEditor ) + { + mSetting->setValue( mEditor->isChecked(), mDynamicKeyPartList ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +bool QgsSettingsBoolEditorWidgetWrapper::valueFromWidget() const +{ + + if ( mEditor ) + { + return mEditor->isChecked(); + } + else + { + QgsDebugMsg( QString( "editor is not set, returning a non-existing value" ) ); + } + return false; +} + + +// ******* +// Integer +// ******* + +QString QgsSettingsIntegerEditorWidgetWrapper::id() const +{ + return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast( Qgis::SettingsType::Integer ) ) ); +} + +bool QgsSettingsIntegerEditorWidgetWrapper::setWidgetValue( const int &value ) const +{ + if ( mEditor ) + { + mEditor->setValue( value ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +bool QgsSettingsIntegerEditorWidgetWrapper::setSettingFromWidget() const +{ + if ( mEditor ) + { + mSetting->setValue( mEditor->value(), mDynamicKeyPartList ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +int QgsSettingsIntegerEditorWidgetWrapper::valueFromWidget() const +{ + if ( mEditor ) + { + return mEditor->value(); + } + else + { + QgsDebugMsg( QString( "editor is not set, returning a non-existing value" ) ); + } + return std::numeric_limits::quiet_NaN(); +} + + + +// ******* +// Double +// ******* + +QString QgsSettingsDoubleEditorWidgetWrapper::id() const +{ + return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast( Qgis::SettingsType::Double ) ) ); +} + +bool QgsSettingsDoubleEditorWidgetWrapper::setWidgetValue( const double &value ) const +{ + if ( mEditor ) + { + mEditor->setValue( value ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +bool QgsSettingsDoubleEditorWidgetWrapper::setSettingFromWidget() const +{ + if ( mEditor ) + { + mSetting->setValue( mEditor->value(), mDynamicKeyPartList ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +double QgsSettingsDoubleEditorWidgetWrapper::valueFromWidget() const +{ + if ( mEditor ) + { + return mEditor->value(); + } + else + { + QgsDebugMsg( QString( "editor is not set, returning a non-existing value" ) ); + } + return std::numeric_limits::quiet_NaN(); +} + +// ******* +// Color +// ******* + +QString QgsSettingsColorEditorWidgetWrapper::id() const +{ + return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast( Qgis::SettingsType::Color ) ) ); +} + +bool QgsSettingsColorEditorWidgetWrapper::setWidgetValue( const QColor &value ) const +{ + if ( mEditor ) + { + mEditor->setColor( value ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +void QgsSettingsColorEditorWidgetWrapper::configureEditorPrivateImplementation() +{ + if ( mEditor ) + { + mEditor->setAllowOpacity( mSetting->allowAlpha() ); + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } +} + +bool QgsSettingsColorEditorWidgetWrapper::setSettingFromWidget() const +{ + if ( mEditor ) + { + mSetting->setValue( mEditor->color(), mDynamicKeyPartList ); + return true; + } + else + { + QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); + } + return false; +} + +QColor QgsSettingsColorEditorWidgetWrapper::valueFromWidget() const +{ + if ( mEditor ) + { + return mEditor->color(); + } + else + { + QgsDebugMsg( QString( "editor is not set, returning a non-existing value" ) ); + } + return QColor(); +} + +// ******* +// StringList +// ******* + +//QString QgsSettingsStringListEditorWidgetWrapper::id() const +//{ +// return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast( Qgis::SettingsType::StringList ) ) ); +//} + +//bool QgsSettingsStringListEditorWidgetWrapper::setWidgetFromSetting() const +//{ +// if ( mEditor ) +// { +// mEditor->setValue( mSetting->value( mDynamicKeyPartList ) ); +// return true; +// } +// else +// { +// QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); +// } +// return false; +//} + +//bool QgsSettingsStringListEditorWidgetWrapper::setSettingFromWidget() const +//{ +// if ( mEditor ) +// { +// mSetting->setValue( mEditor->value(), mDynamicKeyPartList ); +// return true; +// } +// else +// { +// QgsDebugMsg( QStringLiteral( "Settings editor not set for %1" ).arg( mSetting->definitionKey() ) ); +// } +// return false; +//} + +//QVariant QgsSettingsStringListEditorWidgetWrapper::valueFromWidget() const +//{ +// if ( mEditor ) +// { +// return mEditor->value(); +// } +// else +// { +// QgsDebugMsg(QString("editor is not set, returning a non-existing value")); +// } +// return QStringList(); +//} diff --git a/src/gui/settings/qgssettingseditorwidgetwrapperimpl.h b/src/gui/settings/qgssettingseditorwidgetwrapperimpl.h new file mode 100644 index 00000000000..00664471fb8 --- /dev/null +++ b/src/gui/settings/qgssettingseditorwidgetwrapperimpl.h @@ -0,0 +1,268 @@ +/*************************************************************************** + qgssettingseditorwidgetwrapperimpl.h + -------------------------------------- + Date : February 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSSETTINGSEDITORWIDGETWRAPPERIMPL_H +#define QGSSETTINGSEDITORWIDGETWRAPPERIMPL_H + +#include + +#include "qgis_gui.h" +#include "qgssettingseditorwidgetwrapper.h" +#include "qgslogger.h" + +#include "qgssettingsentryimpl.h" +#include "qgscolorbutton.h" +#include +#include +#include +#include +#include + + +//TODO variant map, enum + +class QgsColorButton; + +/** + * \ingroup gui + * \brief This class is a base factory of editor for settings + * + * \since QGIS 3.32 + */ +template +class GUI_EXPORT QgsSettingsEditorWidgetWrapperTemplate : public QgsSettingsEditorWidgetWrapper +{ + public: + //! Constructor + QgsSettingsEditorWidgetWrapperTemplate( QObject *parent = nullptr ) + : QgsSettingsEditorWidgetWrapper( parent ) {} + + virtual QString id() const override = 0; + + virtual bool setWidgetFromSetting() const override + { + if ( mSetting ) + return setWidgetValue( mSetting->value( mDynamicKeyPartList ) ); + + QgsDebugMsg( "editor is not configured" ); + return false; + } + + virtual bool setSettingFromWidget() const override = 0; + + void setWidgetFromVariant( const QVariant &value ) const override + { + setWidgetValue( mSetting->convertFromVariant( value ) ); + } + + //! Sets the widget value + virtual bool setWidgetValue( const U &value ) const = 0; + + QVariant variantValueFromWidget() const override + { + return valueFromWidget(); + }; + + //! Returns the widget value + virtual U valueFromWidget() const = 0; + + //! Returns the editor + V *editor() const {return mEditor;} + + //! Returns the setting + const T *setting() const {return mSetting;} + + virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = nullptr ) const override = 0; + + protected: + virtual QWidget *createEditorPrivate( QWidget *parent = nullptr ) const override + { + V *editor = new V( parent ); + editor->setAutoFillBackground( true ); + return editor; + } + + bool configureEditorPrivate( QWidget *editor, const QgsSettingsEntryBase *setting ) override + { + mSetting = dynamic_cast( setting ); + mEditor = qobject_cast( editor ); + if ( mEditor ) + { + configureEditorPrivateImplementation(); + return true; + } + return false; + } + + //! To be re-implemented to implemeent type specific configuration (e.g. opacity for colors) + virtual void configureEditorPrivateImplementation() {} + + const T *mSetting = nullptr; + V *mEditor = nullptr; +}; + + +/** + * \ingroup gui + * \brief This class is a factory of editor for string settings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsStringEditorWidgetWrapper : public QgsSettingsEditorWidgetWrapperTemplate +{ + Q_OBJECT + public: + //! Constructor + QgsSettingsStringEditorWidgetWrapper( QObject *parent = nullptr ) + : QgsSettingsEditorWidgetWrapperTemplate( parent ) {} + + QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = nullptr ) const override {return new QgsSettingsStringEditorWidgetWrapper( parent );} + + QString id() const override; + + bool setSettingFromWidget() const override; + + QString valueFromWidget() const override; + + bool setWidgetValue( const QString &value ) const override; +}; + +/** + * \ingroup gui + * \brief This class is a factory of editor for boolean settings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsBoolEditorWidgetWrapper : public QgsSettingsEditorWidgetWrapperTemplate +{ + Q_OBJECT + public: + //! Constructor + QgsSettingsBoolEditorWidgetWrapper( QObject *parent = nullptr ) + : QgsSettingsEditorWidgetWrapperTemplate( parent ) {} + + QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = nullptr ) const override {return new QgsSettingsBoolEditorWidgetWrapper( parent );} + + QString id() const override; + + bool setSettingFromWidget() const override; + + bool valueFromWidget() const override; + + bool setWidgetValue( const bool &value ) const override; +}; + +/** + * \ingroup gui + * \brief This class is a factory of editor for integer settings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsIntegerEditorWidgetWrapper : public QgsSettingsEditorWidgetWrapperTemplate +{ + Q_OBJECT + public: + //! Constructor + QgsSettingsIntegerEditorWidgetWrapper( QObject *parent = nullptr ) + : QgsSettingsEditorWidgetWrapperTemplate( parent ) {} + + QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = nullptr ) const override {return new QgsSettingsIntegerEditorWidgetWrapper( parent );} + + QString id() const override; + + bool setSettingFromWidget() const override; + + int valueFromWidget() const override; + + bool setWidgetValue( const int &value ) const override; +}; + + +/** + * \ingroup gui + * \brief This class is a factory of editor for double settings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsDoubleEditorWidgetWrapper : public QgsSettingsEditorWidgetWrapperTemplate +{ + Q_OBJECT + public: + //! Constructor + QgsSettingsDoubleEditorWidgetWrapper( QObject *parent = nullptr ) + : QgsSettingsEditorWidgetWrapperTemplate( parent ) {} + + QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = nullptr ) const override {return new QgsSettingsDoubleEditorWidgetWrapper( parent );} + + QString id() const override; + + bool setSettingFromWidget() const override; + + double valueFromWidget() const override; + + bool setWidgetValue( const double &value ) const override; +}; + + +/** + * \ingroup gui + * \brief This class is a factory of editor for color settings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsColorEditorWidgetWrapper : public QgsSettingsEditorWidgetWrapperTemplate +{ + Q_OBJECT + public: + //! Constructor + QgsSettingsColorEditorWidgetWrapper( QObject *parent = nullptr ) + : QgsSettingsEditorWidgetWrapperTemplate( parent ) {} + + QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = nullptr ) const override {return new QgsSettingsColorEditorWidgetWrapper( parent );} + + QString id() const override; + + bool setSettingFromWidget() const override; + + QColor valueFromWidget() const override; + + bool setWidgetValue( const QColor &value ) const override; + + void configureEditorPrivateImplementation() override; +}; + +///** +// * \ingroup gui +// * \brief This class is a factory of editor for boolean settings +// * +// * \since QGIS 3.32 +// */ +//class GUI_EXPORT QgsSettingsStringListEditorWidgetWrapper : public QgsSettingsEditorWidgetWrapperTemplate +//{ +// public: +// QgsSettingsStringListEditorWidgetWrapper() +// : QgsSettingsEditorWidgetWrapperTemplate() {} + +// QString id() const override; + +// bool setWidgetFromSetting() const override; + +// bool setSettingFromWidget() const override; + +// QStringList valueFromWidget() const override; +//}; + + +#endif // QGSSETTINGSEDITORWIDGETWRAPPERIMPL_H diff --git a/src/gui/settings/qgssettingstreemodel.cpp b/src/gui/settings/qgssettingstreemodel.cpp new file mode 100644 index 00000000000..1592daadd57 --- /dev/null +++ b/src/gui/settings/qgssettingstreemodel.cpp @@ -0,0 +1,565 @@ +/*************************************************************************** + qgssettingstreemodel.cpp + -------------------------------------- + Date : January 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include +#include + +#include "qgssettingstreemodel.h" +#include "qgssettingsentry.h" +#include "qgssettingstreenode.h" +#include "qgssettingseditorwidgetwrapper.h" +#include "qgssettingseditorwidgetregistry.h" +#include "qgsgui.h" +#include "qgslogger.h" + +///@cond PRIVATE + + +QgsSettingsTreeModelNodeData *QgsSettingsTreeModelNodeData::createRootNodeData( const QgsSettingsTreeNode *rootNode, QObject *parent = nullptr ) +{ + QgsSettingsTreeModelNodeData *nodeData = new QgsSettingsTreeModelNodeData( parent ); + nodeData->mType = Type::RootNode; + nodeData->mName = rootNode->key(); + nodeData->mTreeNode = rootNode; + nodeData->fillChildren(); + return nodeData; +} + +void QgsSettingsTreeModelNodeData::applyChanges() +{ + switch ( type() ) + { + case Type::NamedListTreeNode: + case Type::RootNode: + case Type::TreeNode: + case Type::NamedListItem: + { + QList::iterator it = mChildren.begin(); + for ( ; it != mChildren.end(); ++it ) + ( *it )->applyChanges(); + break; + } + case Type::Setting: + { + if ( isEdited() ) + { + setting()->setVariantValue( mValue, mNamedParentNodes ); + } + break; + } + } +} + +bool QgsSettingsTreeModelNodeData::setValue( const QVariant &value ) +{ + Q_ASSERT( mType == Type::Setting ); + if ( !value.isValid() && mValue.isValid() ) + { + mExists = false; + mIsEdited = true; + mValue = QVariant(); + } + else if ( !mValue.isValid() || mValue != value ) + { + mValue = value; + mIsEdited = ( value != mOriginalValue ); + } + // TODO: check the value of setting is fulfilling the settings' contsraints ? + return true; +} + + +void QgsSettingsTreeModelNodeData::addChildForTreeNode( const QgsSettingsTreeNode *node ) +{ + QgsSettingsTreeModelNodeData *nodeData = new QgsSettingsTreeModelNodeData( this ); + nodeData->mParent = this; + nodeData->mNamedParentNodes = mNamedParentNodes; + nodeData->mName = node->key(); + nodeData->mTreeNode = node; + if ( node->type() == Qgis::SettingsTreeNodeType::NamedList ) + { + nodeData->mType = Type::NamedListTreeNode; + const QgsSettingsTreeNamedListNode *nln = dynamic_cast( node ); + const QStringList items = nln->items( mNamedParentNodes ); + for ( const QString &item : items ) + { + nodeData->addChildForNamedListItemNode( item, nln ); + } + } + else + { + nodeData->mType = Type::TreeNode; + nodeData->fillChildren(); + } + mChildren.append( nodeData ); +} + +void QgsSettingsTreeModelNodeData::addChildForNamedListItemNode( const QString &item, const QgsSettingsTreeNamedListNode *namedListNode ) +{ + QgsSettingsTreeModelNodeData *nodeData = new QgsSettingsTreeModelNodeData( this ); + nodeData->mType = Type::NamedListItem; + nodeData->mParent = this; + nodeData->mNamedParentNodes = mNamedParentNodes; + nodeData->mNamedParentNodes.append( item ); + nodeData->mName = item; + nodeData->mTreeNode = namedListNode; + nodeData->fillChildren(); + mChildren.append( nodeData ); +} + +void QgsSettingsTreeModelNodeData::addChildForSetting( const QgsSettingsEntryBase *setting ) +{ + QgsSettingsTreeModelNodeData *nodeData = new QgsSettingsTreeModelNodeData( this ); + nodeData->mType = Type::Setting; + nodeData->mParent = this; + nodeData->mNamedParentNodes = mNamedParentNodes; + nodeData->mSetting = setting; + nodeData->mName = setting->name(); + nodeData->mValue = setting->valueAsVariant( mNamedParentNodes ); + nodeData->mOriginalValue = nodeData->mValue; + nodeData->mExists = setting->exists( mNamedParentNodes ); + + switch ( mNamedParentNodes.count() ) + { + case 1: + QgsDebugMsg( QString( "getting %1 with %2" ).arg( setting->definitionKey(), mNamedParentNodes.at( 0 ) ) ); + break; + case 2: + QgsDebugMsg( QString( "getting %1 with %2" ).arg( setting->definitionKey(), mNamedParentNodes.at( 0 ), mNamedParentNodes.at( 1 ) ) ); + break; + case 0: + QgsDebugMsg( QString( "getting %1" ).arg( setting->definitionKey() ) ); + break; + default: + Q_ASSERT( false ); + QgsDebugMsg( QString( "Not handling that many named parent nodes for %1" ).arg( setting->definitionKey() ) ); + break; + } + + mChildren.append( nodeData ); +} + +void QgsSettingsTreeModelNodeData::fillChildren() +{ + const QList childrenNodes = mTreeNode->childrenNodes(); + for ( const QgsSettingsTreeNode *childNode : childrenNodes ) + { + addChildForTreeNode( childNode ); + } + const QList childrenSettings = mTreeNode->childrenSettings(); + for ( const QgsSettingsEntryBase *setting : childrenSettings ) + { + addChildForSetting( setting ); + } +} + +///@endcond + + + +QgsSettingsTreeModel::QgsSettingsTreeModel( QgsSettingsTreeNode *rootNode, QObject *parent ) + : QAbstractItemModel( parent ) +{ + mRootNode = QgsSettingsTreeModelNodeData::createRootNodeData( rootNode, this ); + + QPalette pal = qApp->palette(); + mEditedColorBack = pal.color( QPalette::Active, QPalette::Dark ); + mEditedColorFore = pal.color( QPalette::Active, QPalette::BrightText ); + mNotSetColor = pal.color( QPalette::Disabled, QPalette::WindowText ); +} + +QgsSettingsTreeModel::~QgsSettingsTreeModel() +{ + //delete mRootNode; +} + +void QgsSettingsTreeModel::applyChanges() +{ + beginResetModel(); + mRootNode->applyChanges(); + endResetModel(); +} + +QgsSettingsTreeModelNodeData *QgsSettingsTreeModel::index2node( const QModelIndex &index ) const +{ + if ( !index.isValid() ) + return mRootNode; + + QObject *obj = reinterpret_cast( index.internalPointer() ); + return qobject_cast( obj ); +} + +QModelIndex QgsSettingsTreeModel::node2index( QgsSettingsTreeModelNodeData *node ) const +{ + if ( !node || !node->parent() ) + return QModelIndex(); // this is the only root item -> invalid index + + QModelIndex parentIndex = node2index( node->parent() ); + + int row = node->parent()->children().indexOf( node ); + Q_ASSERT( row >= 0 ); + return index( row, static_cast( Column::Name ), parentIndex ); +} + + +QModelIndex QgsSettingsTreeModel::index( int row, int column, const QModelIndex &parent ) const +{ + if ( column < 0 || column >= columnCount( parent ) || + row < 0 || row >= rowCount( parent ) ) + return QModelIndex(); + + QgsSettingsTreeModelNodeData *n = index2node( parent ); + if ( !n ) + return QModelIndex(); // have no children + + + return createIndex( row, column, static_cast( n->children().at( row ) ) ); +} + +QModelIndex QgsSettingsTreeModel::parent( const QModelIndex &child ) const +{ + if ( !child.isValid() ) + return QModelIndex(); + + if ( QgsSettingsTreeModelNodeData *n = index2node( child ) ) + { + return indexOfParentSettingsTreeNode( n->parent() ); // must not be null + } + else + { + Q_ASSERT( false ); // no other node types! + return QModelIndex(); + } +} + +QModelIndex QgsSettingsTreeModel::indexOfParentSettingsTreeNode( QgsSettingsTreeModelNodeData *parentNode ) const +{ + Q_ASSERT( parentNode ); + + const QgsSettingsTreeModelNodeData *grandParentNode = parentNode->parent(); + if ( !grandParentNode ) + return QModelIndex(); // root node -> invalid index + + int row = grandParentNode->children().indexOf( parentNode ); + Q_ASSERT( row >= 0 ); + + return createIndex( row, 0, static_cast( parentNode ) ); +} + +int QgsSettingsTreeModel::rowCount( const QModelIndex &parent ) const +{ + QgsSettingsTreeModelNodeData *n = index2node( parent ); + if ( !n ) + return 0; + + return n->children().count(); +} + +int QgsSettingsTreeModel::columnCount( const QModelIndex &parent ) const +{ + Q_UNUSED( parent ) + return 3; +} + +QVariant QgsSettingsTreeModel::data( const QModelIndex &index, int role ) const +{ + if ( !index.isValid() || index.column() > columnCount( index ) ) + return QVariant(); + + QgsSettingsTreeModelNodeData *node = index2node( index ); + + if ( role == Qt::ForegroundRole && node->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + if ( !node->exists() ) + { + // settings not yet set + return mNotSetColor; + } + + if ( node->isEdited() && + ( node->setting()->settingsType() != Qgis::SettingsType::Color || index.column() != static_cast( Column::Value ) ) ) + { + return mEditedColorFore; + } + } + + if ( role == Qt::BackgroundRole && node->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + // background for edited settings (except colors) + if ( node->isEdited() && + ( node->setting()->settingsType() != Qgis::SettingsType::Color || index.column() != static_cast( Column::Value ) ) ) + { + return mEditedColorBack; + } + } + + switch ( static_cast( index.column() ) ) + { + case Column::Name: + { + if ( role == Qt::DisplayRole || role == Qt::EditRole ) + { + return node->name(); + } + break; + } + + case Column::Value: + { + if ( role == Qt::CheckStateRole ) + { + if ( node->type() == QgsSettingsTreeModelNodeData::Type::Setting && + node->setting()->settingsType() == Qgis::SettingsType::Bool ) + { + // special handling of bool setting to show combobox + return node->value().toBool() ? Qt::Checked : Qt::Unchecked; + } + } + if ( role == Qt::DisplayRole || role == Qt::EditRole ) + { + if ( node->type() == QgsSettingsTreeModelNodeData::Type::Setting && + node->setting()->settingsType() == Qgis::SettingsType::Bool ) + { + // special handling of bool setting to show combobox + return QString(); + } + else + { + return node->value(); + } + } + else if ( role == Qt::BackgroundRole ) + { + if ( node->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + switch ( node->setting()->settingsType() ) + { + case Qgis::SettingsType::Custom: + case Qgis::SettingsType::Variant: + case Qgis::SettingsType::String: + case Qgis::SettingsType::StringList: + case Qgis::SettingsType::VariantMap: + case Qgis::SettingsType::Bool: + case Qgis::SettingsType::Integer: + case Qgis::SettingsType::Double: + case Qgis::SettingsType::EnumFlag: + break; + + case Qgis::SettingsType::Color: + return node->value(); + } + } + } + break; + } + + case Column::Description: + { + if ( node->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + if ( role == Qt::DisplayRole || role == Qt::EditRole ) + { + return node->setting()->description(); + } + } + break; + } + + default: + break; + } + return QVariant(); +} + + +QVariant QgsSettingsTreeModel::headerData( int section, Qt::Orientation orientation, int role ) const +{ + if ( orientation == Qt::Orientation::Horizontal && role == Qt::DisplayRole ) + { + switch ( static_cast( section ) ) + { + case Column::Name: + return tr( "Name" ); + case Column::Value: + return tr( "Value" ); + case Column::Description: + return tr( "Description" ); + }; + } + + return QVariant(); +} + +Qt::ItemFlags QgsSettingsTreeModel::flags( const QModelIndex &index ) const +{ + if ( index.column() == static_cast( Column::Value ) ) + { + QgsSettingsTreeModelNodeData *nodeData = index2node( index ); + if ( nodeData->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + if ( nodeData->setting()->settingsType() == Qgis::SettingsType::Bool ) + { + return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; + } + else + { + return Qt::ItemIsEnabled | Qt::ItemIsEditable; + } + } + } + else + { + return Qt::ItemIsEnabled; + } + return Qt::NoItemFlags; +} + +bool QgsSettingsTreeModel::setData( const QModelIndex &index, const QVariant &value, int role ) +{ + if ( index.column() == static_cast( Column::Value ) ) + { + if ( role == Qt::EditRole || role == Qt::CheckStateRole ) + { + QgsSettingsTreeModelNodeData *nodeData = index2node( index ); + if ( nodeData->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + if ( role == Qt::CheckStateRole ) + { + Q_ASSERT( nodeData->setting()->settingsType() == Qgis::SettingsType::Bool ); + nodeData->setValue( value == Qt::Checked ? true : false ); + } + else + { + nodeData->setValue( value ); + } + emit dataChanged( index.siblingAtColumn( 0 ), index.siblingAtColumn( columnCount( index.parent() ) - 1 ) ); + return true; + } + } + } + return false; +} + + +///@cond PRIVATE + + +QgsSettingsTreeItemDelegate::QgsSettingsTreeItemDelegate( QgsSettingsTreeModel *model, QObject *parent ) + : QItemDelegate( parent ) + , mModel( model ) +{ +} + +QWidget *QgsSettingsTreeItemDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + Q_UNUSED( option ) + if ( static_cast( index.column() ) == QgsSettingsTreeModel::Column::Value ) + { + QModelIndex sourceIndex = index; + const QgsSettingsTreeProxyModel *proxyModel = qobject_cast( index.model() ); + if ( proxyModel ) + { + sourceIndex = proxyModel->mapToSource( index ); + } + QgsSettingsTreeModelNodeData *nodeData = mModel->index2node( sourceIndex ); + if ( nodeData->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + return QgsGui::settingsEditorWidgetRegistry()->createEditor( nodeData->setting(), nodeData->namedParentNodes(), parent ); + } + } + return nullptr; +} + +void QgsSettingsTreeItemDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const +{ + QgsSettingsEditorWidgetWrapper *eww = QgsSettingsEditorWidgetWrapper::fromWidget( editor ); + if ( eww ) + eww->setWidgetFromVariant( index.model()->data( index, Qt::DisplayRole ) ); +} + +void QgsSettingsTreeItemDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const +{ + QgsSettingsEditorWidgetWrapper *eww = QgsSettingsEditorWidgetWrapper::fromWidget( editor ); + if ( eww ) + model->setData( index, eww->variantValueFromWidget(), Qt::EditRole ); +} + +///@endcond + + + + + +QgsSettingsTreeProxyModel::QgsSettingsTreeProxyModel( QgsSettingsTreeNode *rootNode, QObject *parent ) + : QSortFilterProxyModel( parent ) +{ + mSourceModel = new QgsSettingsTreeModel( rootNode, parent ); + QSortFilterProxyModel::setSourceModel( mSourceModel ); +} + +void QgsSettingsTreeProxyModel::setFilterText( const QString &filterText ) +{ + if ( filterText == mFilterText ) + return; + + mFilterText = filterText; + invalidateFilter(); +} + +bool QgsSettingsTreeProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const +{ + QgsSettingsTreeModelNodeData *node = mSourceModel->index2node( mSourceModel->index( source_row, static_cast( QgsSettingsTreeModel::Column::Name ), source_parent ) ); + return nodeShown( node ); +} + +bool QgsSettingsTreeProxyModel::nodeShown( QgsSettingsTreeModelNodeData *node ) const +{ + if ( !node ) + return false; + if ( node->type() == QgsSettingsTreeModelNodeData::Type::Setting ) + { + if ( node->name().contains( mFilterText, Qt::CaseInsensitive ) ) + return true; + + // also returns settings for which the parent nodes have a match + QModelIndex index = mSourceModel->node2index( node ).parent(); + while ( ( index.isValid() ) ) + { + QgsSettingsTreeModelNodeData *parentNode = mSourceModel->index2node( mSourceModel->index( index.row(), static_cast( QgsSettingsTreeModel::Column::Name ), index.parent() ) ); + if ( parentNode->name().contains( mFilterText, Qt::CaseInsensitive ) ) + return true; + + index = index.parent(); + } + return false; + } + else + { + // show all children if name of node matches + if ( node->name().contains( mFilterText, Qt::CaseInsensitive ) ) + return true; + + const auto constChildren = node->children(); + for ( QgsSettingsTreeModelNodeData *child : constChildren ) + { + if ( nodeShown( child ) ) + { + return true; + } + } + return false; + } +} + diff --git a/src/gui/settings/qgssettingstreemodel.h b/src/gui/settings/qgssettingstreemodel.h new file mode 100644 index 00000000000..073c25aba26 --- /dev/null +++ b/src/gui/settings/qgssettingstreemodel.h @@ -0,0 +1,248 @@ +/*************************************************************************** + qgssettingstreemodel.h + -------------------------------------- + Date : January 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSSETTINGSTREEMODEL_H +#define QGSSETTINGSTREEMODEL_H + + +#include "qgis_sip.h" +#include "qgis_gui.h" + +#include +#include +#include + +class QgsSettingsEntryBase; +class QgsSettingsTreeNode; +class QgsSettingsTreeModel; +class QgsSettingsTreeNamedListNode; + +#ifndef SIP_RUN + +///@cond PRIVATE + +/** + * \ingroup gui + * \class QgsSettingsTreeNodeData + * \brief QgsSettingsTree holds data of the tree model for the settings tree. + * + * \note Not available in Python bindings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsTreeModelNodeData : public QObject +{ + Q_OBJECT + public: + + //! Type of tree element + enum class Type + { + RootNode, + TreeNode, + NamedListTreeNode, + NamedListItem, + Setting + }; + + //! Constructor for the tree node data + static QgsSettingsTreeModelNodeData *createRootNodeData( const QgsSettingsTreeNode *rootNode, QObject *parent ); + + //! Apply changes to the settings + void applyChanges(); + + //! Returns if the node is the root node + bool isRoot() const { return mParent == nullptr; } + + //! Returns the dynamic key parts of the named list parent tree nodes + QStringList namedParentNodes() const { return mNamedParentNodes; } + + //! Returns the children nodes of the node (setting or tree node) + QList children() const {return mChildren;} + + //! Returns the parent of the node + QgsSettingsTreeModelNodeData *parent() const {return mParent;} + + //! Returns the type of the node (setting or tree node) + Type type() const {return mType;} + + //! Returns the name of the node (setting or tree node) + QString name() const {return mName;} + + //! Returns the value of the node (setting or tree node) + QVariant value() const {return mValue;} + + //! Returns the value of the node (setting or tree node) + QVariant originalValue() const {return mOriginalValue;} + + //! Sets the \a value of the setting node + bool setValue( const QVariant &value ); + + //! Returns if the setting exists (value is set) + bool exists() const {return mExists;} + + //! Returns if the setting is edited + bool isEdited() const {return mIsEdited;} + + /** + * Returns a pointer to the setting of the node or NULLPTR if the + * setting does not exist. + */ + const QgsSettingsEntryBase *setting() const {return mSetting;} + + private: + //! Private constructor, use createRootNodeData instead + QgsSettingsTreeModelNodeData( QObject *parent ) : QObject( parent ) {} + void addChildForTreeNode( const QgsSettingsTreeNode *node ); + void addChildForNamedListItemNode( const QString &item, const QgsSettingsTreeNamedListNode *namedListNode ); + void addChildForSetting( const QgsSettingsEntryBase *setting ); + void fillChildren(); + + Type mType = Type::TreeNode; + QString mName; + QVariant mValue; + QVariant mOriginalValue; + QStringList mNamedParentNodes; + bool mExists = false; + bool mIsEdited = false; + + QList mChildren; + QgsSettingsTreeModelNodeData *mParent = nullptr; + + const QgsSettingsTreeNode *mTreeNode = nullptr; + const QgsSettingsEntryBase *mSetting = nullptr; +}; + + +/** + * \ingroup gui + * \class QgsSettingsTreeItemDelegate + * \brief QgsSettingsTreeItemDelegate allows editing the settings in the settings tree + * + * \note Not available in Python bindings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsTreeItemDelegate : public QItemDelegate +{ + Q_OBJECT + + public: + //! Constructor + explicit QgsSettingsTreeItemDelegate( QgsSettingsTreeModel *model, QObject *parent = nullptr ); + + QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const override; + void setEditorData( QWidget *editor, const QModelIndex &index ) const override; + void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const override; + + private: + QgsSettingsTreeModel *mModel = nullptr; +}; + +///@endcond + +#endif + + +/** + * \ingroup gui + * \class QgsSettingsTreeModel + * \brief QgsSettingsTreeModel is a tree model for the settings tree. + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsTreeModel : public QAbstractItemModel +{ + Q_OBJECT + public: + + //! Columns + enum class Column + { + Name, //!< Name + Value, //!< Value + Description, //!< Description + }; + + //! Constructor + QgsSettingsTreeModel( QgsSettingsTreeNode *rootNode = nullptr, QObject *parent = nullptr ); + + ~QgsSettingsTreeModel(); + + //! Apply pending changes in the model to the corresponding settings + void applyChanges(); + + /** + * Returns settings tree node for given \a index or the root node if the index is invalid. + */ + QgsSettingsTreeModelNodeData *index2node( const QModelIndex &index ) const SIP_SKIP; + + //! Returns the index from the settings tree node + QModelIndex node2index( QgsSettingsTreeModelNodeData *node ) const SIP_SKIP; + + + QModelIndex index( int row, int column, const QModelIndex &parent ) const override; + QModelIndex parent( const QModelIndex &child ) const override; + int rowCount( const QModelIndex &parent ) const override; + int columnCount( const QModelIndex &parent ) const override; + QVariant data( const QModelIndex &index, int role ) const override; + QVariant headerData( int section, Qt::Orientation orientation, int role ) const override; + Qt::ItemFlags flags( const QModelIndex &index ) const override; + bool setData( const QModelIndex &index, const QVariant &value, int role ) override; + + private: + QModelIndex indexOfParentSettingsTreeNode( QgsSettingsTreeModelNodeData *parentNode ) const; + + QgsSettingsTreeModelNodeData *mRootNode = nullptr; + + QColor mEditedColorBack; + QColor mEditedColorFore; + QColor mNotSetColor; + +}; + +/** + * \ingroup gui + * \class QgsSettingsTreeProxyModel + * \brief QgsSettingsTreeProxyModel allows filtering the settings tree + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsTreeProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + public: + //! Constructor + QgsSettingsTreeProxyModel( QgsSettingsTreeNode *rootNode = nullptr, QObject *parent = nullptr ); + + //! Apply pending changes in the model to the corresponding settings + void applyChanges() {mSourceModel->applyChanges();} + + public slots: + //! Sets the filter text + void setFilterText( const QString &filterText = QString() ); + + + protected: + bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const override; + + private: + QgsSettingsTreeModel *mSourceModel = nullptr; + + bool nodeShown( QgsSettingsTreeModelNodeData *node ) const; + QString mFilterText; +}; + +#endif // QGSSETTINGSTREEMODEL_H diff --git a/src/gui/settings/qgssettingstreewidget.cpp b/src/gui/settings/qgssettingstreewidget.cpp new file mode 100644 index 00000000000..8f7c25cff84 --- /dev/null +++ b/src/gui/settings/qgssettingstreewidget.cpp @@ -0,0 +1,68 @@ +/*************************************************************************** + qgssettingstreewidget.h + -------------------------------------- + Date : April 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "qgssettingstreewidget.h" +#include "qgssettingstreemodel.h" +#include "qgssettingstree.h" + +#include +#include +#include +#include + + +QgsSettingsTreeWidget::QgsSettingsTreeWidget( QWidget *parent ) + : QWidget( parent ) + , QgsOptionsDialogHighlightWidget( this ) +{ + setObjectName( QStringLiteral( "mSettingsTreeWidget" ) ); + + QVBoxLayout *mainLayout = new QVBoxLayout( this ); + mainLayout->setContentsMargins( 0, 0, 0, 0 ); + + mTreeModel = new QgsSettingsTreeProxyModel( QgsSettingsTree::treeRoot() ); + + mTreeView = new QTreeView( this ); + mTreeView->setModel( mTreeModel ); + mTreeView->setItemDelegate( new QgsSettingsTreeItemDelegate( qobject_cast( mTreeModel->sourceModel() ), parent ) ); + mTreeView->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); + mTreeView->setMinimumWidth( 400 ); + mTreeView->resizeColumnToContents( 0 ); + + mainLayout->addWidget( mTreeView ); +} + +void QgsSettingsTreeWidget::applyChanges() const +{ + mTreeModel->applyChanges(); +} + + +bool QgsSettingsTreeWidget::searchText( const QString &text ) +{ + mTreeModel->setFilterText( text ); + return mTreeModel->rowCount() > 0; +} + +bool QgsSettingsTreeWidget::highlightText( const QString &text ) +{ + Q_UNUSED( text ); + return true; +} + +void QgsSettingsTreeWidget::reset() +{ + mTreeModel->setFilterText( QString() ); +} diff --git a/src/gui/settings/qgssettingstreewidget.h b/src/gui/settings/qgssettingstreewidget.h new file mode 100644 index 00000000000..13086fc3484 --- /dev/null +++ b/src/gui/settings/qgssettingstreewidget.h @@ -0,0 +1,58 @@ +/*************************************************************************** + qgssettingstreewidget.h + -------------------------------------- + Date : April 2023 + Copyright : (C) 2023 by Denis Rouzaud + Email : denis@opengis.ch + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSSETTINGSTREEWIDGET_H +#define QGSSETTINGSTREEWIDGET_H + +#include "qgis_gui.h" + +#include "qgsoptionsdialoghighlightwidget.h" + + +class QTreeView; + +class QgsSettingsTreeProxyModel; + +/** + * \ingroup gui + * \class QgsSettingsTreeWidget + * \brief QgsSettingsTreeWidget is a widget with the settings tree to visualize, search and edit settings + * + * \since QGIS 3.32 + */ +class GUI_EXPORT QgsSettingsTreeWidget : public QWidget, public QgsOptionsDialogHighlightWidget +{ + Q_OBJECT + public: + //! Constructor + explicit QgsSettingsTreeWidget( QWidget *parent = nullptr ); + + + //! Apply changes to settings value + void applyChanges() const; + + private: + QgsSettingsTreeProxyModel *mTreeModel = nullptr; + QTreeView *mTreeView = nullptr; + + + // QgsOptionsDialogHighlightWidget interface + protected: + bool searchText( const QString &text ) override; + bool highlightText( const QString &text ) override; + void reset() override; +}; + +#endif // QGSSETTINGSTREEWIDGET_H diff --git a/src/ui/qgsadvancedsettingswidget.ui b/src/ui/qgsadvancedsettingswidget.ui index 12c5463c422..42de80b6370 100644 --- a/src/ui/qgsadvancedsettingswidget.ui +++ b/src/ui/qgsadvancedsettingswidget.ui @@ -10,7 +10,13 @@ 610 - + + + 0 + 0 + + + 0 @@ -24,11 +30,17 @@ 0 - + + + + 0 + 0 + + Advanced Settings Editor - + @@ -42,6 +54,13 @@ + + + + Use new settings tree widget (some settings will be missing) + + + @@ -52,26 +71,11 @@ - - - - false - - - - - - QgsSettingsTreeWidget - QWidget -
qgssettingstreewidget.h
- 1 -
-