diff --git a/python/plugins/fTools/tools/doMergeShapes.py b/python/plugins/fTools/tools/doMergeShapes.py index 452f3ad1a5e..cd7dcd67d12 100755 --- a/python/plugins/fTools/tools/doMergeShapes.py +++ b/python/plugins/fTools/tools/doMergeShapes.py @@ -58,8 +58,8 @@ class Dialog( QDialog, Ui_Dialog ): 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 @@ -134,7 +134,7 @@ class Dialog( QDialog, Ui_Dialog ): self.btnOk.setEnabled( False ) self.mergeThread = ShapeMergeThread( baseDir, self.inputFiles, self.inEncoding, self.outFileName, self.encoding ) - QObject.connect( self.mergeThread, SIGNAL( "rangeChanged( PyQt_PyObject )" ), self.setProgressRange ) + 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 ) @@ -149,8 +149,8 @@ class Dialog( QDialog, Ui_Dialog ): 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 ): @@ -216,13 +216,38 @@ class ShapeMergeThread( QThread ): 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 ) @@ -234,6 +259,7 @@ class ShapeMergeThread( QThread ): continue vprovider = newLayer.dataProvider() vprovider.setEncoding( self.inputEncoding ) + layerFields = vprovider.fields() allAttrs = vprovider.attributeIndexes() vprovider.select( allAttrs ) nFeat = vprovider.featureCount() @@ -244,9 +270,15 @@ class ShapeMergeThread( QThread ): 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()" ) ) diff --git a/python/plugins/fTools/tools/ftools_utils.py b/python/plugins/fTools/tools/ftools_utils.py index 1ca4b368a1b..661ca6c058b 100755 --- a/python/plugins/fTools/tools/ftools_utils.py +++ b/python/plugins/fTools/tools/ftools_utils.py @@ -253,7 +253,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() @@ -269,18 +269,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 ):