Skip to content
Permalink
Browse files
apply Merge Shapefiles fixes from master
  • Loading branch information
alexbruy committed Feb 24, 2012
1 parent fe3bb76 commit 5e0766729b1f292eef750a85ea3a4b0e11e42f67
Showing with 78 additions and 17 deletions.
  1. +68 −13 python/plugins/fTools/tools/doMergeShapes.py
  2. +10 −4 python/plugins/fTools/tools/ftools_utils.py
@@ -12,20 +12,22 @@

class Dialog( QDialog, Ui_Dialog ):
def __init__( self, iface ):
QDialog.__init__( self )
QDialog.__init__( self, iface.mainWindow() )
self.setupUi( self )
self.iface = iface

self.mergeThread = None
self.inputFiles = None
self.outFileName = None
self.inEncoding = None

self.btnOk = self.buttonBox.button( QDialogButtonBox.Ok )
self.btnClose = self.buttonBox.button( QDialogButtonBox.Close )

QObject.connect( self.btnSelectDir, SIGNAL( "clicked()" ), self.inputDir )
QObject.connect( self.btnSelectFile, SIGNAL( "clicked()" ), self.outFile )
QObject.connect( self.chkListMode, SIGNAL( "stateChanged( int )" ), self.changeMode )
QObject.connect( self.leOutShape, SIGNAL( "editingFinished()" ), self.updateOutFile )

