[sextante] several fixes for supporting optional parameters in modeler

This commit is contained in:
Victor Olaya 2013-04-13 09:40:01 +02:00
parent 3b205d36d6
commit 065b3572e6
12 changed files with 140 additions and 43 deletions

View File

@ -59,7 +59,7 @@ class ConvexHull(GeoAlgorithm):
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"))
@ -71,22 +71,23 @@ class ConvexHull(GeoAlgorithm):
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,

View File

@ -268,8 +268,6 @@ class Sextante:
return
else:
i = 0
settrace()
for param in alg.parameters:
if not param.hidden:
if not param.setValue(args[i]):

View File

@ -409,11 +409,11 @@ class ModelerAlgorithm(GeoAlgorithm):
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)

View File

@ -418,7 +418,7 @@ class ModelerParametersDialog(QtGui.QDialog):
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()
@ -597,6 +597,7 @@ class ModelerParametersDialog(QtGui.QDialog):
params = self.alg.parameters
outputs = self.alg.outputs
for param in params:
if param.hidden:
continue
@ -650,12 +651,16 @@ class ModelerParametersDialog(QtGui.QDialog):
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:
@ -664,16 +669,22 @@ class ModelerParametersDialog(QtGui.QDialog):
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:
@ -684,7 +695,15 @@ class ModelerParametersDialog(QtGui.QDialog):
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

View File

@ -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)
@ -71,7 +72,7 @@ class MultilineTextPanel(QtGui.QWidget):
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))

View File

@ -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

View File

@ -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

View File

@ -39,13 +39,13 @@ class ParameterExtent(Parameter):
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:
@ -60,5 +60,5 @@ class ParameterExtent(Parameter):
def deserialize(self, s):
tokens = s.split("|")
return ParameterExtent(tokens[0], tokens[1], tokens[2])
return ParameterExtent(tokens[1], tokens[2], tokens[3])

View File

@ -35,6 +35,7 @@ class ParameterString(Parameter):
self.default = default
self.value = None
self.multiline = multiline
self.optional = optional
def setValue(self, obj):
if obj is None:

View File

@ -36,6 +36,7 @@ class ParameterTableField(Parameter):
self.parent = parent
self.value = None
self.datatype = datatype
self.optional= optional
def getValueAsCommandLineParameter(self):
return "\"" + str(self.value) + "\""
@ -44,7 +45,9 @@ class ParameterTableField(Parameter):
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

View File

@ -121,6 +121,48 @@ class ModelerAlgorithmTest(unittest.TestCase):
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():

View File

@ -142,7 +142,7 @@ class QgisAlgsTest(unittest.TestCase):
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()