~ubuntu-branches/ubuntu/utopic/qgis/utopic

« back to all changes in this revision

Viewing changes to python/plugins/fTools/tools/doVectorSplit.py

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-04-24 15:12:20 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120424151220-r88g00af5fpn5fc3
Tags: 1.7.4+1.7.5~20120320-1
The "Sometimes they come back" release.

* Branching from Qgis tree and adapting to current Debian Policy and
  standards. The target tree is currently set to release-1.7.
  (closes: #661491, #606304, #615683, #616182, #600308)
* Policy bumped to 3.9.3.
* Moving to debhelper compatibility level 9.
* Source format is now 3.0 with quilt support.
* Merged with 2bf42287 upstream git snapshot.
* Migrated to dh_python2 instead of python-central.
  (closes: #617048)
* Snapshot in qgis.org release-1.7: c936d031
* Added an automagic creation of a lintian override for sqlite embedding.
  This is required for uploading currently.
* Added missing ${misc:Depends} to make lintian happy.
* Copyright notes updated and debian/copyright moved to format 1.0.
* More licenses notices now reported in debian/copyright. Thanks ftpmasters.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
1
2
#-----------------------------------------------------------
2
 
3
 
# Vector Split
4
 
#
5
 
# A QGIS plugin for creating separate output shapefiles
6
 
# based on an attribute from a single input vector layer
7
 
#
 
3
#
 
4
# fTools
 
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
 
8
#
 
9
# A collection of data management and analysis tools for vector data
10
10
#
11
11
#-----------------------------------------------------------
12
 
 
12
#
13
13
# licensed under the terms of GNU GPL 2
14
 
 
14
#
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.
19
 
 
19
#
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.
24
 
 
24
#
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.
28
 
 
28
#
29
29
#---------------------------------------------------------------------
30
30
 
31
31
from PyQt4.QtCore import *
32
32
from PyQt4.QtGui import *
33
33
from qgis.core import *
34
 
#import os, sys, string, math
 
34
import ftools_utils
35
35
from ui_frmVectorSplit import Ui_Dialog
36
36
 
37
37
class Dialog(QDialog, Ui_Dialog):
38
 
        def __init__(self, iface):
39
 
                QDialog.__init__(self)
40
 
                self.iface = iface
41
 
                # Set up the user interface from Designer.
42
 
                self.setupUi(self)
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")
46
 
                # populate layer list
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())
53
 
 
54
 
        def update(self, inputLayer):
55
 
                self.inField.clear()
56
 
                changedLayer = self.getVectorLayerByName(inputLayer)
57
 
                changedField = self.getFieldList(changedLayer)
58
 
                for i in changedField:
59
 
                        self.inField.addItem(unicode(changedField[i].name()))
60
 
 
61
 
        def accept(self):
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")
66
 
                else:
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)
78
 
                        self.outShape.clear()
79
 
                        QMessageBox.information(self, "Vector Split", "Created output shapefiles in folder:\n" + unicode(outPath))
80
 
                        self.progressBar.setValue(0)
81
 
 
82
 
        def outFile(self):
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:
138
 
                        return
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)
144
 
 
145
 
        def split(self, vlayer, outPath, inField, progressBar):
146
 
                provider = vlayer.dataProvider()
147
 
                #unique = []
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)
155
 
                sRs = provider.crs()
156
 
                inFeat = QgsFeature()
157
 
                progressBar.setValue(20)
158
 
                start = 20.00
159
 
                add = 80.00 / len(unique)
160
 
                for i in unique:
161
 
                        check = QFile(baseName + "_" + unicode(i) + ".shp")
162
 
                        if check.exists():
163
 
                                if not QgsVectorFileWriter.deleteShapeFile(baseName + "_" + unicode(i.toString().trimmed()) + ".shp"):
164
 
                                        return
165
 
                        writer = QgsVectorFileWriter(baseName + "_" + unicode(i.toString().trimmed()) + ".shp", self.encoding, fieldList, vlayer.dataProvider().geometryType(), sRs)
166
 
                        provider.rewind()
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)
172
 
                        del writer
173
 
                        start = start + add
174
 
                        progressBar.setValue(start)
175
 
 
176
 
        def getVectorLayerByName(self, myName):
177
 
                mc = self.iface.mapCanvas()
178
 
                nLayers = mc.layerCount()
179
 
                for l in range(nLayers):
180
 
                        layer = mc.layer(l)
181
 
                        if unicode(layer.name()) == unicode(myName):
182
 
                                vlayer = QgsVectorLayer(unicode(layer.source()),  unicode(myName),  unicode(layer.dataProvider().name()))
183
 
                                if vlayer.isValid():
184
 
                                        return vlayer
185
 
 
186
 
        def getFieldList(self, vlayer):
187
 
                fProvider = vlayer.dataProvider()
188
 
                feat = QgsFeature()
189
 
                allAttrs = fProvider.attributeIndexes()
190
 
                # fetch all attributes for each feature
191
 
                fProvider.select(allAttrs)
192
 
                # retrieve all fields
193
 
                myFields = fProvider.fields()
194
 
                return myFields
195
 
 
196
 
        def getUniqueValues(self, provider, index):
197
 
                allAttrs = provider.attributeIndexes()    
198
 
                provider.select(allAttrs)
199
 
                feat = QgsFeature()
200
 
                values = []
201
 
                check = []
202
 
                provider.rewind()
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() )
207
 
                return values
208
 
 
 
38
    def __init__(self, iface):
 
39
        QDialog.__init__(self)
 
40
        self.iface = iface
 
41
 
 
42
        self.setupUi(self)
 
43
        self.setWindowTitle(self.tr("Split vector layer"))
 
