def __init__(self, iface,  parent=None):
        QtGui.QDialog.__init__(self, parent)

        self.parent = parent
        self.plugin_dir = os.path.dirname(__file__)

        # initialize locale
        locale = QtCore.QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n', 'mergeLayers_{}.qm'.format(locale))
        if os.path.exists(locale_path):
            self.translator = QtCore.QTranslator()
            self.translator.load(locale_path)
            QtCore.QCoreApplication.installTranslator(self.translator)

        self.NOMATCH  = "<no match>"

        self.ui = Ui_mergeLayersDialogBase()
        self.ui.setupUi(self)
        self.layers = []
        self.iface = iface
        self.updateLayers()
        self._initGui()
class mergeLayersDialog(QtGui.QDialog):

    def __init__(self, iface,  parent=None):
        QtGui.QDialog.__init__(self, parent)

        self.parent = parent
        self.plugin_dir = os.path.dirname(__file__)

        # initialize locale
        locale = QtCore.QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n', 'mergeLayers_{}.qm'.format(locale))
        if os.path.exists(locale_path):
            self.translator = QtCore.QTranslator()
            self.translator.load(locale_path)
            QtCore.QCoreApplication.installTranslator(self.translator)

        self.NOMATCH  = "<no match>"

        self.ui = Ui_mergeLayersDialogBase()
        self.ui.setupUi(self)
        self.layers = []
        self.iface = iface
        self.updateLayers()
        self._initGui()

    def trans(self, message, **kwargs):
        trans = QtCore.QCoreApplication.translate('mergeLayers', message)
        if isinstance( trans, str ): return trans
        else: return message

    def accept(self):
        sourceLyr, targetLyr = (None,None)
        for lyr in self.layers:
            if lyr.name() ==  self.ui.sourceCbx.currentText():
                sourceLyr = lyr
            if lyr.name() ==  self.ui.targetCbx.currentText():
                targetLyr = lyr

        if not sourceLyr or not targetLyr:
            QtGui.QMessageBox.warning(self, self.trans("Warning"),
                                      self.trans("Layers are not set correctly"), '')
            return
        if  sourceLyr == targetLyr:
            QtGui.QMessageBox.warning(self, self.trans("Warning"),
                                      self.trans("Target and source are the same."), '')
            return
        if self.ui.add2targetRadio.isChecked() and not (targetLyr.dataProvider().capabilities() & QgsVectorDataProvider.AddFeatures):
            QtGui.QMessageBox.warning(self, self.trans("Warning"),
                                      self.trans("Target is not editable, try merge to new layer"), '')
            return
        if sourceLyr.geometryType() != targetLyr.geometryType():
            QtGui.QMessageBox.warning(self, self.trans("Geometries don't match"),
                                      self.trans("The geometries of inputlayer and targerlayer don't match, so the files can't be merged"), '')
            return
        if self.ui.merge2newRadio.isChecked() and len( self.ui.outputFileTxt.text() ) == 0:
            QtGui.QMessageBox.warning(self, self.trans("Need a output location"),
                                      self.trans("Define a output location on for the merged layer by clicking on the 'File'-button"), '')
            return

        if self.ui.add2targetRadio.isChecked():
            self.addsource2target(sourceLyr, targetLyr)
        else:
            self.mergeSourceAndTarget(sourceLyr, targetLyr)
        self.refresh(targetLyr)
        self.close()

    def _initGui(self):
        self.ui.matchTbl.setColumnWidth(0, 120)
        self.ui.matchTbl.setColumnWidth(1, 120)

        #ADD EVENTS
        self.iface.mapCanvas().layersChanged.connect( self.updateLayers )
        self.ui.sourceCbx.currentIndexChanged.connect( self.updateMatchWidget )
        self.ui.targetCbx.currentIndexChanged.connect( self.updateMatchWidget )
        self.ui.outputFileBtn.clicked.connect(self.setOutput)

    def updateMatchWidget(self):
        sourceLyrName = self.ui.sourceCbx.currentText()
        targetLyrName = self.ui.targetCbx.currentText()
        sourceLyr = None
        targetLyr = None
        self.ui.matchTbl.setHorizontalHeaderLabels([sourceLyrName,targetLyrName])

        for lyr in self.layers:
            if lyr.name() == sourceLyrName:
                sourceLyr = lyr
            if lyr.name() == targetLyrName:
                targetLyr = lyr

        if not sourceLyr or not targetLyr:
            return

        sourceFields = sourceLyr.pendingFields()
        self.ui.matchTbl.setRowCount( sourceFields.count() )
        rowIndex = 0
        for field in sourceFields:
            sourceName = field.name()
            sourceType = field.type()
            targetFields = [self.NOMATCH] + [f.name() for f in targetLyr.pendingFields()
                                                      if f.type() == sourceType or sourceType == 10 ]
            targetFieldCbx = QtGui.QComboBox()
            targetFieldCbx.insertItems(0, targetFields)

            if sourceName in targetFields:
                targetFieldCbx.setCurrentIndex( targetFields.index(sourceName) )

            #populate the table
            self.ui.matchTbl.setCellWidget( rowIndex, 0, QtGui.QLabel(sourceName) )
            self.ui.matchTbl.setCellWidget( rowIndex, 1, targetFieldCbx )
            rowIndex += 1

    def updateLayers(self):
        self.layers = QgsMapLayerRegistry.instance().mapLayers().values()
        lyrs = [layer.name() for layer in self.layers if layer.type() == QgsMapLayer.VectorLayer ]
        editLayers = [layer.name() for layer in self.layers
                      if layer.type() == QgsMapLayer.VectorLayer and layer.dataProvider().capabilities() ]
        self.ui.sourceCbx.clear()
        self.ui.targetCbx.clear()
        self.ui.sourceCbx.addItems( lyrs )
        self.ui.targetCbx.addItems( editLayers )

        self.updateMatchWidget()

    def table2fieldMap(self):
        fieldMap = []

        for n in range( self.ui.matchTbl.rowCount() ):
            sourceField = self.ui.matchTbl.cellWidget(n, 0).text()
            targetField = self.ui.matchTbl.cellWidget(n, 1).currentText()
            fieldMap.append(( targetField, sourceField ))
        return fieldMap

    def addsource2target(self, sourceLyr, targetLyr):
        newFeats = []
        fieldMap = self.table2fieldMap()
        targetType = targetLyr.dataProvider().storageType()

        targetLyr.beginEditCommand("Starting to append..")  # use editbuffer
        for sourceFeat in sourceLyr.getFeatures():
            newFeat = QgsFeature(targetLyr.pendingFields())

            for targetField, sourceField in fieldMap:
                if targetType == "ESRI Shapefile":
                    targetField = utils.nameMaxLenght( targetField , 10)

                if targetField != self.NOMATCH:
                        newFeat.setAttribute(targetField, sourceFeat[sourceField])

            newFeat.setGeometry(sourceFeat.geometry())
            newFeats.append(newFeat)

            if len(newFeats) > 5000:  # append in blocks of 5000 the speed up.
                targetLyr.dataProvider().addFeatures(newFeats)
                newFeats = []
        targetLyr.dataProvider().addFeatures(newFeats)  # add remaining
        targetLyr.endEditCommand()

    def mergeSourceAndTarget(self, source, target):
        fpath = self.ui.outputFileTxt.text()
        newlayer = utils.copyLayer(fpath, target)
        QgsMapLayerRegistry.instance().addMapLayer( newlayer )
        self.addsource2target(source, newlayer)

    def setOutput(self):
        home = os.path.expanduser('~')
        title = self.trans(u"Save As")
        ftypeFilter = "Shapefile (*.shp);;Geopackage (*.gpkg);;GeoJSON (*.geojson);;Mapinfo (*.tab);;GML ($.gml);;SQLITE (*.sqlite)"
        outFile = QtGui.QFileDialog.getSaveFileName( self, title, filter=ftypeFilter, directory=home )
        self.ui.outputFileTxt.setText(outFile)

    def refresh(self, layer=None):
        if self.iface.mapCanvas().isCachingEnabled() and isinstance(layer, QgsVectorLayer):
            layer.setCacheImage(None)
        else:
            self.iface.mapCanvas().refresh()