Skip to content

Commit

Permalink
[processing] Input parameter name for in place algorithms is not
Browse files Browse the repository at this point in the history
always fixed, so ensure we correctly obtain and use the correct
input parameter name
  • Loading branch information
nyalldawson committed Feb 3, 2021
1 parent c6895d9 commit f5d3164
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 @@ -204,8 +204,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 f5d3164

Please sign in to comment.