Skip to content

Commit

Permalink
[sextante] several fixes for supporting optional parameters in modeler
Browse files Browse the repository at this point in the history
  • Loading branch information
volaya committed Apr 13, 2013
1 parent 3b205d3 commit 065b357
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 43 deletions.
27 changes: 14 additions & 13 deletions python/plugins/sextante/algs/ftools/ConvexHull.py
Expand Up @@ -59,7 +59,7 @@ def defineCharacteristics(self):
self.name = "Convex hull"
self.group = "Vector geometry tools"
self.addParameter(ParameterVector(ConvexHull.INPUT, "Input layer", ParameterVector.VECTOR_TYPE_ANY))
self.addParameter(ParameterTableField(ConvexHull.FIELD, "Field", ConvexHull.INPUT))
self.addParameter(ParameterTableField(ConvexHull.FIELD, "Field (optional, only used if creating convex hulls by classes)", ConvexHull.INPUT, optional = True))
self.addParameter(ParameterSelection(ConvexHull.METHOD, "Method", ConvexHull.METHODS))
self.addOutput(OutputVector(ConvexHull.OUTPUT, "Convex hull"))

Expand All @@ -71,22 +71,23 @@ def processAlgorithm(self, progress):
GEOS_EXCEPT = True
FEATURE_EXCEPT = True

index = layer.fieldNameIndex(fieldName)
fType = layer.pendingFields()[index].type()

f = QgsField("value")
f.setType(QVariant.String)
f.setLength(255)
if useField:
if fType == QVariant.Int:
f.setType(QVariant.Int)
f.setLength(20)
elif fType == QVariant.Double:
f.setType(QVariant.Double)
f.setLength(20)
f.setPrecision(6)
else:
f.setType(QVariant.String)
f.setLength(255)
index = layer.fieldNameIndex(fieldName)
fType = layer.pendingFields()[index].type()
if fType == QVariant.Int:
f.setType(QVariant.Int)
f.setLength(20)
elif fType == QVariant.Double:
f.setType(QVariant.Double)
f.setLength(20)
f.setPrecision(6)
else:
f.setType(QVariant.String)
f.setLength(255)