def inputDir( self ):
inDir = QFileDialog.getExistingDirectory( self,
@@ -56,8 +58,8 @@ def outFile( self ):
self.leOutShape.setText( self.outFileName )

def inputFile( self ):
files = QFileDialog.getOpenFileNames( self, self.tr( "Select files to merge" ), ".", "Shapefiles(*.shp *.SHP)" )
if files.isEmpty():
( files, self.inEncoding ) = ftools_utils.openDialog( self, dialogMode="ManyFiles" )
if files is None or self.inEncoding is None:
self.inputFiles = None
return

@@ -83,6 +85,11 @@ def changeMode( self ):
self.lblGeometry.setEnabled( True )
self.cmbGeometry.setEnabled( True )

def updateOutFile( self ):
self.outFileName = self.leOutShape.text()
settings = QSettings()
self.outEncoding = settings.value( "/UI/encoding" ).toString()

def reject( self ):
QDialog.reject( self )

@@ -113,8 +120,6 @@ def accept( self ):
self.inputFiles = ftools_utils.getShapesByGeometryType( baseDir, self.inputFiles, self.cmbGeometry.currentIndex() )
self.progressFiles.setRange( 0, self.inputFiles.count() )

self.progressFiles.setRange( 0, self.inputFiles.count() )

outFile = QFile( self.outFileName )
if outFile.exists():
if not QgsVectorFileWriter.deleteShapeFile( self.outFileName ):
@@ -126,8 +131,11 @@ def accept( self ):

self.btnOk.setEnabled( False )

self.mergeThread = ShapeMergeThread( baseDir, self.inputFiles, self.outFileName, self.encoding )
QObject.connect( self.mergeThread, SIGNAL( "rangeChanged( PyQt_PyObject )" ), self.setProgressRange )
self.mergeThread = ShapeMergeThread( baseDir, self.inputFiles, self.inEncoding, self.outFileName, self.encoding )
QObject.connect( self.mergeThread, SIGNAL( "rangeChanged( PyQt_PyObject )" ), self.setFeatureProgressRange )
QObject.connect( self.mergeThread, SIGNAL( "checkStarted()" ), self.setFeatureProgressFormat )
QObject.connect( self.mergeThread, SIGNAL( "checkFinished()" ), self.resetFeatureProgressFormat )
QObject.connect( self.mergeThread, SIGNAL( "fileNameChanged( PyQt_PyObject )" ), self.setShapeProgressFormat )
QObject.connect( self.mergeThread, SIGNAL( "featureProcessed()" ), self.featureProcessed )
QObject.connect( self.mergeThread, SIGNAL( "shapeProcessed()" ), self.shapeProcessed )
QObject.connect( self.mergeThread, SIGNAL( "processingFinished()" ), self.processingFinished )
@@ -139,13 +147,22 @@ def accept( self ):

self.mergeThread.start()

def setProgressRange( self, max ):
self.progressFeatures.setRange( 0, max )
def setFeatureProgressRange( self, maximum ):
self.progressFeatures.setRange( 0, maximum )
self.progressFeatures.setValue( 0 )

def setFeatureProgressFormat( self ):
self.progressFeatures.setFormat( "Checking files: %p% ")

def resetFeatureProgressFormat( self ):
self.progressFeatures.setFormat( "%p% ")

def featureProcessed( self ):
self.progressFeatures.setValue( self.progressFeatures.value() + 1 )

def setShapeProgressFormat( self, fileName ):
self.progressFiles.setFormat( "%p% " + fileName )

def shapeProcessed( self ):
self.progressFiles.setValue( self.progressFiles.value() + 1 )

@@ -154,7 +171,9 @@ def processingFinished( self ):

if self.chkAddToCanvas.isChecked():
if not ftools_utils.addShapeToCanvas( unicode( self.outFileName ) ):
QMessageBox.warning( self, self.tr( "Merging" ), self.tr( "Error loading output shapefile:\n%1" ).arg( unicode( self.outFileName ) ) )
QMessageBox.warning( self, self.tr( "Merging" ),
self.tr( "Error loading output shapefile:\n%1" )
.arg( unicode( self.outFileName ) ) )

self.restoreGui()

@@ -167,6 +186,7 @@ def stopProcessing( self ):
self.mergeThread = None

def restoreGui( self ):
self.progressFiles.setFormat( "%p%" )
self.progressFeatures.setRange( 0, 100 )
self.progressFeatures.setValue( 0 )
self.progressFiles.setValue( 0 )
@@ -175,10 +195,11 @@ def restoreGui( self ):
self.btnOk.setEnabled( True )

class ShapeMergeThread( QThread ):
def __init__( self, dir, shapes, outputFileName, outputEncoding ):
def __init__( self, dir, shapes, inputEncoding, outputFileName, outputEncoding ):
QThread.__init__( self, QThread.currentThread() )
self.baseDir = dir
self.shapes = shapes
self.inputEncoding = inputEncoding
self.outputFileName = outputFileName
self.outputEncoding = outputEncoding

@@ -192,13 +213,38 @@ def run( self ):

interrupted = False

# create attribute list with uniquie fields
# from all selected layers
mergedFields = {}
count = 0
self.emit( SIGNAL( "rangeChanged( PyQt_PyObject )" ), len( self.shapes ) )
self.emit( SIGNAL( "checkStarted()" ) )
for fileName in self.shapes:
layerPath = QFileInfo( self.baseDir + "/" + fileName ).absoluteFilePath()
newLayer = QgsVectorLayer( layerPath, QFileInfo( layerPath ).baseName(), "ogr" )
if not newLayer.isValid():
continue
vprovider = newLayer.dataProvider()
layerFields = vprovider.fields()
for layerIndex, layerField in layerFields.iteritems():
fieldFound = False
for mergedIndex, mergedField in mergedFields.iteritems():
if ( mergedField.name() == layerField.name() ) and ( mergedField.type() == layerField.type() ):
fieldFound = True

if not fieldFound:
mergedFields[ count ] = layerField
count += 1
self.emit( SIGNAL( "featureProcessed()" ) )
self.emit( SIGNAL( "checkFinished()" ) )

# get information about shapefiles
layerPath = QFileInfo( self.baseDir + "/" + self.shapes[ 0 ] ).absoluteFilePath()
newLayer = QgsVectorLayer( layerPath, QFileInfo( layerPath ).baseName(), "ogr" )
self.crs = newLayer.crs()
self.geom = newLayer.wkbType()
vprovider = newLayer.dataProvider()
self.fields = vprovider.fields()
self.fields = mergedFields

writer = QgsVectorFileWriter( self.outputFileName, self.outputEncoding,
self.fields, self.geom, self.crs )
@@ -209,18 +255,27 @@ def run( self ):
if not newLayer.isValid():
continue
vprovider = newLayer.dataProvider()
vprovider.setEncoding( self.inputEncoding )
layerFields = vprovider.fields()
allAttrs = vprovider.attributeIndexes()
vprovider.select( allAttrs )
nFeat = vprovider.featureCount()
self.emit( SIGNAL( "rangeChanged( PyQt_PyObject )" ), nFeat )
self.emit( SIGNAL( "fileNameChanged( PyQt_PyObject )" ), fileName )
inFeat = QgsFeature()
outFeat = QgsFeature()
inGeom = QgsGeometry()
while vprovider.nextFeature( inFeat ):
atMap = inFeat.attributeMap()
mergedAttrs = {}
# fill available attributes with values
for layerIndex, layerField in layerFields.iteritems():
for mergedIndex, mergedField in self.fields.iteritems():
if ( mergedField.name() == layerField.name() ) and ( mergedField.type() == layerField.type() ):
mergedAttrs[ mergedIndex ] = atMap[ layerIndex ]
inGeom = QgsGeometry( inFeat.geometry() )
outFeat.setGeometry( inGeom )
outFeat.setAttributeMap( atMap )
outFeat.setAttributeMap( mergedAttrs )
writer.addFeature( outFeat )
self.emit( SIGNAL( "featureProcessed()" ) )

@@ -255,7 +255,7 @@ def getUniqueValues( provider, index ):
return values

# Generate a save file dialog with a dropdown box for choosing encoding style
def saveDialog( parent, filtering="Shapefiles (*.shp)"):
def saveDialog( parent, filtering="Shapefiles (*.shp *.SHP)"):
settings = QSettings()
dirName = settings.value( "/UI/lastShapefileDir" ).toString()
encode = settings.value( "/UI/encoding" ).toString()
@@ -271,18 +271,24 @@ def saveDialog( parent, filtering="Shapefiles (*.shp)"):
return ( unicode( files.first() ), unicode( fileDialog.encoding() ) )

# Generate a save file dialog with a dropdown box for choosing encoding style
def openDialog( parent, filtering="Shapefiles (*.shp)"):
# with mode="SingleFile" will allow to select only one file, in other cases - several files
def openDialog( parent, filtering="Shapefiles (*.shp *.SHP)", dialogMode="SingleFile"):
settings = QSettings()
dirName = settings.value( "/UI/lastShapefileDir" ).toString()
encode = settings.value( "/UI/encoding" ).toString()
fileDialog = QgsEncodingFileDialog( parent, "Save output shapefile", dirName, QString(filtering), encode )
fileDialog.setFileMode( QFileDialog.AnyFile )
#fileDialog.setFileMode( QFileDialog.AnyFile )
fileDialog.setFileMode( QFileDialog.ExistingFiles )
fileDialog.setAcceptMode( QFileDialog.AcceptOpen )
if not fileDialog.exec_() == QDialog.Accepted:
return None, None
files = fileDialog.selectedFiles()
settings.setValue("/UI/lastShapefileDir", QVariant( QFileInfo( unicode( files.first() ) ).absolutePath() ) )
return ( unicode( files.first() ), unicode( fileDialog.encoding() ) )
#return ( unicode( files.first() ), unicode( fileDialog.encoding() ) )
if dialogMode == "SingleFile":
return ( unicode( files.first() ), unicode( fileDialog.encoding() ) )
else:
return ( files, unicode( fileDialog.encoding() ) )

# Generate a select directory dialog with a dropdown box for choosing encoding style
def dirDialog( parent ):

0 comments on commit 5e07667

Please sign in to comment.