Skip to content

Commit c763b92

Browse files
Rashad Kanavathnyalldawson
authored andcommittedMar 20, 2019
fix #21373 #21374: handle update optional status based on user-input
Parameters are marked required in descriptor file for certian applications but they are only required if a parent parameter has a "certain" value. So initial idea was to make all of those parameters optional from OTB part. So that qgis can work correctly and was a easy fix. But.. we (me and Antonie) decided not to take that route and found a better fix. `OtbParameterChoice` and its wrapper will update optional status of all sub-parameters depending on the value of a choice parameter. A test has been added to check this issue and will be available in next commit.
1 parent f6ad474 commit c763b92

File tree

1 file changed

+71
-52
lines changed

1 file changed

+71
-52
lines changed
 

‎python/plugins/processing/algs/otb/OtbChoiceWidget.py

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,34 @@
2727

2828
from qgis.PyQt.QtWidgets import QComboBox
2929
from qgis.core import (QgsProcessingParameterString,
30-
QgsProcessingOutputString)
30+
QgsProcessingOutputString,
31+
QgsProcessingParameterDefinition)
32+
from qgis.gui import QgsProcessingModelerParameterWidget
3133
from processing.gui.wrappers import (WidgetWrapper,
3234
DIALOG_STANDARD,
3335
DIALOG_BATCH,
3436
DIALOG_MODELER)
3537

38+
# TODO: QGIS 3.8 move this class to processing/gui/
39+
# OtbChoiceWidget is a crucial parameter type in otb provider
40+
# It is the one that can handles required parameters are run-time depending on user input!.
41+
# This idea is indeed different from static list of required/optional parameters from a descriptor file.
42+
# So this class (if treated as first class citizen in processing/gui) have potential
43+
# to be reused in existing or future processing providers.
44+
3645

3746
class OtbChoiceWidgetWrapper(WidgetWrapper):
3847

48+
def __init__(self, param, dialog, row=0, col=0, **kwargs):
49+
self.flagsModified = {}
50+
super().__init__(param, dialog, row=0, col=0, **kwargs)
51+
self.updateAllParameters(None)
52+
3953
def createWidget(self):
4054
widget = QComboBox()
4155
widget.addItems(self.param.options)
4256
if self.dialogType in(DIALOG_MODELER, DIALOG_STANDARD):
43-
widget.currentIndexChanged.connect(self.valueChanged)
57+
widget.currentIndexChanged.connect(self.updateAllParameters)
4458
return widget
4559

4660
def get_algorithm(self):
@@ -49,46 +63,59 @@ def get_algorithm(self):
4963
else:
5064
return self.dialog.algorithm()
5165

52-
def setWrapperVisible(self, name, visible):
53-
if self.dialogType == DIALOG_STANDARD:
66+
def __updateWrapper(self, name, visible):
67+
if self.dialogType == DIALOG_BATCH:
68+
return
69+
elif self.dialogType == DIALOG_STANDARD:
5470
if self.dialog.mainWidget() is None:
5571
return
56-
# For compatibility with 3.x API, we need to check whether the wrapper is
57-
# the deprecated WidgetWrapper class. If not, it's the newer
58-
# QgsAbstractProcessingParameterWidgetWrapper class
59-
# TODO QGIS 4.0 - remove is_python_wrapper logic
60-
is_python_wrapper = issubclass(self.dialog.mainWidget().wrappers[name].__class__, WidgetWrapper)
61-
if is_python_wrapper:
62-
self.dialog.mainWidget().wrappers[name].widget.setVisible(visible)
63-
if self.dialog.mainWidget().wrappers[name].label:
64-
self.dialog.mainWidget().wrappers[name].label.setVisible(visible)
65-
else:
66-
self.dialog.mainWidget().wrappers[name].wrappedWidget().setVisible(visible)
67-
if self.dialog.mainWidget().wrappers[name].wrappedLabel():
68-
self.dialog.mainWidget().wrappers[name].wrappedLabel().setVisible(visible)
72+
if name in self.dialog.mainWidget().wrappers:
73+
self.__setWrapperVisibility(self.dialog.mainWidget().wrappers[name], visible)
74+
75+
#Fur Qgis modeler
6976
else:
70-
# For compatibility with 3.x API, we need to check whether the wrapper is
71-
# the deprecated WidgetWrapper class. If not, it's the newer
72-
# QgsAbstractProcessingParameterWidgetWrapper class
73-
# TODO QGIS 4.0 - remove is_python_wrapper logic
7477
if name in self.dialog.wrappers:
75-
is_python_wrapper = issubclass(self.dialog.wrappers[name].__class__, WidgetWrapper)
76-
if is_python_wrapper:
77-
self.dialog.wrappers[name].widget.setVisible(visible)
78-
if self.dialog.wrappers[name].label:
79-
self.dialog.wrappers[name].label.setVisible(visible)
80-
else:
81-
self.dialog.wrappers[name].setVisible(visible)
82-
if name in self.dialog.widget_labels:
83-
self.dialog.widget_labels[name].setVisible(visible)
78+
self.__setWrapperVisibility(self.dialog.wrappers[name], visible)
79+
if name in self.dialog.widget_labels:
80+
self.dialog.widget_labels[name].setVisible(visible)
81+
82+
def __setWrapperVisibility(self, wrapper, v):
83+
# For compatibility with 3.x API, we need to check whether the wrapper is
84+
# the deprecated WidgetWrapper class. If not, it's the newer
85+
# QgsAbstractProcessingParameterWidgetWrapper class
86+
# TODO QGIS 4.0 - remove is_python_wrapper logic
87+
if issubclass(wrapper.__class__, WidgetWrapper):
88+
wrapper.widget.setVisible(v)
89+
if wrapper.label:
90+
wrapper.label.setVisible(v)
91+
elif issubclass(wrapper.__class__, QgsProcessingModelerParameterWidget):
92+
wrapper.setVisible(v)
93+
else:
94+
wrapper.wrappedWidget().setVisible(v)
95+
if wrapper.wrappedLabel():
96+
wrapper.wrappedLabel().setVisible(v)
8497

