Skip to content
Permalink
Browse files

[FEATURE][processing] New "Add values by expression" option for

populating batch processing dialog

This option adds news rows using the values from an expression
which returns an array. (As opposed to "Calculate by Expression",
which works only on existing rows).

The intended use case is to allow populating the batch dialog
using complex numeric series, e.g. those created by the "generate_series"
expression function.

For example, adding rows for a batch buffer using the expression

    generate_series(100, 1000, 50)

(results in new rows with values 100, 150, 200, .... 1000)
  • Loading branch information
nyalldawson committed Apr 26, 2019
1 parent ee7daa8 commit 9f43f2f608e08b2be30019c9e288b55622d23264
Showing with 46 additions and 14 deletions.
  1. +46 −14 python/plugins/processing/gui/BatchPanel.py
@@ -130,6 +130,12 @@ def createMenu(self):
calculate_by_expression.setToolTip(self.tr('Calculates parameter values by evaluating an expression'))
self.menu.addAction(calculate_by_expression)

add_by_expression = QAction(QCoreApplication.translate('BatchPanel', 'Add Values by Expression…'),
self.menu)
add_by_expression.triggered.connect(self.addByExpression)
add_by_expression.setToolTip(self.tr('Adds new parameter values by evaluating an expression'))
self.menu.addAction(add_by_expression)

if isinstance(self.parameterDefinition, (QgsProcessingParameterFile,
QgsProcessingParameterMapLayer,
QgsProcessingParameterRasterLayer,
@@ -192,6 +198,18 @@ def calculateByExpression(self):
"""
Calculates parameter values by evaluating expressions.
"""
self.populateByExpression(adding=False)

def addByExpression(self):
"""
Adds new parameter values by evaluating an expression
"""
self.populateByExpression(adding=True)

def populateByExpression(self, adding=False):
"""
Populates the panel using an expression
"""
context = dataobjects.createContext()
expression_context = context.expressionContext()

@@ -211,27 +229,41 @@ def calculateByExpression(self):
expression_context.setHighlightedVariables(highlighted_vars)

dlg = QgsExpressionBuilderDialog(layer=None, context=context.expressionContext())
if adding:
dlg.setExpectedOutputFormat(self.tr('An array of values corresponding to each new row to add'))

if not dlg.exec_():
return

for row in range(self.panel.batchRowCount()):
params = self.panel.parametersForRow(row, warnOnInvalid=False)
if adding:
exp = QgsExpression(dlg.expressionText())
res = exp.evaluate(expression_context)

# remove previous algorithm scope -- we need to rebuild this completely, using the
# other parameter values from the current row
expression_context.popScope()
alg_scope = QgsExpressionContextUtils.processingAlgorithmScope(self.panel.alg, params, context)
if type(res) is not list:
res = [res]

for k, v in params.items():
alg_scope.setVariable(k, v, True)
first_row = self.panel.batchRowCount() if self.panel.batchRowCount() > 1 else 0
for row, value in enumerate(res):
self.setRowValue(row + first_row, value, context)
else:
for row in range(self.panel.batchRowCount()):
params = self.panel.parametersForRow(row, warnOnInvalid=False)

expression_context.appendScope(alg_scope)
# remove previous algorithm scope -- we need to rebuild this completely, using the
# other parameter values from the current row
expression_context.popScope()
alg_scope = QgsExpressionContextUtils.processingAlgorithmScope(self.panel.alg, params, context)

# rebuild a new expression every time -- we don't want the expression compiler to replace
# variables with precompiled values
exp = QgsExpression(dlg.expressionText())
value = exp.evaluate(expression_context)
self.setRowValue(row, value, context)
for k, v in params.items():
alg_scope.setVariable(k, v, True)

expression_context.appendScope(alg_scope)

# rebuild a new expression every time -- we don't want the expression compiler to replace
# variables with precompiled values
exp = QgsExpression(dlg.expressionText())
value = exp.evaluate(expression_context)
self.setRowValue(row, value, context)


class BatchPanel(BASE, WIDGET):

0 comments on commit 9f43f2f

Please sign in to comment.
You can’t perform that action at this time.