[processing] JoinAttributes improvement

- allow join not only with vector attribute table but also with geometryless table
- performance and key comparison improvement
- str to unicode fix
This commit is contained in:
Minoru Akagi 2014-07-05 13:37:37 +09:00
parent 51408e1608
commit 361202e9fc
2 changed files with 20 additions and 16 deletions

View File

@ -30,6 +30,7 @@ from PyQt4.QtGui import *
from qgis.core import * from qgis.core import *
from processing.core.GeoAlgorithm import GeoAlgorithm from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.parameters.ParameterVector import ParameterVector from processing.parameters.ParameterVector import ParameterVector
from processing.parameters.ParameterTable import ParameterTable
from processing.parameters.ParameterTableField import ParameterTableField from processing.parameters.ParameterTableField import ParameterTableField
from processing.outputs.OutputVector import OutputVector from processing.outputs.OutputVector import OutputVector
from processing.tools import dataobjects, vector from processing.tools import dataobjects, vector
@ -48,8 +49,8 @@ class JoinAttributes(GeoAlgorithm):
self.group = 'Vector general tools' self.group = 'Vector general tools'
self.addParameter(ParameterVector(self.INPUT_LAYER, 'Input layer', self.addParameter(ParameterVector(self.INPUT_LAYER, 'Input layer',
[ParameterVector.VECTOR_TYPE_ANY], False)) [ParameterVector.VECTOR_TYPE_ANY], False))
self.addParameter(ParameterVector(self.INPUT_LAYER_2, 'Input layer 2', self.addParameter(ParameterTable(self.INPUT_LAYER_2, 'Input layer 2',
[ParameterVector.VECTOR_TYPE_ANY], False)) False))
self.addParameter(ParameterTableField(self.TABLE_FIELD, 'Table field', self.addParameter(ParameterTableField(self.TABLE_FIELD, 'Table field',
self.INPUT_LAYER)) self.INPUT_LAYER))
self.addParameter(ParameterTableField(self.TABLE_FIELD_2, self.addParameter(ParameterTableField(self.TABLE_FIELD_2,
@ -84,22 +85,25 @@ class JoinAttributes(GeoAlgorithm):
inFeat2 = QgsFeature() inFeat2 = QgsFeature()
outFeat = QgsFeature() outFeat = QgsFeature()
# Cache attributes of Layer 2
cache = {}
features2 = vector.features(layer2)
for inFeat2 in features2:
attrs2 = inFeat2.attributes()
joinValue2 = unicode(attrs2[joinField2Index])
# Put the attributes into the dict if the join key is not contained in the keys of the dict.
# Note: This behavior is same as previous behavior of this function,
# but different from the attribute cache function of QGIS core.
if not joinValue2 in cache:
cache[joinValue2] = attrs2
# Create output vector layer with additional attribute # Create output vector layer with additional attribute
features = vector.features(layer) features = vector.features(layer)
for inFeat in features: for inFeat in features:
inGeom = inFeat.geometry() outFeat.setGeometry(inFeat.geometry())
attrs = inFeat.attributes() attrs = inFeat.attributes()
joinValue1 = attrs[joinField1Index] joinValue1 = unicode(attrs[joinField1Index])
features2 = vector.features(layer2) attrs.extend(cache.get(joinValue1, []))
for inFeat2 in features2:
# Maybe it should cache this entries...
attrs2 = inFeat2.attributes()
joinValue2 = attrs2[joinField2Index]
if joinValue1 == joinValue2:
# Create the new feature
outFeat.setGeometry(inGeom)
attrs.extend(attrs2)
break
outFeat.setAttributes(attrs) outFeat.setAttributes(attrs)
writer.addFeature(outFeat) writer.addFeature(outFeat)
del writer del writer

View File

@ -43,7 +43,7 @@ class ParameterTableField(Parameter):
self.optional = optional self.optional = optional
def getValueAsCommandLineParameter(self): def getValueAsCommandLineParameter(self):
return '"' + str(self.value) + '"' return '"' + unicode(self.value) + '"'
def getAsScriptCode(self): def getAsScriptCode(self):
return '##' + self.name + '=field ' + str(self.parent) return '##' + self.name + '=field ' + str(self.parent)
@ -52,7 +52,7 @@ class ParameterTableField(Parameter):
if value is None: if value is None:
return self.optional return self.optional
elif len(value) > 0: elif len(value) > 0:
self.value = str(value) self.value = unicode(value)
else: else:
return self.optional return self.optional
return True return True