While extending a plugin with a Processing Provider and a set of algorithms I mostly followed the defaults of Plugin Builder 3
. So, the basic code is smth along the lines of
class ORSisochronesAlgo(QgsProcessingAlgorithm):
def initAlgorithm(self, configuration, p_str=None, Any=None, *args, **kwargs):
# add all input parameters
self.addParameter(
QgsProcessingParameterFeatureSink(
'OUTPUT',
'Output layer'
)
)
def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.INPUT, context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
context, source.fields(), source.wkbType(), source.sourceCrs())
features = source.getFeatures()
for feature in features:
new_feature = QgsFeature()
# Some API calls and processing to populate new feature
sink.addFeature(new_feature, QgsFeatureSink.FastInsert)
return {self.OUTPUT: dest_id}
So, the output layer is automatically handled and added to the map. Very nice!
But now: How do I post-process that output layer within the Processing Algorithm? Sounds weird maybe, but here are 2 scenarios:
Depending on the value of a Boolean input parameter, I'd like to be able to calculate geometric differences of the output features. For this to work, the layer has to be built first. And then handled in some sort of post-processing.
Also, I'd like to be able to customize the style of the output layer.
There is the postProcessAlgorithm()
method for QgsProcessingAlgorithm
, but I'm not so sure how to work with this.. It doesn't seem to take parameters
as input, no idea how to access the output layer.
Being able to do this would make the plugin so much more user-friendly.
1 Answer 1
Just to be more elaborate than the comment.
Basically, the postProcessAlgorithm()
does what it says. It also returns a value map, including the OUTPUT
. However, you need to look up the layer in the algorithm's context with QgsProcessingUtils.mapLayerFromString()
. For that to work, you have to save a reference to the original output layer from processAlgorithm()
:
class ORSisochronesAlgo(QgsProcessingAlgorithm):
dest_id = None # Save a reference to the output layer id
def initAlgorithm(self, configuration, p_str=None, Any=None, *args, **kwargs):
# add all input parameters
self.addParameter(
QgsProcessingParameterFeatureSink(
'OUTPUT',
'Output layer'
)
)
def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.INPUT, context)
(sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
context, source.fields(), source.wkbType(), source.sourceCrs())
features = source.getFeatures()
for feature in features:
new_feature = QgsFeature()
# Some API calls and processing to populate new feature
sink.addFeature(new_feature, QgsFeatureSink.FastInsert)
return {self.OUTPUT: dest_id}
def postProcessAlgorithm(self, context, feedback):
processed_layer = QgsProcessingUtils.mapLayerFromString(self.dest_id, context)
# Do smth with the layer, e.g. style it
return {self.OUT: self.dest_id}
-
I think it should be return {self.OUPUT: self.dest_id}CitizenFish– CitizenFish2021年11月08日 11:15:32 +00:00Commented Nov 8, 2021 at 11:15
QgsProcessingUtils.mapLayerFromString()
lets one access layers from the provided context and one can use that in the class'spostProcessAlgorithm()
. I'll post an answer if I have entirely succeeded. At least styling the layer already works:)