Skip to content

Commit e08fdaa

Browse files
committed
[processing] support for expressions in numerical values in modeler
includes cleanup of modeler, to adapt to latest changes in parameters architecture
1 parent fe5d016 commit e08fdaa

10 files changed

+127
-380
lines changed

python/plugins/processing/core/Processing.py

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
from processing.core.alglist import algList
5555

5656
from processing.modeler.ModelerAlgorithmProvider import ModelerAlgorithmProvider
57-
from processing.modeler.ModelerOnlyAlgorithmProvider import ModelerOnlyAlgorithmProvider
5857
from processing.algs.qgis.QGISAlgorithmProvider import QGISAlgorithmProvider
5958
from processing.algs.grass.GrassAlgorithmProvider import GrassAlgorithmProvider
6059
from processing.algs.grass7.Grass7AlgorithmProvider import Grass7AlgorithmProvider

python/plugins/processing/core/parameters.py

+35-6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import os
3333
from inspect import isclass
3434
from copy import deepcopy
35+
import numbers
3536

3637
from qgis.utils import iface
3738
from qgis.PyQt.QtCore import QCoreApplication
@@ -40,6 +41,7 @@
4041

4142
from processing.tools.vector import resolveFieldIndex, features
4243
from processing.tools import dataobjects
44+
from processing.core.outputs import OutputNumber
4345

4446
def parseBool(s):
4547
if s is None or s == str(None).lower():
@@ -192,6 +194,9 @@ def wrapper(self, dialog, row=0, col=0):
192194

193195
def evaluate(self, alg):
194196
pass
197+
198+
def evaluateForModeler(self, value, model):
199+
return value
195200

196201
class ParameterBoolean(Parameter):
197202

@@ -810,6 +815,7 @@ def setValue(self, n):
810815
self.value = float(v)
811816
return True
812817
except:
818+
raise
813819
return False
814820
else:
815821
try:
@@ -826,6 +832,7 @@ def setValue(self, n):
826832
self.value = value
827833
return True
828834
except:
835+
raise
829836
return False
830837

831838
def getAsScriptCode(self):
@@ -843,8 +850,8 @@ def fromScriptCode(self, line):
843850
default = definition.strip()[len('number') + 1:] or None
844851
return ParameterNumber(name, descName, default=default, optional=isOptional)
845852

846-
def _evaluate(self):
847-
exp = QgsExpression(self.value)
853+
def _evaluate(self, value):
854+
exp = QgsExpression(value)
848855
if exp.hasParserError():
849856
raise ValueError(self.tr("Error in parameter expression: ") + exp.parserErrorString())
850857
result = exp.evaluate(_expressionContext())
@@ -853,7 +860,26 @@ def _evaluate(self):
853860
return result
854861

855862
def evaluate(self, alg):
856-
self.value = self._evaluate(self.value)
863+
if isinstance(self.value, basestring):
864+
self.value = self._evaluate(self.value)
865+
866+
def evaluateForModeler(self, value, model):
867+
if isinstance(value, numbers.Number):
868+
return value
869+
variables = {}
870+
for param in model.parameters:
871+
if isinstance(param, ParameterNumber):
872+
variables["@" + param.name] = param.value
873+
for alg in model.algs.values():
874+
for out in alg.algorithm.outputs:
875+
if isinstance(out, OutputNumber):
876+
variables["@%s_%s" % (alg.name, out.name)] = out.value
877+
for k,v in variables.iteritems():
878+
print k,v
879+
value = value.replace(k,unicode(v))
880+
881+
print value
882+
return value
857883

858884
def expressionContext(self):
859885
return _expressionContext()
@@ -1427,9 +1453,12 @@ def getParameterFromString(s):
14271453
isAdvanced = True
14281454
tokens = s.split("|")
14291455
params = [t if unicode(t) != unicode(None) else None for t in tokens[1:]]
1430-
clazz = getattr(sys.modules[__name__], tokens[0])
1431-
param = clazz(*params)
1432-
param.isAdvanced = isAdvanced
1456+
try:
1457+
clazz = getattr(sys.modules[__name__], tokens[0])
1458+
param = clazz(*params)
1459+
param.isAdvanced = isAdvanced
1460+
except:
1461+
return None
14331462
else: # try script syntax
14341463
for paramClass in paramClasses:
14351464
try:

python/plugins/processing/gui/NumberInputPanel.py

