[processing] added multiple option to ParameterTableFIeld

removed ParameterTableMultipleField and did some cleanup
This commit is contained in:
volaya 2016-09-09 10:48:51 +02:00
parent bc06600871
commit fe5d0166cc
10 changed files with 123 additions and 294 deletions

View File

@ -36,7 +36,7 @@ from processing.tools import dataobjects, vector
class DeleteColumn(GeoAlgorithm):
INPUT = 'INPUT'
COLUMN = 'COLUMN'
COLUMNS = 'COLUMN'
OUTPUT = 'OUTPUT'
def defineCharacteristics(self):
@ -45,17 +45,20 @@ class DeleteColumn(GeoAlgorithm):
self.addParameter(ParameterVector(self.INPUT,
self.tr('Input layer')))
self.addParameter(ParameterTableField(self.COLUMN,
self.tr('Field to delete'), self.INPUT))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Deleted column')))
self.addParameter(ParameterTableField(self.COLUMNS,
self.tr('Fields to delete'), self.INPUT, multiple=True))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Output layer')))
def processAlgorithm(self, progress):
layer = dataobjects.getObjectFromUri(
self.getParameterValue(self.INPUT))
idx = layer.fields().lookupField(self.getParameterValue(self.COLUMN))
layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
toDelete = self.getParameterValue(self.COLUMNS)
fields = layer.fields()
fields.remove(idx)
idxs = []
for f in toDelete:
idx = layer.fieldNameIndex()
fields.remove(idx)
idxs.append[idx]
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
layer.wkbType(), layer.crs())
@ -67,7 +70,8 @@ class DeleteColumn(GeoAlgorithm):
for current, f in enumerate(features):
feat.setGeometry(f.geometry())
attributes = f.attributes()
del attributes[idx]
for idx in idxs:
del attributes[idx]
feat.setAttributes(attributes)
writer.addFeature(feat)

View File

@ -37,7 +37,7 @@ from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterBoolean
from processing.core.parameters import ParameterTableMultipleField
from processing.core.parameters import ParameterTableField
from processing.core.outputs import OutputVector
from processing.tools import vector, dataobjects
@ -62,8 +62,8 @@ class Dissolve(GeoAlgorithm):
[dataobjects.TYPE_VECTOR_POLYGON, dataobjects.TYPE_VECTOR_LINE]))
self.addParameter(ParameterBoolean(Dissolve.DISSOLVE_ALL,
self.tr('Dissolve all (do not use fields)'), True))
self.addParameter(ParameterTableMultipleField(Dissolve.FIELD,
self.tr('Unique ID fields'), Dissolve.INPUT, optional=True))
self.addParameter(ParameterTableField(Dissolve.FIELD,
self.tr('Unique ID fields'), Dissolve.INPUT, optional=True, multiple=True))
self.addOutput(OutputVector(Dissolve.OUTPUT, self.tr('Dissolved')))
def processAlgorithm(self, progress):

View File

@ -46,7 +46,6 @@ from processing.core.parameters import ParameterNumber
from processing.core.parameters import ParameterBoolean
from processing.core.parameters import ParameterSelection
from processing.core.parameters import ParameterTableField
from processing.core.parameters import ParameterTableMultipleField
from processing.core.parameters import ParameterExtent
from processing.core.parameters import ParameterCrs
from processing.core.parameters import ParameterFile
@ -328,8 +327,7 @@ class RAlgorithm(GeoAlgorithm):
commands.append(param.name + '= NULL')
else:
commands.append(param.name + ' = "' + param.value + '"')
elif isinstance(param, (ParameterTableField, ParameterTableMultipleField, ParameterString,
ParameterFile)):
elif isinstance(param, (ParameterTableField, ParameterString, ParameterFile)):
if param.value is None:
commands.append(param.name + '= NULL')
else:

View File

