3131from PyQt4 .QtCore import *
3232from PyQt4 .QtGui import *
3333from qgis .core import *
34- #import os, sys, string, math
3534import ftools_utils
3635from ui_frmVectorSplit import Ui_Dialog
3736
3837class Dialog (QDialog , Ui_Dialog ):
3938 def __init__ (self , iface ):
4039 QDialog .__init__ (self )
4140 self .iface = iface
42- # Set up the user interface from Designer.
41+
4342 self .setupUi (self )
43+ self .setWindowTitle (self .tr ("Split vector layer" ))
44+
4445 QObject .connect (self .toolOut , SIGNAL ("clicked()" ), self .outFile )
4546 QObject .connect (self .inShape , SIGNAL ("currentIndexChanged(QString)" ), self .update )
46- self .setWindowTitle (self .tr ("Split vector layer" ))
47- self .buttonOk = self .buttonBox_2 .button ( QDialogButtonBox .Ok )
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+
4853 # populate layer list
49- self .progressBar .setValue (0 )
5054 mapCanvas = self .iface .mapCanvas ()
5155 layers = ftools_utils .getLayerNames ([QGis .Point , QGis .Line , QGis .Polygon ])
5256 self .inShape .addItems (layers )
@@ -58,63 +62,151 @@ def update(self, inputLayer):
5862 for i in changedField :
5963 self .inField .addItem (unicode (changedField [i ].name ()))
6064
61- def accept (self ):
62- self .buttonOk .setEnabled ( False )
63- if self .inShape .currentText () == "" :
64- QMessageBox .information (self , self .tr ("Vector Split" ), self .tr ("No input shapefile specified" ))
65- elif self .outShape .text () == "" :
66- QMessageBox .information (self , self .tr ("Vector Split" ), self .tr ("Please specify output shapefile" ))
67- else :
68- inField = self .inField .currentText ()
69- inLayer = ftools_utils .getVectorLayerByName (unicode (self .inShape .currentText ()))
70- self .progressBar .setValue (5 )
71- outPath = QString (self .folderName )
72- self .progressBar .setValue (10 )
73- if outPath .contains ("\\ " ):
74- outPath .replace ("\\ " , "/" )
75- self .progressBar .setValue (15 )
76- if not outPath .endsWith ("/" ): outPath = outPath + "/"
77- self .split (inLayer , unicode (outPath ), unicode (inField ), self .progressBar )
78- self .progressBar .setValue (100 )
79- self .outShape .clear ()
80- QMessageBox .information (self , self .tr ("Vector Split" ), self .tr ("Created output shapefiles in folder:\n %1" ).arg ( outPath ))
81- self .progressBar .setValue (0 )
82- self .buttonOk .setEnabled ( True )
83-
8465 def outFile (self ):
8566 self .outShape .clear ()
8667 ( self .folderName , self .encoding ) = ftools_utils .dirDialog ( self )
8768 if self .folderName is None or self .encoding is None :
8869 return
8970 self .outShape .setText ( QString ( self .folderName ) )
9071
91- def split (self , vlayer , outPath , inField , progressBar ):
92- provider = vlayer .dataProvider ()
93- #unique = []
94- index = provider .fieldNameIndex (inField )
95- #provider.uniqueValues(index, unique)
96- unique = ftools_utils .getUniqueValues (vlayer .dataProvider (), int (index ))
97- baseName = unicode ( outPath + vlayer .name () + "_" + inField + "_" )
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 + "_" )
98165 allAttrs = provider .attributeIndexes ()
99166 provider .select (allAttrs )
100- fieldList = ftools_utils .getFieldList (vlayer )
167+ fieldList = ftools_utils .getFieldList (self . layer )
101168 sRs = provider .crs ()
169+ geom = self .layer .wkbType ()
102170 inFeat = QgsFeature ()
103- progressBar . setValue ( 20 )
104- start = 20.00
105- add = 80.00 / len ( unique )
171+
172+ self . emit ( SIGNAL ( "rangeCalculated(PyQt_PyObject)" ), len ( unique ))
173+
106174 for i in unique :
107- check = QFile (baseName + "_" + unicode (i ) + ".shp" )
175+ print "I" , i
176+ print "INDEX" , index
177+ check = QFile (baseName + "_" + unicode (i .toString ().trimmed ()) + ".shp" )
178+ fName = check .fileName ()
108179 if check .exists ():
109- if not QgsVectorFileWriter .deleteShapeFile (baseName + "_" + unicode (i .toString ().trimmed ()) + ".shp" ):
110- return
111- writer = QgsVectorFileWriter (baseName + "_" + unicode (i .toString ().trimmed ()) + ".shp" , self .encoding , fieldList , vlayer .dataProvider ().geometryType (), sRs )
180+ if not QgsVectorFileWriter .deleteShapeFile (fName ):
181+ self .errors .append ( fName )
182+ continue
183+
184+ writer = QgsVectorFileWriter (fName , self .encoding , fieldList , geom , sRs )
112185 provider .rewind ()
113186 while provider .nextFeature (inFeat ):
114187 atMap = inFeat .attributeMap ()
115- #changed from QVariant(i) to below:
188+ #print "AtMAP", atMAP
116189 if atMap [index ] == i :
117190 writer .addFeature (inFeat )
118191 del writer
119- start = start + add
120- progressBar .setValue (start )
192+
193+ self .emit (SIGNAL ("valueProcessed()" ))
194+
195+ self .mutex .lock ()
196+ s = self .stopMe
197+ self .mutex .unlock ()
198+ if s == 1 :
199+ interrupted = True
200+ break
201+
202+ if not interrupted :
203+ self .emit (SIGNAL ("processFinished( PyQt_PyObject )" ), self .errors )
204+ else :
205+ self .emit (SIGNAL ("processInterrupted()" ))
206+
207+ def stop (self ):
208+ self .mutex .lock ()
209+ self .stopMe = 1
210+ self .mutex .unlock ()
211+
212+ QThread .wait (self )
0 commit comments