|
25 | 25 |
|
26 | 26 | __revision__ = '$Format:%H$'
|
27 | 27 |
|
| 28 | + |
| 29 | +from PyQt4.QtCore import QVariant |
| 30 | +from qgis.core import QgsFields, QgsVectorLayer |
| 31 | + |
28 | 32 | from processing.core.GeoAlgorithm import GeoAlgorithm
|
29 | 33 | from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
30 |
| -from processing.core.parameters import ParameterVector |
| 34 | +from processing.core.parameters import ParameterMultipleInput |
31 | 35 | from processing.core.outputs import OutputVector
|
32 | 36 |
|
33 | 37 | from processing.tools import dataobjects, vector
|
34 | 38 |
|
35 | 39 |
|
36 | 40 | class Merge(GeoAlgorithm):
|
37 |
| - LAYER1 = 'LAYER1' |
38 |
| - LAYER2 = 'LAYER2' |
| 41 | + LAYERS = 'LAYERS' |
39 | 42 | OUTPUT = 'OUTPUT'
|
40 | 43 |
|
41 | 44 | def defineCharacteristics(self):
|
42 | 45 | self.name, self.i18n_name = self.trAlgorithm('Merge vector layers')
|
43 | 46 | self.group, self.i18n_group = self.trAlgorithm('Vector general tools')
|
44 | 47 |
|
45 |
| - self.addParameter(ParameterVector(self.LAYER1, |
46 |
| - self.tr('Input layer 1'), [ParameterVector.VECTOR_TYPE_ANY])) |
47 |
| - self.addParameter(ParameterVector(self.LAYER2, |
48 |
| - self.tr('Input layer 2'), [ParameterVector.VECTOR_TYPE_ANY])) |
| 48 | + self.addParameter(ParameterMultipleInput(self.LAYERS, |
| 49 | + self.tr('Layers to merge'), datatype=ParameterMultipleInput.TYPE_VECTOR_ANY)) |
49 | 50 |
|
50 | 51 | self.addOutput(OutputVector(self.OUTPUT, self.tr('Merged')))
|
51 | 52 |
|
52 | 53 | def processAlgorithm(self, progress):
|
53 |
| - layer1 = dataobjects.getObjectFromUri( |
54 |
| - self.getParameterValue(self.LAYER1)) |
55 |
| - layer2 = dataobjects.getObjectFromUri( |
56 |
| - self.getParameterValue(self.LAYER2)) |
57 |
| - |
58 |
| - if layer1.wkbType() != layer2.wkbType(): |
59 |
| - raise GeoAlgorithmExecutionException( |
60 |
| - self.tr('Merged layers must have be same type of geometry')) |
61 |
| - |
62 |
| - count = 0 |
63 |
| - fields = [] |
64 |
| - layers = [layer1, layer2] |
65 |
| - for layer in layers: |
66 |
| - count += layer.featureCount() |
| 54 | + inLayers = self.getParameterValue(self.LAYERS) |
| 55 | + paths = inLayers.split(';') |
| 56 | + |
| 57 | + layers = [] |
| 58 | + fields = QgsFields() |
| 59 | + totalFeatureCount = 0 |
| 60 | + for x in xrange(0, len(paths)): |
| 61 | + layer = QgsVectorLayer(paths[x], unicode(x), 'ogr') |
67 | 62 |
|
68 |
| - for sfield in layer.pendingFields(): |
| 63 | + if (len(layers) > 0): |
| 64 | + if (layer.dataProvider().geometryType() != layers[0].dataProvider().geometryType()): |
| 65 | + raise GeoAlgorithmExecutionException( |
| 66 | + self.tr('All layers must have same geometry type!')) |
| 67 | + |
| 68 | + layers.append(layer) |
| 69 | + totalFeatureCount += layer.featureCount() |
| 70 | + |
| 71 | + for sindex, sfield in enumerate(layer.dataProvider().fields()): |
69 | 72 | found = None
|
70 | 73 | for dfield in fields:
|
71 |
| - if dfield.name() == sfield.name() and \ |
72 |
| - dfield.type() == sfield.type(): |
| 74 | + if (dfield.name().upper() == sfield.name().upper()): |
73 | 75 | found = dfield
|
74 |
| - break |
| 76 | + if (dfield.type() != sfield.type()): |
| 77 | + raise GeoAlgorithmExecutionException( |
| 78 | + self.tr('{} field in layer {} has different ' |
| 79 | + 'data type than in other layers.')) |
75 | 80 |
|
76 | 81 | if not found:
|
77 | 82 | fields.append(sfield)
|
78 | 83 |
|
| 84 | + total = 100.0 / float(totalFeatureCount) |
79 | 85 | writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
|
80 |
| - fields, layer1.wkbType(), layer1.crs()) |
| 86 | + fields.toList(), layers[0].dataProvider().geometryType(), |
| 87 | + layers[0].crs()) |
81 | 88 |
|
82 |
| - total = 100.0 / float(count) |
83 |
| - count = 0 |
| 89 | + featureCount = 0 |
84 | 90 | for layer in layers:
|
85 |
| - idx = {} |
86 |
| - for dfield in fields: |
87 |
| - i = 0 |
88 |
| - for sfield in layer.pendingFields(): |
89 |
| - if sfield.name() == dfield.name() and \ |
90 |
| - sfield.type() == dfield.type(): |
91 |
| - idx[dfield] = i |
92 |
| - break |
93 |
| - i += 1 |
94 |
| - |
95 |
| - features = vector.features(layer) |
96 |
| - for f in features: |
97 |
| - sAttributes = f.attributes() |
98 |
| - dAttributes = [] |
99 |
| - for dfield in fields: |
100 |
| - if dfield in idx: |
101 |
| - dAttributes.append(sAttributes[idx[dfield]]) |
| 91 | + for feature in layer.dataProvider().getFeatures(): |
| 92 | + sattributes = feature.attributes() |
| 93 | + dattributes = [] |
| 94 | + for dindex, dfield in enumerate(fields): |
| 95 | + if (dfield.type() == QVariant.Int): |
| 96 | + dattribute = 0 |
| 97 | + elif (dfield.type() == QVariant.Double): |
| 98 | + dattribute = 0.0 |
102 | 99 | else:
|
103 |
| - dAttributes.append(dfield.type()) |
104 |
| - f.setAttributes(dAttributes) |
105 |
| - writer.addFeature(f) |
106 |
| - |
107 |
| - count += 1 |
108 |
| - progress.setPercentage(int(count * total)) |
| 100 | + dattribute = '' |
| 101 | + |
| 102 | + for sindex, sfield in enumerate(layer.dataProvider().fields()): |
| 103 | + if (sfield.name().upper() == dfield.name().upper()): |
| 104 | + if (sfield.type() != dfield.type()): |
| 105 | + raise GeoAlgorithmExecutionException( |
| 106 | + self.tr('Attribute type mismatch')) |
| 107 | + dattribute = sattributes[sindex] |
| 108 | + break |
| 109 | + |
| 110 | + dattributes.append(dattribute) |
| 111 | + |
| 112 | + feature.setAttributes(dattributes) |
| 113 | + writer.addFeature(feature) |
| 114 | + featureCount += 1 |
| 115 | + progress.setPercentage(int(featureCount * total)) |
109 | 116 |
|
110 | 117 | del writer
|
0 commit comments