| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- # -*- coding: utf-8 -*-
- """
- dtmerge
- `````````````
- """
- """
- Part of DigitizingTools, a QGIS plugin that
- subsumes different tools neded during digitizing sessions
- Tool: Merge features to a new feature _without deleting all of them_
- see http://hub.qgis.org/issues/13490
- * begin : 2015-11-09
- * copyright : (C) 2015 by Bernhard Ströbl
- * email : bernhard.stroebl@jena.de
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- """
- from builtins import str
- from qgis.PyQt import QtCore, QtGui, QtWidgets
- from qgis.core import *
- import dt_icons_rc
- from dttools import DtSingleButton
- from dtToolsDialog import DigitizingToolsChooseRemaining
- class DtMerge(DtSingleButton):
- '''Merge selected features of active layer'''
- def __init__(self, iface, toolBar):
- super().__init__(iface, toolBar,
- QtGui.QIcon(":/Merge.png"),
- QtCore.QCoreApplication.translate("digitizingtools",
- "Merge selected features"),
- geometryTypes = [1, 2, 3, 4, 5, 6], dtName = "dtMerge")
- self.enable()
- def process(self):
- '''Function that does all the real work'''
- title = QtCore.QCoreApplication.translate("digitizingtools", "Merge")
- processLayer = self.iface.activeLayer()
- pkAtts = processLayer.primaryKeyAttributes()
- if len(pkAtts) == 1:
- pkFld = pkAtts[0]
- else:
- pkFld = None
- pkValues = {}
- featDict = {}
- fidsToDelete = []
- for aFeat in processLayer.selectedFeatures():
- aFid = aFeat.id()
- featDict[aFid] = aFeat
- if aFid >= 0: # only already existing features
- if pkFld == None:
- pkValues["Feature ID " + str(aFid)] = aFid
- else:
- aPkValue = aFeat[pkFld]
- pkValues[str(aPkValue)] = aFid
- if len(pkValues) > 1:
- dlg = DigitizingToolsChooseRemaining(self.iface, processLayer, pkValues, featDict, title)
- doContinue = dlg.exec_()
- if doContinue == 1:
- pkValueToKeep = dlg.pkValueToKeep
- elif len(pkValues) == 1:
- doContinue = 1
- pkValueToKeep = list(pkValues.keys())[0]
- else: # all new features
- doContinue = 1
- pkValueToKeep = None
- if doContinue == 1:
- processLayer.beginEditCommand(
- QtCore.QCoreApplication.translate("editcommand",
- "Merge Features"))
- if pkValueToKeep != None:
- outFeat = featDict.pop(pkValues[pkValueToKeep])
- else:
- outFeat = featDict.popitem()[1] # use any
- outFid = outFeat.id()
- outGeom = QgsGeometry(outFeat.geometry())
- for aFeatVal in list(featDict.values()):
- fidsToDelete.append(aFeatVal.id())
- outGeom = outGeom.combine(QgsGeometry(aFeatVal.geometry()))
- if not self.geometryTypeMatchesLayer(processLayer, outGeom):
- self.iface.messageBar().pushCritical("DigitizingTools",
- QtWidgets.QApplication.translate("DigitizingTools",
- "The geometry type of the result is not valid in this layer!"))
- processLayer.destroyEditCommand()
- else:
- processLayer.removeSelection()
- success = processLayer.changeGeometry(outFid, outGeom)
- for aFid in fidsToDelete:
- if not processLayer.deleteFeature(aFid):
- processLayer.destroyEditCommand()
- return None
- processLayer.endEditCommand()
- self.iface.mapCanvas().refresh()
- def enable(self):
- '''Enables/disables the corresponding button.'''
- DtSingleButton.enable(self) # call parent's method
- if self.act.isEnabled():
- layer = self.iface.activeLayer()
- try:
- layer.selectionChanged.disconnect(self.enable) # disconnect, will be reconnected
- except:
- pass
- doEnable = layer.selectedFeatureCount() > 1
- self.act.setEnabled(doEnable)
- layer.selectionChanged.connect(self.enable)
|