85-
def valueChanged(self, value):
98+
def updateAllParameters(self, current_value):
8699
for parameter in self.get_algorithm().parameterDefinitions():
87100
if not 'group_key' in parameter.metadata() or parameter.metadata()['group_key'] != self.param.name():
88101
continue
89102
name = parameter.name()
90-
v = self.value() == parameter.metadata()['group_value']
91-
self.setWrapperVisible(name, v)
103+
choice_key = parameter.metadata()['group_key']
104+
if choice_key and choice_key + "." in name:
105+
choice_param = self.get_algorithm().parameterDefinition(choice_key)
106+
if current_value is None:
107+
current_value = choice_param.defaultValue()
108+
pattern = "{}.{}.".format(choice_key, choice_param.getValueAsText(current_value))
109+
if not pattern in name:
110+
flags = self.get_algorithm().parameterDefinition(name).flags()
111+
if not flags & QgsProcessingParameterDefinition.FlagOptional:
112+
self.flagsModified[name] = True
113+
self.get_algorithm().parameterDefinition(name).setFlags(QgsProcessingParameterDefinition.FlagOptional)
114+
self.__updateWrapper(name, False)
115+
else:
116+
if name in self.flagsModified.keys():
117+
self.get_algorithm().parameterDefinition(name).setFlags(QgsProcessingParameterDefinition.FlagAdvanced)
118+
self.__updateWrapper(name, True)
92119

93120
def setValue(self, value):
94121
if value in self.param.options:
@@ -101,29 +128,16 @@ def value(self):
101128
return self.widget.currentText()
102129

103130
def postInitialize(self, wrappers):
104-
if self.dialogType == DIALOG_BATCH:
105-
return
106-
131+
# if self.dialogType == DIALOG_BATCH:
132+
# return
133+
self.updateAllParameters(current_value=None)
107134
for parameter in self.get_algorithm().parameterDefinitions():
108135
if not 'group_key' in parameter.metadata() or parameter.metadata()['group_key'] != self.param.name():
109136
continue
110-
name = parameter.name()
111-
v = self.value() == parameter.metadata()['group_value']
112137
for wrapper in wrappers:
113-
# For compatibility with 3.x API, we need to check whether the wrapper is
114-
# the deprecated WidgetWrapper class. If not, it's the newer
115-
# QgsAbstractProcessingParameterWidgetWrapper class
116-
# TODO QGIS 4.0 - remove is_python_wrapper logic
117-
is_python_wrapper = issubclass(wrapper.__class__, WidgetWrapper)
118-
if wrapper.param.name() == name:
119-
if is_python_wrapper:
120-
wrapper.widget.setVisible(v)
121-
if wrapper.label:
122-
wrapper.label.setVisible(v)
123-
else:
124-
wrapper.wrappedWidget().setVisible(v)
125-
if wrapper.wrappedLabel():
126-
wrapper.wrappedLabel().setVisible(v)
138+
if wrapper.param.name() == parameter.name():
139+
v = self.value() == parameter.metadata()['group_value']
140+
self.__setWrapperVisibility(wrapper, v)
127141

128142

129143
from qgis.core import QgsProcessingParameterDefinition
@@ -148,6 +162,11 @@ def __init__(self, name='', description='', options=[], default=None, isSource=F
148162
self.default = 0
149163
self.value = self.default
150164

165+
def getValueAsText(self, value):
166+
if not value in self.options:
167+
value = self.options[int(value)]
168+
return value
169+
151170
def setValue(self, value):
152171
if value is None:
153172
self.value = 0

0 commit comments

Comments
 (0)
Please sign in to comment.