44
 
 
45
        QObject.connect(self.toolOut, SIGNAL("clicked()"), self.outFile)
 
46
        QObject.connect(self.inShape, SIGNAL("currentIndexChanged(QString)"), self.update)
 
47
 
 
48
        self.workThread = None
 
49
 
 
50
        self.btnOk = self.buttonBox_2.button( QDialogButtonBox.Ok )
 
51
        self.btnClose = self.buttonBox_2.button( QDialogButtonBox.Close )
 
52
 
 
53
        # populate layer list
 
54
        mapCanvas = self.iface.mapCanvas()
 
55
        layers = ftools_utils.getLayerNames([QGis.Point, QGis.Line, QGis.Polygon])
 
56
        self.inShape.addItems(layers)
 
57
 
 
58
    def update(self, inputLayer):
 
59
        self.inField.clear()
 
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()))
 
64
 
 
65
    def outFile(self):
 
66
        self.outShape.clear()
 
67
        ( self.folderName, self.encoding ) = ftools_utils.dirDialog( self )
 
68
        if self.folderName is None or self.encoding is None:
 
69
            return
 
70
        self.outShape.setText( QString( self.folderName ) )
 
71
 
 
72
    def accept(self):
 
73
        inShape = self.inShape.currentText()
 
74
        outDir = self.outShape.text()
 
75
        if inShape == "":
 
76
            QMessageBox.information(self, self.tr("Vector Split"),
 
77
                                    self.tr("No input shapefile specified"))
 
78
            return
 
79
        elif outDir == "":
 
80
            QMessageBox.information(self, self.tr("Vector Split"),
 
81
                                    self.tr("Please specify output shapefile"))
 
82
            return
 
83
 
 
84
        self.btnOk.setEnabled( False )
 
85
 
 
86
        vLayer = ftools_utils.getVectorLayerByName(unicode(self.inShape.currentText()))
 
87
        self.workThread = SplitThread(vLayer, self.inField.currentText(), self.encoding, outDir)
 
88
 
 
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)
 
93
 
 
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)
 
97
 
 
98
        self.workThread.start()
 
99
 
 
100
    def setProgressRange(self, maximum):
 
101
        self.progressBar.setRange(0, maximum)
 
102
 
 
103
    def valueProcessed(self):
 
104
        self.progressBar.setValue(self.progressBar.value() + 1)
 
105
 
 
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)
 
112
 
 
113
    def stopProcessing(self):
 
114
        if self.workThread != None:
 
115
            self.workThread.stop()
 
116
            self.workThread = None
 
117
 
 
118
    def processInterrupted( self ):
 
119
        self.restoreGui()
 
120
 
 
121
    def processFinished(self, errors):
 
122
        self.stopProcessing()
 
123
        outPath = self.outShape.text()
 
124
        self.restoreGui()
 
125
 
 
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 )
 
129
 
 
130
        QMessageBox.information(self, self.tr("Vector Split"),
 
131
                                self.tr("Created output shapefiles in folder:\n%1").arg(outPath))
 
132
 
 
133
class SplitThread(QThread):
 
134
    def __init__(self, layer, splitField, encoding, outDir):
 
135
        QThread.__init__(self, QThread.currentThread())
 
136
        self.layer = layer
 
137
        self.field = splitField
 
138
        self.encoding = encoding
 
139
        self.outDir = outDir
 
140
 
 
141
        self.mutex = QMutex()
 
142
        self.stopMe = 0
 
143
 
 
144
        self.errors = QStringList()
 
145
 
 
146
    def run(self):
 
147
        self.mutex.lock()
 
148
        self.stopMe = 0
 
149
        self.mutex.unlock()
 
150
 
 
151
        interrupted = False
 
152
 
 
153
        outPath = QString(self.outDir)
 
154
 
 
155
        if outPath.contains("\\"):
 
156
            outPath.replace("\\", "/")
 
157
 
 
158
        if not outPath.endsWith("/"):
 
159
            outPath = outPath + "/"
 
160
 
 
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)
 
168
        sRs = provider.crs()
 
169
        geom = self.layer.wkbType()
 
170
        inFeat = QgsFeature()
 
171
 
 
172
        self.emit(SIGNAL("rangeCalculated(PyQt_PyObject)"), len(unique))
 
173
 
 
174
        for i in unique:
 
175
            check = QFile(baseName + "_" + unicode(i.toString().trimmed()) + ".shp")
 
176
            fName = check.fileName()
 
177
            if check.exists():
 
178
                if not QgsVectorFileWriter.deleteShapeFile(fName):
 
179
                    self.errors.append( fName )
 
180
                    continue
 
181
 
 
182
            writer = QgsVectorFileWriter(fName, self.encoding, fieldList, geom, sRs)
 
183
            provider.rewind()
 
184
            while provider.nextFeature(inFeat):
 
185
                atMap = inFeat.attributeMap()
 
186
                if atMap[index] == i:
 
187
                    writer.addFeature(inFeat)
 
188
            del writer
 
189
 
 
190
            self.emit(SIGNAL("valueProcessed()"))
 
191
 
 
192
            self.mutex.lock()
 
193
            s = self.stopMe
 
194
            self.mutex.unlock()
 
195
            if s == 1:
 
196
                interrupted = True
 
197
                break
 
198
 
 
199
        if not interrupted:
 
200
            self.emit(SIGNAL("processFinished( PyQt_PyObject )"), self.errors)
 
201
        else:
 
202
            self.emit(SIGNAL("processInterrupted()"))
 
203
 
 
204
    def stop(self):
 
205
        self.mutex.lock()
 
206
        self.stopMe = 1
 
207
        self.mutex.unlock()
 
208
 
 
209
        QThread.wait(self)