+34-5
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@
3535
from qgis.core import (QgsDataSourceUri,
3636
QgsCredentials,
3737
QgsExpression,
38-
QgsRasterLayer)
38+
QgsRasterLayer,
39+
QgsExpressionContextScope)
3940
from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog
4041
from qgis.utils import iface
42+
from processing.core.parameters import ParameterNumber
43+
from processing.core.outputs import OutputNumber
44+
from processing.modeler.ModelerAlgorithm import ValueFromInput, ValueFromOutput, CompoundValue
4145

4246
pluginPath = os.path.split(os.path.dirname(__file__))[0]
4347
WIDGET, BASE = uic.loadUiType(
@@ -48,18 +52,27 @@ class NumberInputPanel(BASE, WIDGET):
4852

4953
hasChanged = pyqtSignal()
5054

51-
def __init__(self, param):
55+
def __init__(self, param, modelParametersDialog=None):
5256
super(NumberInputPanel, self).__init__(None)
5357
self.setupUi(self)
5458

5559
self.param = param
56-
self.text = param.default
57-
60+
self.modelParametersDialog = modelParametersDialog
61+
if param.default:
62+
self.setValue(param.default)
5863
self.btnSelect.clicked.connect(self.showExpressionsBuilder)
5964
self.leText.textChanged.connect(lambda: self.hasChanged.emit())
6065

6166
def showExpressionsBuilder(self):
6267
context = self.param.expressionContext()
68+
if self.modelParametersDialog is not None:
69+
context.popScope()
70+
values = self.modelParametersDialog.getAvailableValuesOfType(ParameterNumber, OutputNumber)
71+
modelerScope = QgsExpressionContextScope()
72+
for value in values:
73+
name = value.name if isinstance(value, ValueFromInput) else "%s_%s" % (value.alg, value.output)
74+
modelerScope.setVariable(name, 1)
75+
context.appendScope(modelerScope)
6376
dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, 'generic', context)
6477
dlg.setWindowTitle(self.tr('Expression based input'))
6578
if dlg.exec_() == QDialog.Accepted:
@@ -69,7 +82,23 @@ def showExpressionsBuilder(self):
6982

7083

7184
def getValue(self):
72-
return self.leText.text()
85+
if self.modelParametersDialog:
86+
value = self.leText.text()
87+
values = []
88+
for param in self.modelParametersDialog.model.parameters:
89+
if isinstance(param, ParameterNumber):
90+
if "@" + param.name in value:
91+
values.append(ValueFromInput(param.name))
92+
for alg in self.modelParametersDialog.model.algs.values():
93+
for out in alg.algorithm.outputs:
94+
if isinstance(out, OutputNumber) and "@%s_%s" % (alg.name, out.name) in value:
95+
values.append(ValueFromOutput(alg.name, out.name))
96+
if values:
97+
return CompoundValue(values, value)
98+
else:
99+
return value
100+
else:
101+
return self.leText.text()
73102

74103
def setValue(self, value):
75104
self.leText.setText(unicode(value))

python/plugins/processing/gui/wrappers.py

+5-29
Original file line numberDiff line numberDiff line change
@@ -455,39 +455,15 @@ class NumberWidgetWrapper(WidgetWrapper):
455455

456456
def createWidget(self):
457457
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
458-
return NumberInputPanel(self.param)
458+
return NumberInputPanel(self.param, None)
459459
else:
460-
widget = QComboBox()
461-
widget.setEditable(True)
462-
files = self.dialog.getAvailableValuesOfType(ParameterNumber, OutputNumber)
463-
for f in files:
464-
widget.addItem(self.dialog.resolveValueDescription(f), f)
465-
return widget
460+
return NumberInputPanel(self.param, self.dialog)
466461

467462
def setValue(self, value):
468-
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
469-
self.widget.setValue(value)
470-
else:
471-
self.setComboValue(value)
472-
463+
self.widget.setValue(value)
464+
473465
def value(self):
474-
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
475-
return self.widget.getValue()
476-
else:
477-
def validator(v):
478-
if str(v).strip():
479-
try:
480-
if self.param.isInteger:
481-
int(v)
482-
else:
483-
float(v)
484-
return True
485-
except:
486-
return False
487-
else:
488-
return self.param.optional
489-
return self.comboValue(validator)
490-
466+
return self.widget.getValue()
491467

492468
class RasterWidgetWrapper(WidgetWrapper):
493469

python/plugins/processing/modeler/CalculatorModelerAlgorithm.py

-145
This file was deleted.

0 commit comments

Comments
 (0)