1
# -*- coding: utf-8 -*-
1
2
#-----------------------------------------------------------
5
# A QGIS plugin for creating separate output shapefiles
6
# based on an attribute from a single input vector layer
5
# Copyright (C) 2008-2011 Carson Farmer
8
6
# EMAIL: carson.farmer (at) gmail.com
9
# WEB : www.geog.uvic.ca/spar/carson
7
# WEB : http://www.ftools.ca/fTools.html
9
# A collection of data management and analysis tools for vector data
11
11
#-----------------------------------------------------------
13
13
# licensed under the terms of GNU GPL 2
15
15
# This program is free software; you can redistribute it and/or modify
16
16
# it under the terms of the GNU General Public License as published by
17
17
# the Free Software Foundation; either version 2 of the License, or
18
18
# (at your option) any later version.
20
20
# This program is distributed in the hope that it will be useful,
21
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
23
# GNU General Public License for more details.
25
25
# You should have received a copy of the GNU General Public License along
26
26
# with this program; if not, write to the Free Software Foundation, Inc.,
27
27
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29
29
#---------------------------------------------------------------------
31
31
from PyQt4.QtCore import *
32
32
from PyQt4.QtGui import *
33
33
from qgis.core import *
34
#import os, sys, string, math
35
35
from ui_frmVectorSplit import Ui_Dialog
37
37
class Dialog(QDialog, Ui_Dialog):
38
def __init__(self, iface):
39
QDialog.__init__(self)
41
# Set up the user interface from Designer.
43
QObject.connect(self.toolOut, SIGNAL("clicked()"), self.outFile)
44
QObject.connect(self.inShape, SIGNAL("currentIndexChanged(QString)"), self.update)
45
self.setWindowTitle("Split vector layer")
47
self.progressBar.setValue(0)
48
mapCanvas = self.iface.mapCanvas()
49
for i in range(mapCanvas.layerCount()):
50
layer = mapCanvas.layer(i)
51
if layer.type() == layer.VectorLayer:
52
self.inShape.addItem(layer.name())
54
def update(self, inputLayer):
56
changedLayer = self.getVectorLayerByName(inputLayer)
57
changedField = self.getFieldList(changedLayer)
58
for i in changedField:
59
self.inField.addItem(unicode(changedField[i].name()))
62
if self.inShape.currentText() == "":
63
QMessageBox.information(self, "Vector Split", "No input shapefile specified")
64
elif self.outShape.text() == "":
65
QMessageBox.information(self, "Vector Split", "Please specify output shapefile")
67
inField = self.inField.currentText()
68
inLayer = self.getVectorLayerByName(unicode(self.inShape.currentText()))
69
self.progressBar.setValue(5)
70
outPath = QString(self.folderName)
71
self.progressBar.setValue(10)
72
if outPath.contains("\\"):
73
outPath.replace("\\", "/")
74
self.progressBar.setValue(15)
75
if not outPath.endsWith("/"): outPath = outPath + "/"
76
self.split(inLayer, unicode(outPath), unicode(inField), self.progressBar)
77
self.progressBar.setValue(100)
79
QMessageBox.information(self, "Vector Split", "Created output shapefiles in folder:\n" + unicode(outPath))
80
self.progressBar.setValue(0)
83
fileDialog = QFileDialog()
84
settings = QSettings()
85
dirName = settings.value("/UI/lastShapefileDir").toString()
86
fileDialog.setDirectory(dirName)
87
encodingBox = QComboBox()
88
l = QLabel("Encoding:",fileDialog)
89
fileDialog.layout().addWidget(l)
90
fileDialog.layout().addWidget(encodingBox)
91
encodingBox.addItem("BIG5")
92
encodingBox.addItem("BIG5-HKSCS")
93
encodingBox.addItem("EUCJP")
94
encodingBox.addItem("EUCKR")
95
encodingBox.addItem("GB2312")
96
encodingBox.addItem("GBK")
97
encodingBox.addItem("GB18030")
98
encodingBox.addItem("JIS7")
99
encodingBox.addItem("SHIFT-JIS")
100
encodingBox.addItem("TSCII")
101
encodingBox.addItem("UTF-8")
102
encodingBox.addItem("UTF-16")
103
encodingBox.addItem("KOI8-R")
104
encodingBox.addItem("KOI8-U")
105
encodingBox.addItem("ISO8859-1")
106
encodingBox.addItem("ISO8859-2")
107
encodingBox.addItem("ISO8859-3")
108
encodingBox.addItem("ISO8859-4")
109
encodingBox.addItem("ISO8859-5")
110
encodingBox.addItem("ISO8859-6")
111
encodingBox.addItem("ISO8859-7")
112
encodingBox.addItem("ISO8859-8")
113
encodingBox.addItem("ISO8859-8-I")
114
encodingBox.addItem("ISO8859-9")
115
encodingBox.addItem("ISO8859-10")
116
encodingBox.addItem("ISO8859-13")
117
encodingBox.addItem("ISO8859-14")
118
encodingBox.addItem("ISO8859-15")
119
encodingBox.addItem("IBM 850")
120
encodingBox.addItem("IBM 866")
121
encodingBox.addItem("CP874")
122
encodingBox.addItem("CP1250")
123
encodingBox.addItem("CP1251")
124
encodingBox.addItem("CP1252")
125
encodingBox.addItem("CP1253")
126
encodingBox.addItem("CP1254")
127
encodingBox.addItem("CP1255")
128
encodingBox.addItem("CP1256")
129
encodingBox.addItem("CP1257")
130
encodingBox.addItem("CP1258")
131
encodingBox.addItem("Apple Roman")
132
encodingBox.addItem("TIS-620")
133
encodingBox.setItemText(encodingBox.currentIndex(), QString(QTextCodec.codecForLocale().name()))
134
fileDialog.setAcceptMode(QFileDialog.AcceptSave)
135
fileDialog.setFileMode(QFileDialog.DirectoryOnly)
136
fileDialog.setConfirmOverwrite(False)
137
if not fileDialog.exec_() == 1:
139
folders = fileDialog.selectedFiles()
140
self.folderName = unicode(folders.first())
141
self.encoding = unicode(encodingBox.currentText())
142
self.outShape.clear()
143
self.outShape.insert(self.folderName)
145
def split(self, vlayer, outPath, inField, progressBar):
146
provider = vlayer.dataProvider()
148
index = provider.fieldNameIndex(inField)
149
#provider.uniqueValues(index, unique)
150
unique = self.getUniqueValues(vlayer.dataProvider(), int(index))
151
baseName = outPath + vlayer.name() + "_" + inField + "_"
152
allAttrs = provider.attributeIndexes()
153
provider.select(allAttrs)
154
fieldList = self.getFieldList(vlayer)
156
inFeat = QgsFeature()
157
progressBar.setValue(20)
159
add = 80.00 / len(unique)
161
check = QFile(baseName + "_" + unicode(i) + ".shp")
163
if not QgsVectorFileWriter.deleteShapeFile(baseName + "_" + unicode(i.toString().trimmed()) + ".shp"):
165
writer = QgsVectorFileWriter(baseName + "_" + unicode(i.toString().trimmed()) + ".shp", self.encoding, fieldList, vlayer.dataProvider().geometryType(), sRs)
167
while provider.nextFeature(inFeat):
168
atMap = inFeat.attributeMap()
169
#changed from QVariant(i) to below:
170
if atMap[index] == i:
171
writer.addFeature(inFeat)
174
progressBar.setValue(start)
176
def getVectorLayerByName(self, myName):
177
mc = self.iface.mapCanvas()
178
nLayers = mc.layerCount()
179
for l in range(nLayers):
181
if unicode(layer.name()) == unicode(myName):
182
vlayer = QgsVectorLayer(unicode(layer.source()), unicode(myName), unicode(layer.dataProvider().name()))
186
def getFieldList(self, vlayer):
187
fProvider = vlayer.dataProvider()
189
allAttrs = fProvider.attributeIndexes()
190
# fetch all attributes for each feature
191
fProvider.select(allAttrs)
192
# retrieve all fields
193
myFields = fProvider.fields()
196
def getUniqueValues(self, provider, index):
197
allAttrs = provider.attributeIndexes()
198
provider.select(allAttrs)
203
while provider.nextFeature(feat):
204
if not feat.attributeMap()[index].toString() in check:
205
values.append( feat.attributeMap()[index] )
206
check.append( feat.attributeMap()[index].toString() )
38
def __init__(self, iface):
39
QDialog.__init__(self)
43
self.setWindowTitle(self.tr("Split vector layer"))
45
QObject.connect(self.toolOut, SIGNAL("clicked()"), self.outFile)
46
QObject.connect(self.inShape, SIGNAL("currentIndexChanged(QString)"), self.update)
48
self.workThread = None
50
self.btnOk = self.buttonBox_2.button( QDialogButtonBox.Ok )
51
self.btnClose = self.buttonBox_2.button( QDialogButtonBox.Close )
54
mapCanvas = self.iface.mapCanvas()
55
layers = ftools_utils.getLayerNames([QGis.Point, QGis.Line, QGis.Polygon])
56
self.inShape.addItems(layers)
58
def update(self, inputLayer):
60
changedLayer = ftools_utils.getVectorLayerByName(inputLayer)
61
changedField = ftools_utils.getFieldList(changedLayer)
62
for i in changedField:
63
self.inField.addItem(unicode(changedField[i].name()))
67
( self.folderName, self.encoding ) = ftools_utils.dirDialog( self )
68
if self.folderName is None or self.encoding is None:
70
self.outShape.setText( QString( self.folderName ) )
73
inShape = self.inShape.currentText()
74
outDir = self.outShape.text()
76
QMessageBox.information(self, self.tr("Vector Split"),
77
self.tr("No input shapefile specified"))
80
QMessageBox.information(self, self.tr("Vector Split"),
81
self.tr("Please specify output shapefile"))
84
self.btnOk.setEnabled( False )
86
vLayer = ftools_utils.getVectorLayerByName(unicode(self.inShape.currentText()))
87
self.workThread = SplitThread(vLayer, self.inField.currentText(), self.encoding, outDir)
89
QObject.connect(self.workThread, SIGNAL("rangeCalculated(PyQt_PyObject)"), self.setProgressRange)
90
QObject.connect(self.workThread, SIGNAL("valueProcessed()"), self.valueProcessed)
91
QObject.connect(self.workThread, SIGNAL("processFinished(PyQt_PyObject)"), self.processFinished)
92
QObject.connect(self.workThread, SIGNAL("processInterrupted()"), self.processInterrupted)
94
self.btnClose.setText(self.tr("Cancel"))
95
QObject.disconnect(self.buttonBox_2, SIGNAL("rejected()"), self.reject)
96
QObject.connect(self.btnClose, SIGNAL("clicked()"), self.stopProcessing)
98
self.workThread.start()
100
def setProgressRange(self, maximum):
101
self.progressBar.setRange(0, maximum)
103
def valueProcessed(self):
104
self.progressBar.setValue(self.progressBar.value() + 1)
106
def restoreGui(self):
107
self.progressBar.setValue(0)
108
self.outShape.clear()
109
QObject.connect(self.buttonBox_2, SIGNAL("rejected()"), self.reject)
110
self.btnClose.setText(self.tr("Close"))
111
self.btnOk.setEnabled(True)
113
def stopProcessing(self):
114
if self.workThread != None:
115
self.workThread.stop()
116
self.workThread = None
118
def processInterrupted( self ):
121
def processFinished(self, errors):
122
self.stopProcessing()
123
outPath = self.outShape.text()
126
if not errors.isEmpty():
127
msg = QString( "Processing of the following layers/files ended with error:<br><br>" ).append( errors.join( "<br>" ) )
128
QErrorMessage( self ).showMessage( msg )
130
QMessageBox.information(self, self.tr("Vector Split"),
131
self.tr("Created output shapefiles in folder:\n%1").arg(outPath))
133
class SplitThread(QThread):
134
def __init__(self, layer, splitField, encoding, outDir):
135
QThread.__init__(self, QThread.currentThread())
137
self.field = splitField
138
self.encoding = encoding
141
self.mutex = QMutex()
144
self.errors = QStringList()
153
outPath = QString(self.outDir)
155
if outPath.contains("\\"):
156
outPath.replace("\\", "/")
158
if not outPath.endsWith("/"):
159
outPath = outPath + "/"
161
provider = self.layer.dataProvider()
162
index = provider.fieldNameIndex(self.field)
163
unique = ftools_utils.getUniqueValues(provider, int(index))
164
baseName = unicode( outPath + self.layer.name() + "_" + self.field + "_" )
165
allAttrs = provider.attributeIndexes()
166
provider.select(allAttrs)
167
fieldList = ftools_utils.getFieldList(self.layer)
169
geom = self.layer.wkbType()
170
inFeat = QgsFeature()
172
self.emit(SIGNAL("rangeCalculated(PyQt_PyObject)"), len(unique))
175
check = QFile(baseName + "_" + unicode(i.toString().trimmed()) + ".shp")
176
fName = check.fileName()
178
if not QgsVectorFileWriter.deleteShapeFile(fName):
179
self.errors.append( fName )
182
writer = QgsVectorFileWriter(fName, self.encoding, fieldList, geom, sRs)
184
while provider.nextFeature(inFeat):
185
atMap = inFeat.attributeMap()
186
if atMap[index] == i:
187
writer.addFeature(inFeat)
190
self.emit(SIGNAL("valueProcessed()"))
200
self.emit(SIGNAL("processFinished( PyQt_PyObject )"), self.errors)
202
self.emit(SIGNAL("processInterrupted()"))