fields = [QgsField("id", QVariant.Int, "", 20),
f,
Expand Down
2 changes: 0 additions & 2 deletions python/plugins/sextante/core/Sextante.py
Expand Up @@ -268,8 +268,6 @@ def runAlgorithm(algOrName, onFinish, *args):
return
else:
i = 0

settrace()
for param in alg.parameters:
if not param.hidden:
if not param.setValue(args[i]):
Expand Down
6 changes: 3 additions & 3 deletions python/plugins/sextante/modeler/ModelerAlgorithm.py
Expand Up @@ -409,11 +409,11 @@ def prepareAlgorithm(self, alg, iAlg):
aap = self.algParameters[iAlg][param.name]
if aap == None:
if isinstance(param, ParameterExtent):
value = self.getValueFromAlgorithmAndParameter(aap)
if value is None:
value = self.getMinCoveringExtent()
value = self.getMinCoveringExtent()
if not param.setValue(value):
raise GeoAlgorithmExecutionException("Wrong value: " + str(value))
else:
param.setValue(None)
continue
if isinstance(param, ParameterMultipleInput):
value = self.getValueFromAlgorithmAndParameter(aap)
Expand Down
49 changes: 34 additions & 15 deletions python/plugins/sextante/modeler/ModelerParametersDialog.py
Expand Up @@ -418,7 +418,7 @@ def getWidgetFromParameter(self, param):
elif isinstance(param, ParameterString):
strings = self.getStrings()
if param.multiline:
item = MultilineTextPanel(strings)
item = MultilineTextPanel(strings,self.model)
item.setText(str(param.default))
else:
item = QtGui.QComboBox()
Expand Down Expand Up @@ -597,6 +597,7 @@ def setParamValues(self):

params = self.alg.parameters
outputs = self.alg.outputs

for param in params:
if param.hidden:
continue
Expand Down Expand Up @@ -650,12 +651,16 @@ def setParamTableFieldValue(self, param, widget):
idx = widget.findText(widget.currentText())
if idx < 0:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
value = str(widget.currentText()).strip()
if value == "":
return False
value = AlgorithmAndParameter(AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
s = str(widget.currentText()).strip()
if s == "":
if param.optional:
self.params[param.name] = None
return True
else:
return False
else:
self.params[param.name] = value
self.values[name] = str(widget.currentText())
return True
else:
Expand All @@ -664,16 +669,22 @@ def setParamTableFieldValue(self, param, widget):
return True

def setParamStringValue(self, param, widget):
if param.multiline:
option = widget.getOption()
if param.multiline:
name = self.getSafeNameForHarcodedParameter(param)
paramValue = AlgorithmAndParameter(AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
value = widget.getValue()
if option == MultilineTextPanel.USE_TEXT:
option = widget.getOption()
if option == MultilineTextPanel.USE_TEXT:
if value == "":
return False
name = self.getSafeNameForHarcodedParameter(param)
self.values[name] = value
paramValue = AlgorithmAndParameter(AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = paramValue
if param.optional:
self.params[param.name] = None
return True
else:
return False
else:
self.values[name] = value

self.params[param.name] = paramValue
else:
self.params[param.name] = value
else:
Expand All @@ -684,7 +695,15 @@ def setParamStringValue(self, param, widget):
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = str(widget.currentText())
value = str(widget.currentText()).strip()
if value == "":
if param.optional:
self.values[name] = None
return True
else:
return False
else:
self.values[name] = str(widget.currentText())
else:
value = widget.itemData(widget.currentIndex()).toPyObject()
self.params[param.name] = value
Expand Down
5 changes: 3 additions & 2 deletions python/plugins/sextante/modeler/MultilineTextPanel.py
Expand Up @@ -34,9 +34,10 @@ class MultilineTextPanel(QtGui.QWidget):

USE_TEXT = 0

def __init__(self, options, parent = None):
def __init__(self, options, model, parent = None):
super(MultilineTextPanel, self).__init__(parent)
self.options = options
self.model = model
self.verticalLayout = QtGui.QVBoxLayout(self)
self.verticalLayout.setSpacing(2)
self.verticalLayout.setMargin(0)
Expand Down Expand Up @@ -71,7 +72,7 @@ def setValue(self, value):
if item.alg == value.alg and item.param == value.param:
self.combo.setCurrentIndex(idx)
return
self.combo.setCurrentIndex(idx)
self.combo.setCurrentIndex(0)
value = self.model.getValueFromAlgorithmAndParameter(value)
if value:
self.textBox.setPlainText(str(value))
20 changes: 20 additions & 0 deletions python/plugins/sextante/modeler/models/emptystring.model
@@ -0,0 +1,20 @@
NAME:A model with an empty string
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_V|v|-1|False
120.0,60.0
VALUE:HARDCODEDPARAMVALUE_FORMULA_0===value = 10
VALUE:HARDCODEDPARAMVALUE_FIELD_PRECISION_0===0
VALUE:HARDCODEDPARAMVALUE_FIELD_TYPE_0===0
VALUE:HARDCODEDPARAMVALUE_FIELD_LENGTH_0===10
VALUE:HARDCODEDPARAMVALUE_FIELD_NAME_0===NewField
ALGORITHM:qgis:advancedpythonfieldcalculator
120.0,160.0
None
-1|VECTORLAYER_V
-1|HARDCODEDPARAMVALUE_FIELD_NAME_0
-1|HARDCODEDPARAMVALUE_FIELD_TYPE_0
-1|HARDCODEDPARAMVALUE_FIELD_LENGTH_0
-1|HARDCODEDPARAMVALUE_FIELD_PRECISION_0
None
-1|HARDCODEDPARAMVALUE_FORMULA_0
out
12 changes: 12 additions & 0 deletions python/plugins/sextante/modeler/models/optionalfield.model
@@ -0,0 +1,12 @@
NAME:A model with an optional field
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_V|v|-1|False
120.0,60.0
VALUE:HARDCODEDPARAMVALUE_METHOD_0===0
ALGORITHM:qgis:convexhull
135.0,186.0
None
-1|VECTORLAYER_V
None
-1|HARDCODEDPARAMVALUE_METHOD_0
result
12 changes: 6 additions & 6 deletions python/plugins/sextante/parameters/ParameterExtent.py
Expand Up @@ -39,13 +39,13 @@ def setValue(self, text):
self.value = self.default
return True
tokens = text.split(",")
if len(tokens)!= 5:
if len(tokens)!= 4:
return False
try:
n1 = float(tokens[1])
n2 = float(tokens[2])
n3 = float(tokens[3])
n4 = float(tokens[4])
n1 = float(tokens[0])
n2 = float(tokens[1])
n3 = float(tokens[2])
n4 = float(tokens[3])
self.value=text
return True
except:
Expand All @@ -60,5 +60,5 @@ def serialize(self):

def deserialize(self, s):
tokens = s.split("|")
return ParameterExtent(tokens[0], tokens[1], tokens[2])
return ParameterExtent(tokens[1], tokens[2], tokens[3])

1 change: 1 addition & 0 deletions python/plugins/sextante/parameters/ParameterString.py
Expand Up @@ -35,6 +35,7 @@ def __init__(self, name="", description="", default="", multiline = False, optio
self.default = default
self.value = None
self.multiline = multiline
self.optional = optional

def setValue(self, obj):
if obj is None:
Expand Down
5 changes: 4 additions & 1 deletion python/plugins/sextante/parameters/ParameterTableField.py
Expand Up @@ -36,6 +36,7 @@ def __init__(self, name="", description="", parent=None, datatype=-1, optional=F
self.parent = parent
self.value = None
self.datatype = datatype
self.optional= optional

def getValueAsCommandLineParameter(self):
return "\"" + str(self.value) + "\""
Expand All @@ -44,7 +45,9 @@ def getAsScriptCode(self):
return "##" + self.name + "=field " + str(self.parent)

def setValue(self, field):
if len(field) > 0:
if field is None:
return self.optional
elif len(field) > 0:
self.value = str(field)
else:
return self.optional
Expand Down
42 changes: 42 additions & 0 deletions python/plugins/sextante/tests/ModelerAlgorithmTest.py
Expand Up @@ -121,6 +121,48 @@ def test_modelernotinorder(self):
dataset=gdal.Open(output, GA_ReadOnly)
strhash=hash(str(dataset.ReadAsArray(0).tolist()))
self.assertEqual(strhash,-1557050506)

def test_modeleroptionalfield(self):
outputs=sextante.runalg("modeler:optionalfield",points(),None)
output=outputs['OUTPUT_ALG0']
layer=QGisLayers.getObjectFromUri(output, True)
fields=layer.pendingFields()
expectednames=['id','value','area','perim']
expectedtypes=['Integer','String','Real','Real']
names=[str(f.name()) for f in fields]
types=[str(f.typeName()) for f in fields]
self.assertEqual(expectednames, names)
self.assertEqual(expectedtypes, types)
features=sextante.getfeatures(layer)
self.assertEqual(1, len(features))
feature=features.next()
attrs=feature.attributes()
expectedvalues=["0","all","3592.818848","230.989919"]
values=[str(attr.toString()) for attr in attrs]
self.assertEqual(expectedvalues, values)
wkt='POLYGON((270839.46818665 4458921.97813894,270778.60197966 4458935.96883677,270786.54279065 4458980.04784113,270803.15756434 4458983.84880322,270839.65586926 4458983.16267036,270855.74530134 4458940.79948673,270839.46818665 4458921.97813894))'
self.assertEqual(wkt, str(feature.geometry().exportToWkt()))

def test_modeleremptystring(self):
outputs=sextante.runalg("modeler:emptystring",union(),None)
output=outputs['OUTPUT_LAYER_ALG0']
layer=QGisLayers.getObjectFromUri(output, True)
fields=layer.pendingFields()
expectednames=['ID','POLY_NUM_A','POLY_ST_A','ID_2','POLY_NUM_B','POLY_ST_B','NewField']
expectedtypes=['Integer','Real','String','Integer','Real','String','Integer']
names=[str(f.name()) for f in fields]
types=[str(f.typeName()) for f in fields]
self.assertEqual(expectednames, names)
self.assertEqual(expectedtypes, types)
features=sextante.getfeatures(layer)
self.assertEqual(8, len(features))
feature=features.next()
attrs=feature.attributes()
expectedvalues=["1","1.1","string a","2","1","string a","10"]
values=[str(attr.toString()) for attr in attrs]
self.assertEqual(expectedvalues, values)
wkt='POLYGON((270807.08580285 4458940.1594565,270798.42294527 4458914.62661676,270780.81854858 4458914.21983449,270763.52289518 4458920.715993,270760.3449542 4458926.6570575,270763.78234766 4458958.22561242,270794.30290024 4458942.16424502,270807.08580285 4458940.1594565))'
self.assertEqual(wkt, str(feature.geometry().exportToWkt()))


def suite():
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/tests/QgisAlgsTest.py
Expand Up @@ -142,7 +142,7 @@ def test_qgiscreategrid(self):
self.assertEqual(wkt, str(feature.geometry().exportToWkt()))

def test_qgiscreategridnointeger(self):
outputs=sextante.runalg("qgis:creategrid",0.1,0.1,1,1,0,0,None)
outputs=sextante.runalg("qgis:creategrid",0.1,0.1,1,1,0,0,0,None)
output=outputs['SAVENAME']
layer=QGisLayers.getObjectFromUri(output, True)
fields=layer.pendingFields()
Expand Down

0 comments on commit 065b357

Please sign in to comment.