@ -106,10 +106,8 @@ class Parameter:
take as input.
"""
default_metadata = {
'widget_wrapper': 'processing.gui.wrappers.BasicWidgetWrapper'
}
default_metadata = {}
def __init__(self, name='', description='', default=None, optional=False,
metadata={}):
self.name = name
@ -809,8 +807,7 @@ class ParameterNumber(Parameter):
if isinstance(n, basestring):
try:
v = self._evaluate(n)
float(v)
self.value = n
self.value = float(v)
return True
except:
return False
@ -846,8 +843,8 @@ class ParameterNumber(Parameter):
default = definition.strip()[len('number') + 1:] or None
return ParameterNumber(name, descName, default=default, optional=isOptional)
def _evaluate(self, v):
exp = QgsExpression(v)
def _evaluate(self):
exp = QgsExpression(self.value)
if exp.hasParserError():
raise ValueError(self.tr("Error in parameter expression: ") + exp.parserErrorString())
result = exp.evaluate(_expressionContext())
@ -856,8 +853,7 @@ class ParameterNumber(Parameter):
return result
def evaluate(self, alg):
if isinstance(self.value, basestring):
self.value = self._evaluate(self.value)
self.value = self._evaluate(self.value)
def expressionContext(self):
return _expressionContext()
@ -866,17 +862,12 @@ class ParameterNumber(Parameter):
if self.value is None:
return str(None)
if isinstance(self.value, basestring):
return '"%s"' % self.value
return '"%s"' + self.value
return str(self.value)
class ParameterRange(Parameter):
default_metadata = {
'widget_wrapper': 'processing.gui.wrappers.BasicWidgetWrapper'
}
def __init__(self, name='', description='', default=None, optional=False):
Parameter.__init__(self, name, description, default, optional)
@ -1226,24 +1217,28 @@ class ParameterTableField(Parameter):
DATA_TYPE_ANY = -1
def __init__(self, name='', description='', parent=None, datatype=-1,
optional=False):
optional=False, multiple = False):
Parameter.__init__(self, name, description, None, optional)
self.parent = parent
self.multiple = True
self.datatype = int(datatype)
def getValueAsCommandLineParameter(self):
return '"' + str(self.value) + '"' if self.value is not None else str(None)
def setValue(self, value):
if value is None:
if not bool(value):
if not self.optional:
return False
self.value = None
return True
elif len(value) == 0 and not self.optional:
return False
self.value = str(value)
if isinstance(value, list):
if not self.multiple and len(value) > 1:
return False
self.value = ";".join(value)
return True
else:
self.value = str(value)
return True
def __str__(self):
@ -1284,97 +1279,12 @@ class ParameterTableField(Parameter):
return ParameterTableField(name, descName, parent, datatype, isOptional)
class ParameterTableMultipleField(Parameter):
"""A parameter representing several table fields.
Its value is a string with items separated by semicolons, each of
which represents the name of each field.
In a script you can use it with
##Fields=[optional] multiple field [number|string] Parentinput
In the batch runner simply use a string with items separated by
semicolons, each of which represents the name of each field.
see algs.qgis.DeleteColumn.py for an usage example
"""
DATA_TYPE_NUMBER = 0
DATA_TYPE_STRING = 1
DATA_TYPE_ANY = -1
def __init__(self, name='', description='', parent=None, datatype=-1,
optional=False):
Parameter.__init__(self, name, description, None, optional)
self.parent = parent
self.datatype = int(datatype)
def getValueAsCommandLineParameter(self):
return '"' + str(self.value) + '"' if self.value is not None else str(None)
def setValue(self, obj):
if obj is None:
if self.optional:
self.value = None
return True
return False
if isinstance(obj, list):
if len(obj) == 0:
if self.optional:
self.value = None
return True
return False
self.value = ";".join(obj)
return True
else:
self.value = str(obj)
return True
def __str__(self):
return self.name + ' <' + self.__module__.split('.')[-1] + ' from ' \
+ self.parent + '>'
def dataType(self):
if self.datatype == self.DATA_TYPE_NUMBER:
return 'numeric'
elif self.datatype == self.DATA_TYPE_STRING:
return 'string'
else:
return 'any'
def getAsScriptCode(self):
param_type = ''
if self.optional:
param_type += 'optional '
param_type += 'multiple field '
return '##' + self.name + '=' + param_type + self.parent
@classmethod
def fromScriptCode(self, line):
isOptional, name, definition = _splitParameterOptions(line)
if definition.lower().strip().startswith('multiple field'):
descName = _createDescriptiveName(name)
if definition.lower().strip().startswith('multiple field number'):
field = definition.strip()[len('multiple field number') + 1:]
datatype = ParameterTableMultipleField.DATA_TYPE_NUMBER
elif definition.lower().strip().startswith('multiple field string'):
field = definition.strip()[len('multiple field string') + 1:]
datatype = ParameterTableMultipleField.DATA_TYPE_STRING
else:
field = definition.strip()[len('multiple field') + 1:]
datatype = ParameterTableMultipleField.DATA_TYPE_ANY
return ParameterTableMultipleField(name, descName, field, datatype, isOptional)
class ParameterVector(ParameterDataObject):
default_metadata = {
'widget_wrapper': 'processing.gui.wrappers.VectorWidgetWrapper'
}
def __init__(self, name='', description='', datatype=[-1],
optional=False):
ParameterDataObject.__init__(self, name, description, None, optional)
@ -1468,10 +1378,6 @@ class ParameterVector(ParameterDataObject):
class ParameterGeometryPredicate(Parameter):
default_metadata = {
'widget_wrapper': 'processing.gui.wrappers.BasicWidgetWrapper'
}
predicates = ('intersects',
'contains',
'disjoint',

View File

@ -50,7 +50,6 @@ from processing.core.parameters import ParameterSelection
from processing.core.parameters import ParameterFixedTable
from processing.core.parameters import ParameterRange
from processing.core.parameters import ParameterTableField
from processing.core.parameters import ParameterTableMultipleField
from processing.core.parameters import ParameterMultipleInput
from processing.core.parameters import ParameterString
from processing.core.parameters import ParameterNumber

View File

@ -42,27 +42,7 @@ from qgis.PyQt.QtWidgets import (QWidget, QLayout, QVBoxLayout, QHBoxLayout, QTo
from qgis.PyQt.QtGui import QIcon
from processing.gui.OutputSelectionPanel import OutputSelectionPanel
from processing.gui.PointSelectionPanel import PointSelectionPanel
from processing.gui.GeometryPredicateSelectionPanel import \
GeometryPredicateSelectionPanel
from processing.gui.ListMultiselectWidget import ListMultiSelectWidget
from processing.core.parameters import ParameterRaster
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterTable
from processing.core.parameters import ParameterTableField
from processing.core.parameters import ParameterTableMultipleField
from processing.core.parameters import ParameterSelection
from processing.core.parameters import ParameterFixedTable
from processing.core.parameters import ParameterRange
from processing.core.parameters import ParameterMultipleInput
from processing.core.parameters import ParameterNumber
from processing.core.parameters import ParameterExtent
from processing.core.parameters import ParameterFile
from processing.core.parameters import ParameterCrs
from processing.core.parameters import ParameterString
from processing.core.parameters import ParameterPoint
from processing.core.parameters import ParameterGeometryPredicate
from processing.core.parameters import ParameterVector, ParameterExtent, ParameterPoint
from processing.core.outputs import OutputRaster
from processing.core.outputs import OutputTable
from processing.core.outputs import OutputVector

View File

@ -17,7 +17,6 @@
* *
***************************************************************************
"""
from gui.GeometryPredicateSelectionPanel import GeometryPredicateSelectionPanel
__author__ = 'Arnaud Morvan'
__date__ = 'May 2016'
@ -52,6 +51,7 @@ from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel
from processing.gui.FixedTablePanel import FixedTablePanel
from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel
from processing.gui.StringInputPanel import StringInputPanel
from processing.gui.GeometryPredicateSelectionPanel import GeometryPredicateSelectionPanel
DIALOG_STANDARD = 'standard'
@ -440,7 +440,7 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
options = dataobjects.getVectorLayers(sorting=False)
else:
options = dataobjects.getVectorLayers([self.param.datatype], sorting=False)
return self.param.setValue([options[i] for i in self.widget.selectedoptions])
return [options[i] for i in self.widget.selectedoptions]
elif self.dialogType == DIALOG_BATCH:
return self.widget.getText()
else:
@ -734,32 +734,42 @@ class TableFieldWidgetWrapper(WidgetWrapper):
NOT_SET = '[Not set]'
def createWidget(self):
if self.dialogType == DIALOG_STANDARD:
widget = QComboBox()
return widget
elif self.dialogType == DIALOG_BATCH:
item = QLineEdit()
if self.param.default is not None:
item.setText(self.param.default)
else:
widget = QComboBox()
widget.setEditable(True)
fields = self.dialog.getAvailableValuesOfType(ParameterTableField, None)
if self.param.optional:
widget.addItem(self.NOT_SET, None)
for f in fields:
widget.addItem(self.dialog.resolveValueDescription(f), f)
return widget
if self.param.multiple:
if self.dialogType == DIALOG_STANDARD:
return MultipleInputPanel(options=[])
else:
return QLineEdit()
else:
if self.dialogType == DIALOG_STANDARD:
widget = QComboBox()
return widget
elif self.dialogType == DIALOG_BATCH:
item = QLineEdit()
if self.param.default is not None:
item.setText(self.param.default)
else:
widget = QComboBox()
widget.setEditable(True)
fields = self.dialog.getAvailableValuesOfType(ParameterTableField, None)
if self.param.optional:
widget.addItem(self.NOT_SET, None)
for f in fields:
widget.addItem(self.dialog.resolveValueDescription(f), f)
return widget
def postInitialize(self, wrappers):
for wrapper in wrappers:
if wrapper.param.name == self.param.parent:
layer = wrapper.widget.itemData(wrapper.widget.currentIndex())
if layer is not None:
self.widget.clear()
if self.param.optional:
self.widget.addItem(self.tr(self.NOT_SET))
self.widget.addItems(self.getFields(layer, wrapper.param.datatype))
fields = self.getFields(layer, wrapper.param.datatype)
if self.param.multiple:
self.widget.updateForOptions(fields)
else:
self.widget.clear()
if self.param.optional:
self.widget.addItem(self.tr(self.NOT_SET))
self.widget.addItems(fields)
break
def getFields(self, layer, datatype):
@ -777,33 +787,59 @@ class TableFieldWidgetWrapper(WidgetWrapper):
return sorted(list(fieldNames), cmp=locale.strcoll)
def setValue(self, value):
if self.dialogType == DIALOG_STANDARD:
pass # TODO
elif self.dialogType == DIALOG_BATCH:
return self.widget.setText(value)
else:
self.setComboValue(value)
if self.param.multiple:
if self.dialogType == DIALOG_STANDARD:
options = self.widget.options
selected = []
for i, opt in enumerate(options):
if opt in value:
selected.append(i)
self.widget.setSelectedItems(selected)
else:
self.widget.setText(value)
else:
if self.dialogType == DIALOG_STANDARD:
pass # TODO
elif self.dialogType == DIALOG_BATCH:
return self.widget.setText(value)
else:
self.setComboValue(value)
def value(self):
if self.dialogType == DIALOG_STANDARD:
if self.param.optional and self.widget.currentIndex() == 0:
return None
return self.widget.currentText()
elif self.dialogType == DIALOG_BATCH:
return self.widget.text()
else:
return self.comboValue()
if self.param.multiple:
if self.dialogType == DIALOG_STANDARD:
return [self.widget.options[i] for i in self.widget.selectedoptions]
elif self.dialogType == DIALOG_BATCH:
return self.widget.text()
else:
text = self.widget.text()
if not bool(text) and not self.param.optional:
raise InvalidParameterValue()
return text
else:
if self.dialogType == DIALOG_STANDARD:
if self.param.optional and self.widget.currentIndex() == 0:
return None
return self.widget.currentText()
elif self.dialogType == DIALOG_BATCH:
return self.widget.text()
else:
return self.comboValue()
def anotherParameterWidgetHasChanged(self,wrapper):
if wrapper.param.name == self.param.parent:
layer = wrapper.value()
if layer is not None:
self.widget.clear()
if self.param.optional:
self.widget.addItem(self.tr(self.NOT_SET))
self.widget.addItems(self.getFields(layer, wrapper.param.datatype))
fields = self.getFields(layer, wrapper.param.datatype)
if self.param.multiple:
self.widget.updateForOptions(fields)
else:
self.widget.clear()
if self.param.optional:
self.widget.addItem(self.tr(self.NOT_SET))
self.widget.addItems(fields)
def GeometryPredicateWidgetWrapper(WidgetWrapper):

