Skip to content

Commit

Permalink
[FEATURE][processing] New "Add values by expression" option for
Browse files Browse the repository at this point in the history
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)
nyalldawson committed Apr 30, 2019
1 parent ee7daa8 commit 9f43f2f
Showing 1 changed file with 46 additions and 14 deletions.
60 changes: 46 additions & 14 deletions python/plugins/processing/gui/BatchPanel.py
Original file line number Diff line number Diff line change
@@ -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.