3

I created a QGIS Plugin which is available in the processing toolbar. I want to give users the possibility to either create a new temporary layer (or save in a new file) or use the "edit feature in place" possibility of QGIS processing:

Button to edit feature in place

I couldn't find a solution in this tutorial: https://www.qgistutorials.com/en/docs/3/processing_python_plugin.html When I activate the "edit feature in place", my self-made processing tool is not available.

Alternatively I would have to only give the possibility to edit features in an existing layer as in this answer: https://gis.stackexchange.com/a/412130/193285

Taras
35.8k5 gold badges77 silver badges152 bronze badges
asked May 22 at 14:08

1 Answer 1

6

To allow your custom algorithm to edit features in place and be available in the toolbox when the Edit Features In-Place icon is toggled on, you need to override two methods in your QgsProcessingAlgorithm sub-class.

The first is the flags() method where you need to return the SupportsInPlaceEdits ProcessingAlgorithmFlag.

E.g.

def flags(self):
 return Qgis.ProcessingAlgorithmFlag.SupportsInPlaceEdits

Note that prior to QGIS 3.36, this would be:

def flags(self):
 return QgsProcessingAlgorithm.FlagSupportsInPlaceEdits

Secondly, you need to also override the supportInPlaceEdit() method. the QgsMapLayer argument which gets passed to this method is the active layer (on which the algorithm would be executed in place). So this method needs to return a Boolean value based on whether the active layer can support the algorithm's operation. For example, if your algorithm produces geometries of a different type than the input layer, it can not be run in place. e.g. a buffer operation cannot edit features in place with a point or line input layer.

So, in this method, you need to take care to do whatever checks are necessary and only return True if the operations implemented in your algorithm can be successfully run on the features of the input layer e.g.

def supportInPlaceEdit(self, lyr):
 return lyr.wkbType() == Qgis.WkbType.Polygon or lyr.wkbType() == Qgis.WkbType.MultiPolygon

Or for versions prior to 3.30:

def supportInPlaceEdit(self, lyr):
 return lyr.wkbType() == QgsWkbTypes.Polygon or lyr.wkbType() == QgsWkbTypes.MultiPolygon

Here is a complete, basic example script:

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (Qgis, QgsProcessing, QgsProcessingAlgorithm,
 QgsProcessingParameterFeatureSource, QgsProcessingParameterDistance,
 QgsProcessingParameterFeatureSink, QgsFeature, QgsWkbTypes,
 QgsFeatureSink)
 
class ExBufferInPlace(QgsProcessingAlgorithm):
 INPUT = 'INPUT'
 DISTANCE = 'DISTANCE'
 OUTPUT = 'OUTPUT'
 
 def __init__(self):
 super().__init__()
 
 def name(self):
 return "bufferpoly"
 
 def tr(self, text):
 return QCoreApplication.translate("bufferpoly", text)
 
 def displayName(self):
 return self.tr("In place example")
 
 def group(self):
 return self.tr("Examples")
 
 def groupId(self):
 return "examples"
 
 def shortHelpString(self):
 return self.tr("Example supporting edit in place")
 
 def helpUrl(self):
 return "https://qgis.org"
 
 def createInstance(self):
 return type(self)()
 
 def flags(self):
 return QgsProcessingAlgorithm.FlagSupportsInPlaceEdits
 
 def initAlgorithm(self, config=None):
 self.addParameter(QgsProcessingParameterFeatureSource(
 self.INPUT,
 self.tr("Input layer"),
 [QgsProcessing.TypeVectorAnyGeometry]))
 
 self.addParameter(QgsProcessingParameterDistance(
 self.DISTANCE,
 self.tr('Distance'),
 parentParameterName=self.INPUT))
 self.addParameter(QgsProcessingParameterFeatureSink(
 self.OUTPUT,
 self.tr("Output layer"),
 QgsProcessing.TypeVectorAnyGeometry))
 
 def supportInPlaceEdit(self, lyr):
 return lyr.wkbType() == QgsWkbTypes.Polygon or lyr.wkbType() == QgsWkbTypes.MultiPolygon
 
 def processAlgorithm(self, parameters, context, feedback):
 source = self.parameterAsSource(parameters, self.INPUT, context)
 dist_value = self.parameterAsDouble(parameters, self.DISTANCE, context)
 (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
 source.fields(), QgsWkbTypes.Polygon, source.sourceCrs())
 
 for f in source.getFeatures():
 g = f.geometry().buffer(dist_value, 25)
 out_feat = QgsFeature()
 out_feat.setGeometry(g)
 out_feat.setAttributes(f.attributes())
 sink.addFeature(out_feat, QgsFeatureSink.FastInsert)
 return {self.OUTPUT: dest_id}

The resulting behaviour is shown below- with the edit in place filter toggled on and a polygon layer selected, my example algorithm is available:

enter image description here

If I switch the active layer to a point layer, my algorithm is no longer available:

enter image description here

Taras
35.8k5 gold badges77 silver badges152 bronze badges
answered May 23 at 0:58

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.