View File

@ -51,8 +51,7 @@ from processing.core.parameters import (Parameter,
ParameterExtent,
ParameterFile,
ParameterPoint,
ParameterCrs,
ParameterTableMultipleField)
ParameterCrs)
from processing.gui.CrsSelectionPanel import CrsSelectionPanel
@ -65,7 +64,6 @@ class ModelerParameterDefinitionDialog(QDialog):
PARAMETER_STRING = 'String'
PARAMETER_BOOLEAN = 'Boolean'
PARAMETER_TABLE_FIELD = 'Table field'
PARAMETER_TABLE_MULTIPLE_FIELD = 'Table multiple field'
PARAMETER_EXTENT = 'Extent'
PARAMETER_FILE = 'File'
PARAMETER_POINT = 'Point'
@ -84,7 +82,6 @@ class ModelerParameterDefinitionDialog(QDialog):
PARAMETER_STRING,
PARAMETER_TABLE,
PARAMETER_TABLE_FIELD,
PARAMETER_TABLE_MULTIPLE_FIELD,
PARAMETER_VECTOR,
PARAMETER_POINT,
PARAMETER_CRS,
@ -132,7 +129,7 @@ class ModelerParameterDefinitionDialog(QDialog):
self.nameTextBox.setText(self.param.description)
if self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN or \
isinstance(self.param, ParameterBoolean):
isinstance(self.param, ParameterBoolean):
self.state = QCheckBox()
self.state.setText(self.tr('Checked'))
self.state.setChecked(False)
@ -140,11 +137,8 @@ class ModelerParameterDefinitionDialog(QDialog):
self.state.setChecked(True if self.param.value else False)
self.horizontalLayoutParent.addWidget(self.state)
self.verticalLayout.addLayout(self.horizontalLayoutParent)
elif self.paramType in (
ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD,
ModelerParameterDefinitionDialog.PARAMETER_TABLE_MULTIPLE_FIELD)\
or isinstance(self.param, (ParameterTableField,
ParameterTableMultipleField)):
elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or \
isinstance(self.param, ParameterTableField):
self.horizontalLayoutParent.addWidget(QLabel(self.tr('Parent layer')))
self.parentCombo = QComboBox()
idx = 0
@ -300,27 +294,15 @@ class ModelerParameterDefinitionDialog(QDialog):
or isinstance(self.param, ParameterBoolean):
self.param = ParameterBoolean(name, description,
self.state.isChecked())
elif self.paramType in (
ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD,
ModelerParameterDefinitionDialog.PARAMETER_TABLE_MULTIPLE_FIELD)\
or isinstance(self.param, (ParameterTableField,
ParameterTableMultipleField)):
elif self.paramType in ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD \
or isinstance(self.param, ParameterTableField):
if self.parentCombo.currentIndex() < 0:
QMessageBox.warning(self, self.tr('Unable to define parameter'),
self.tr('Wrong or missing parameter values'))
return
parent = self.parentCombo.itemData(self.parentCombo.currentIndex())
datatype = self.datatypeCombo.itemData(
self.datatypeCombo.currentIndex())
if (self.paramType ==
ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or
isinstance(self.param, ParameterTableField)):
self.param = ParameterTableField(
name, description, parent, datatype)
else:
self.param = ParameterTableMultipleField(
name, description, parent, datatype)
datatype = self.datatypeCombo.itemData(self.datatypeCombo.currentIndex())
self.param = ParameterTableField(name, description, parent, datatype)
elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_RASTER or \
isinstance(self.param, ParameterRaster):
self.param = ParameterRaster(

View File

@ -42,24 +42,6 @@ from qgis.gui import QgsMessageBar
from processing.gui.wrappers import InvalidParameterValue
from processing.gui.MultipleInputPanel import MultipleInputPanel
from processing.gui.GeometryPredicateSelectionPanel import \
GeometryPredicateSelectionPanel
from processing.core.parameters import (ParameterExtent,
ParameterRaster,
ParameterVector,
ParameterTable,
ParameterFixedTable,
ParameterMultipleInput,
ParameterSelection,
ParameterRange,
ParameterNumber,
ParameterString,
ParameterCrs,
ParameterTableField,
ParameterTableMultipleField,
ParameterFile,
ParameterPoint,
ParameterGeometryPredicate)
from processing.core.outputs import (OutputRaster,
OutputVector,
OutputTable,
@ -75,8 +57,7 @@ from processing.modeler.ModelerAlgorithm import (ValueFromInput,
ValueFromOutput,
Algorithm,
ModelerOutput)
from processing.modeler.MultilineTextPanel import MultilineTextPanel
from processing.tools import dataobjects
from qgis.core import QgsApplication
from qgis.PyQt.QtGui import QToolButton, QMenu, QAction

View File

@ -39,8 +39,7 @@ from processing.core.parameters import (Parameter,
ParameterPoint,
ParameterString,
ParameterVector,
ParameterTableField,
ParameterTableMultipleField)
ParameterTableField)
from processing.tools import dataobjects
from processing.tests.TestData import points2
@ -435,61 +434,5 @@ class ParameterTableFieldTest(unittest.TestCase):
'myName', 'myDesc', parent_name, optional=True)
class ParameterTableMultipleFieldTest(unittest.TestCase):
def setUp(self):
self.parent_name = 'test_parent_layer'
test_data = points2()
test_layer = QgsVectorLayer(test_data, self.parent_name, 'ogr')
self.parent = ParameterVector(self.parent_name,
self.parent_name)
self.parent.setValue(test_layer)
def testGetAsScriptCode(self):
parameter = ParameterTableMultipleField(
'myName', 'myDesc', self.parent_name, optional=False)
self.assertEqual(
parameter.getAsScriptCode(),
'##myName=multiple field test_parent_layer')
# test optional
parameter.optional = True
self.assertEqual(
parameter.getAsScriptCode(),
'##myName=optional multiple field test_parent_layer')
def testOptional(self):
parameter = ParameterTableMultipleField(
'myName', 'myDesc', self.parent_name, optional=True)
parameter.setValue(['my', 'super', 'widget', '77'])
self.assertEqual(parameter.value, 'my;super;widget;77')
parameter.setValue([])
self.assertEqual(parameter.value, None)
parameter.setValue(None)
self.assertEqual(parameter.value, None)
parameter.setValue(['my', 'widget', '77'])
self.assertEqual(parameter.value, 'my;widget;77')
def testSetValue(self):
parameter = ParameterTableMultipleField(
'myName', 'myDesc', self.parent_name, optional=False)
parameter.setValue(['my', 'super', 'widget', '77'])
self.assertEqual(parameter.value, 'my;super;widget;77')
parameter.setValue([])
self.assertEqual(parameter.value, 'my;super;widget;77')
parameter.setValue(None)
self.assertEqual(parameter.value, 'my;super;widget;77')
parameter.setValue(['my', 'widget', '77'])
self.assertEqual(parameter.value, 'my;widget;77')
if __name__ == '__main__':
unittest.main()