Skip to content

Commit f9c05c5

Browse files
authored
Merge pull request qgis#59014 from 3nids/settings.fup.2
python implementation of enum settings editor widget wrapper + fix crash
2 parents 079d21f + c2ef9ea commit f9c05c5

File tree

9 files changed

+224
-2
lines changed

9 files changed

+224
-2
lines changed

python/PyQt6/core/additions/qgssettingsentry.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ def __init__(self, key, pluginName, defaultValue, description=str(), options=Qgi
5959
parent = pluginName
6060
super().__init__(key, parent, defaultValueStr, description, options)
6161

62+
def metaEnum(self):
63+
return self.__metaEnum
64+
65+
def typeId(self):
66+
"""
67+
Defines a custom id since this class has not the same API as the cpp implementation
68+
"""
69+
return "py-enumflag"
70+
6271
def value(self, dynamicKeyPart=None):
6372
"""
6473
Get settings value.
@@ -138,5 +147,4 @@ def settingsType(self):
138147
"""
139148
Get the settings entry type.
140149
"""
141-
142150
return self.SettingsType.EnumFlag

python/PyQt6/gui/__init__.py.in

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ __copyright__ = '(C) 2014, Nathan Woodrow'
2424
from qgis.PyQt import QtCore
2525
from qgis._gui import *
2626
from qgis.core import Qgis as _Qgis
27+
from .additions.qgssettingsenumflageditorwrapper import PyQgsSettingsEnumEditorWidgetWrapper
2728

2829
@MONKEYPATCH_INJECTIONS@
2930

@@ -76,3 +77,6 @@ QgsMapLayerAction.EnabledOnlyWhenEditable = _Qgis.MapLayerActionFlag.EnabledOnly
7677
QgsMapLayerAction.EnabledOnlyWhenEditable.is_monkey_patched = True
7778
QgsMapLayerAction.EnabledOnlyWhenEditable.__doc__ = "Action should be shown only for editable layers"
7879
QgsMapLayerAction.Flags = _Qgis.MapLayerActionFlags
80+
81+
# Classes patched
82+
QgsSettingsEnumEditorWidgetWrapper = PyQgsSettingsEnumEditorWidgetWrapper
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
qgssettingsenumflageditorwrapper.py
6+
---------------------
7+
Date : October 2024
8+
Copyright : (C) 2021 by Denis Rouzaud
9+
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
from qgis.PyQt.QtWidgets import QWidget, QComboBox
21+
22+
from qgis.core import QgsSettingsEntryBase
23+
from qgis.gui import QgsSettingsEditorWidgetWrapper
24+
25+
26+
class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
27+
"""
28+
A settings editor widget wrapper for enum settings as PyQgsSettingsEntryEnumFlag
29+
"""
30+
31+
def __init__(self, parent=None, editor=None, setting=None, displayStrings: dict = None):
32+
self.setting = setting
33+
self.editor = editor
34+
self.displayStrings = {}
35+
super().__init__(parent)
36+
if editor is not None and setting is not None:
37+
if displayStrings:
38+
self.displayStrings = displayStrings
39+
self.configureEditor(editor, setting)
40+
41+
def id(self):
42+
return 'py-enum'
43+
44+
def createWrapper(self, parent=None):
45+
return PyQgsSettingsEnumEditorWidgetWrapper(parent)
46+
47+
def setWidgetFromSetting(self):
48+
if self.setting:
49+
return self.setWidgetFromVariant(self.setting.value(self.dynamicKeyPartList()))
50+
return False
51+
52+
def setSettingFromWidget(self):
53+
if self.editor:
54+
self.setting.setValue(self.variantValueFromWidget(), self.dynamicKeyPartList())
55+
return True
56+
else:
57+
return False
58+
59+
def variantValueFromWidget(self):
60+
if self.editor:
61+
return self.setting.defaultValue().__class__(self.editor.currentData())
62+
return None
63+
64+
def setWidgetFromVariant(self, value):
65+
if self.editor:
66+
idx = self.editor.findData(value)
67+
self.editor.setCurrentIndex(idx)
68+
return idx >= 0
69+
return False
70+
71+
def createEditorPrivate(self, parent=None):
72+
return QComboBox(parent)
73+
74+
def configureEditorPrivate(self, editor: QWidget, setting: QgsSettingsEntryBase):
75+
self.setting = setting
76+
if isinstance(editor, QComboBox):
77+
self.editor = editor
78+
for i in range(self.setting.metaEnum().keyCount()):
79+
value = self.setting.metaEnum().value(i)
80+
key = self.setting.metaEnum().key(i)
81+
text = self.displayStrings.get(value, key)
82+
self.editor.addItem(text, value)
83+
return True
84+
else:
85+
return False
86+
87+
def enableAutomaticUpdatePrivate(self):
88+
self.editor.currentIndexChanged.connect(
89+
lambda: self.setting.setValue(self.editor.currentData(), self.dynamicKeyPartList()))

python/PyQt6/gui/auto_generated/settings/qgssettingseditorwidgetwrapper.sip.in

+7
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ If not, the setting will be updated directly at each widget value change.
9494

9595
This must called after :py:func:`~QgsSettingsEditorWidgetWrapper.createEditor` or :py:func:`~QgsSettingsEditorWidgetWrapper.configureEditor`.
9696

97+
.. versionadded:: 3.40
98+
%End
99+
100+
QStringList dynamicKeyPartList() const;
101+
%Docstring
102+
Returns the dynamic key parts
103+
97104
.. versionadded:: 3.40
98105
%End
99106

python/core/additions/qgssettingsentry.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ def __init__(self, key, pluginName, defaultValue, description=str(), options=Qgi
5959
parent = pluginName
6060
super().__init__(key, parent, defaultValueStr, description, options)
6161

62+
def metaEnum(self):
63+
return self.__metaEnum
64+
65+
def typeId(self):
66+
"""
67+
Defines a custom id since this class has not the same API as the cpp implementation
68+
"""
69+
return "py-enumflag"
70+
6271
def value(self, dynamicKeyPart=None):
6372
"""
6473
Get settings value.
@@ -138,5 +147,4 @@ def settingsType(self):
138147
"""
139148
Get the settings entry type.
140149
"""
141-
142150
return self.SettingsType.EnumFlag

python/gui/__init__.py.in

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ __copyright__ = '(C) 2014, Nathan Woodrow'
2424
from qgis.PyQt import QtCore
2525
from qgis._gui import *
2626
from qgis.core import Qgis as _Qgis
27+
from .additions.qgssettingsenumflageditorwrapper import PyQgsSettingsEnumEditorWidgetWrapper
2728

2829
@MONKEYPATCH_INJECTIONS@
2930

@@ -83,3 +84,6 @@ QgsSettingsBoolEditorWidgetWrapper = QgsSettingsBoolCheckBoxWrapper
8384
QgsSettingsIntegerEditorWidgetWrapper = QgsSettingsIntegerSpinBoxWrapper
8485
QgsSettingsDoubleEditorWidgetWrapper = QgsSettingsDoubleSpinBoxWrapper
8586
QgsSettingsColorEditorWidgetWrapper = QgsSettingsColorButtonWrapper
87+
88+
# Classes patched
89+
QgsSettingsEnumEditorWidgetWrapper = PyQgsSettingsEnumEditorWidgetWrapper
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
qgssettingsenumflageditorwrapper.py
6+
---------------------
7+
Date : October 2024
8+
Copyright : (C) 2021 by Denis Rouzaud
9+
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
from qgis.PyQt.QtWidgets import QWidget, QComboBox
21+
22+
from qgis.core import QgsSettingsEntryBase
23+
from qgis.gui import QgsSettingsEditorWidgetWrapper
24+
25+
26+
class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
27+
"""
28+
A settings editor widget wrapper for enum settings as PyQgsSettingsEntryEnumFlag
29+
"""
30+
31+
def __init__(self, parent=None, editor=None, setting=None, displayStrings: dict = None):
32+
self.setting = setting
33+
self.editor = editor
34+
self.displayStrings = {}
35+
super().__init__(parent)
36+
if editor is not None and setting is not None:
37+
if displayStrings:
38+
self.displayStrings = displayStrings
39+
self.configureEditor(editor, setting)
40+
41+
def id(self):
42+
return 'py-enum'
43+
44+
def createWrapper(self, parent=None):
45+
return PyQgsSettingsEnumEditorWidgetWrapper(parent)
46+
47+
def setWidgetFromSetting(self):
48+
if self.setting:
49+
return self.setWidgetFromVariant(self.setting.value(self.dynamicKeyPartList()))
50+
return False
51+
52+
def setSettingFromWidget(self):
53+
if self.editor:
54+
self.setting.setValue(self.variantValueFromWidget(), self.dynamicKeyPartList())
55+
return True
56+
else:
57+
return False
58+
59+
def variantValueFromWidget(self):
60+
if self.editor:
61+
return self.setting.defaultValue().__class__(self.editor.currentData())
62+
return None
63+
64+
def setWidgetFromVariant(self, value):
65+
if self.editor:
66+
idx = self.editor.findData(value)
67+
self.editor.setCurrentIndex(idx)
68+
return idx >= 0
69+
return False
70+
71+
def createEditorPrivate(self, parent=None):
72+
return QComboBox(parent)
73+
74+
def configureEditorPrivate(self, editor: QWidget, setting: QgsSettingsEntryBase):
75+
self.setting = setting
76+
if isinstance(editor, QComboBox):
77+
self.editor = editor
78+
for i in range(self.setting.metaEnum().keyCount()):
79+
value = self.setting.metaEnum().value(i)
80+
key = self.setting.metaEnum().key(i)
81+
text = self.displayStrings.get(value, key)
82+
self.editor.addItem(text, value)
83+
return True
84+
else:
85+
return False
86+
87+
def enableAutomaticUpdatePrivate(self):
88+
self.editor.currentIndexChanged.connect(
89+
lambda: self.setting.setValue(self.editor.currentData(), self.dynamicKeyPartList()))

python/gui/auto_generated/settings/qgssettingseditorwidgetwrapper.sip.in

+7
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ If not, the setting will be updated directly at each widget value change.
9494

9595
This must called after :py:func:`~QgsSettingsEditorWidgetWrapper.createEditor` or :py:func:`~QgsSettingsEditorWidgetWrapper.configureEditor`.
9696

97+
.. versionadded:: 3.40
98+
%End
99+
100+
QStringList dynamicKeyPartList() const;
101+
%Docstring
102+
Returns the dynamic key parts
103+
97104
.. versionadded:: 3.40
98105
%End
99106

src/gui/settings/qgssettingseditorwidgetwrapper.h

+6
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ class GUI_EXPORT QgsSettingsEditorWidgetWrapper : public QObject
9494
*/
9595
void configureAutomaticUpdate( QDialog *dialog = nullptr );
9696

97+
/**
98+
* Returns the dynamic key parts
99+
* \since QGIS 3.40
100+
*/
101+
QStringList dynamicKeyPartList() const {return mDynamicKeyPartList;}
102+
97103

98104
protected:
99105
//! Creates the widgets

0 commit comments

Comments
 (0)