Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[processing] Input parameter name for in place algorithms is not
always fixed, so ensure we correctly obtain and use the correct
input parameter name

(cherry picked from commit 0a2b99c)
  • Loading branch information
nyalldawson committed Feb 19, 2021
1 parent 122725b commit ac6df58
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 13 deletions.
6 changes: 5 additions & 1 deletion python/plugins/processing/gui/AlgorithmDialog.py
Expand Up @@ -72,7 +72,11 @@ def __init__(self, alg, in_place=False, parent=None):
self.buttonBox().addButton(self.runAsBatchButton,
QDialogButtonBox.ResetRole) # reset role to ensure left alignment
else:
self.mainWidget().setParameters({'INPUT': self.active_layer})
in_place_input_parameter_name = 'INPUT'
if hasattr(alg, 'inputParameterName'):
in_place_input_parameter_name = alg.inputParameterName()

self.mainWidget().setParameters({in_place_input_parameter_name: self.active_layer})

self.runAsBatchButton = None
has_selection = self.active_layer and (self.active_layer.selectedFeatureCount() > 0)
Expand Down
27 changes: 19 additions & 8 deletions python/plugins/processing/gui/AlgorithmExecutor.py
Expand Up @@ -102,7 +102,11 @@ def execute_in_place_run(alg, parameters, context=None, feedback=None, raise_exc
except AttributeError:
pass

active_layer = parameters['INPUT']
in_place_input_parameter_name = 'INPUT'
if hasattr(alg, 'inputParameterName'):
in_place_input_parameter_name = alg.inputParameterName()

active_layer = parameters[in_place_input_parameter_name]

# Run some checks and prepare the layer for in-place execution by:
# - getting the active layer and checking that it is a vector
Expand Down Expand Up @@ -137,7 +141,7 @@ def execute_in_place_run(alg, parameters, context=None, feedback=None, raise_exc
active_layer.selectAll()

# Make sure we are working on selected features only
parameters['INPUT'] = QgsProcessingFeatureSourceDefinition(active_layer.id(), True)
parameters[in_place_input_parameter_name] = QgsProcessingFeatureSourceDefinition(active_layer.id(), True)
parameters['OUTPUT'] = 'memory:'

req = QgsFeatureRequest(QgsExpression(r"$id < 0"))
Expand Down Expand Up @@ -300,14 +304,21 @@ def execute_in_place(alg, parameters, context=None, feedback=None):
if context is None:
context = dataobjects.createContext(feedback)

if 'INPUT' not in parameters or not parameters['INPUT']:
parameters['INPUT'] = iface.activeLayer()
in_place_input_parameter_name = 'INPUT'
if hasattr(alg, 'inputParameterName'):
in_place_input_parameter_name = alg.inputParameterName()
in_place_input_layer_name = 'INPUT'
if hasattr(alg, 'inputParameterDescription'):
in_place_input_layer_name = alg.inputParameterDescription()

if in_place_input_parameter_name not in parameters or not parameters[in_place_input_parameter_name]:
parameters[in_place_input_parameter_name] = iface.activeLayer()
ok, results = execute_in_place_run(alg, parameters, context=context, feedback=feedback)
if ok:
if isinstance(parameters['INPUT'], QgsProcessingFeatureSourceDefinition):
layer = alg.parameterAsVectorLayer({'INPUT': parameters['INPUT'].source}, 'INPUT', context)
elif isinstance(parameters['INPUT'], QgsVectorLayer):
layer = parameters['INPUT']
if isinstance(parameters[in_place_input_parameter_name], QgsProcessingFeatureSourceDefinition):
layer = alg.parameterAsVectorLayer({in_place_input_parameter_name: parameters[in_place_input_parameter_name].source}, in_place_input_layer_name, context)
elif isinstance(parameters[in_place_input_parameter_name], QgsVectorLayer):
layer = parameters[in_place_input_parameter_name]
if layer:
layer.triggerRepaint()
return ok, results
Expand Down
6 changes: 5 additions & 1 deletion python/plugins/processing/gui/AlgorithmLocatorFilter.py
Expand Up @@ -188,8 +188,12 @@ def triggerResult(self, result):
dlg.exec_()
return

in_place_input_parameter_name = 'INPUT'
if hasattr(alg, 'inputParameterName'):
in_place_input_parameter_name = alg.inputParameterName()

if [d for d in alg.parameterDefinitions() if
d.name() not in ('INPUT', 'OUTPUT')]:
d.name() not in (in_place_input_parameter_name, 'OUTPUT')]:
dlg = alg.createCustomParametersWidget(parent=iface.mainWindow())
if not dlg:
dlg = AlgorithmDialog(alg, True, parent=iface.mainWindow())
Expand Down
8 changes: 6 additions & 2 deletions python/plugins/processing/gui/ParametersPanel.py
Expand Up @@ -94,6 +94,10 @@ def initWidgets(self):
if isinstance(self.algorithm(), QgsProcessingModelAlgorithm):
widget_context.setModel(self.algorithm())

in_place_input_parameter_name = 'INPUT'
if hasattr(self.algorithm(), 'inputParameterName'):
in_place_input_parameter_name = self.algorithm().inputParameterName()

# Create widgets and put them in layouts
for param in self.algorithm().parameterDefinitions():
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
Expand All @@ -102,7 +106,7 @@ def initWidgets(self):
if param.isDestination():
continue
else:
if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
if self.in_place and param.name() in (in_place_input_parameter_name, 'OUTPUT'):
# don't show the input/output parameter widgets in in-place mode
# we still need to CREATE them, because other wrappers may need to interact
# with them (e.g. those parameters which need the input layer for field
Expand Down Expand Up @@ -155,7 +159,7 @@ def initWidgets(self):
if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
continue

if self.in_place and output.name() in ('INPUT', 'OUTPUT'):
if self.in_place and output.name() in (in_place_input_parameter_name, 'OUTPUT'):
continue

wrapper = QgsGui.processingGuiRegistry().createParameterWidgetWrapper(output, QgsProcessingGui.Standard)
Expand Down
6 changes: 5 additions & 1 deletion python/plugins/processing/gui/ProcessingToolbox.py
Expand Up @@ -248,7 +248,11 @@ def executeAlgorithm(self):
dlg.exec_()
return

if self.in_place_mode and not [d for d in alg.parameterDefinitions() if d.name() not in ('INPUT', 'OUTPUT')]:
in_place_input_parameter_name = 'INPUT'
if hasattr(alg, 'inputParameterName'):
in_place_input_parameter_name = alg.inputParameterName()

if self.in_place_mode and not [d for d in alg.parameterDefinitions() if d.name() not in (in_place_input_parameter_name, 'OUTPUT')]:
parameters = {}
feedback = MessageBarProgress(algname=alg.displayName())
ok, results = execute_in_place(alg, parameters, feedback=feedback)
Expand Down

0 comments on commit ac6df58

Please sign in to comment.