4

How can I import a .qml style from a file and apply it to a sink?

In QGIS 2.18, I used something like that script:

output=QgsVectorLayer ('Point?crs=EPSG:2154','output', 'memory')
path_style='./path/to/style.qml'
output.loadNamedStyle(path_style)
output.triggerRepaint()

But when I tried it on anita graser's example of QGIS3 script, .loadNamedStyle() wouldn't work on the sink OUTPUT:

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsField, QgsFeature, QgsFeatureSink, QgsFeatureRequest, QgsProcessing, QgsProcessingAlgorithm, QgsProcessingParameterFeatureSource, QgsProcessingParameterFeatureSink)

class ExAlgo(QgsProcessingAlgorithm):
    INPUT = 'INPUT'
    OUTPUT = 'OUTPUT'
    def __init__(self):
        super().__init__()
    def name(self):
        return "exalgo"
    def tr(self, text):
        return QCoreApplication.translate("exalgo", text)
    def createInstance(self):
        return type(self)()

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFeatureSource(
            self.INPUT,
            self.tr("Input layer"),
            [QgsProcessing.TypeVectorAnyGeometry]))
        self.addParameter(QgsProcessingParameterFeatureSink(
            self.OUTPUT,
            self.tr("Output layer"),
            QgsProcessing.TypeVectorAnyGeometry))

    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(QgsFeatureRequest())
        for feat in features:
            out_feat = QgsFeature()
            out_feat.setGeometry(feat.geometry())
            out_feat.setAttributes(feat.attributes())
            sink.addFeature(out_feat, QgsFeatureSink.FastInsert)

        # --------------------the part that doesn't work:
        path_style='./path/to/style.qml'
        sink.loadNamedStyle(path_style)
        sink.triggerRepaint()
        #--------------------

        return {self.OUTPUT: dest_id}

Is there a simple way to load and apply a style in the new QGIS Processing?

1

2 Answers 2

4

you need call def postProcessAlgorithm method.I add an example of how the code should be,

    def postProcessAlgorithm(self, context, feedback):
        """
        PostProcessing to define the Symbology
        """
        output = QgsProcessingUtils.mapLayerFromString(self.dest_id, context)
        path = ='./path/to/style.qml'
        output.loadNamedStyle(path)
        output.triggerRepaint()
        return {self.OUTPUT: self.dest_id}
2
  • Simply pasting your code didn't work however when I read your sample code in your first answer, line 521" to get hold of the layer in post processing" I finally understood.
    – LeoC
    Commented May 7, 2019 at 15:26
  • does it still work for QGIS 3.16? It seems to no longer work for me or i got something else wrong
    – miraculix
    Commented Mar 18, 2022 at 18:52
2

Thank you @Fran Raga for your answer, the example you gave didn't work at first but by reading the sample code you provided in your first comment I finnaly succeded here's what works for me:

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsField, QgsFeature, QgsFeatureSink, QgsFeatureRequest, QgsProcessing, QgsProcessingAlgorithm, QgsProcessingParameterFeatureSource, QgsProcessingParameterFeatureSink)

class ExAlgo(QgsProcessingAlgorithm):
    INPUT = 'INPUT'
    OUTPUT = 'OUTPUT'
    def __init__(self):
        super().__init__()
    def name(self):
        return "exalgo"
    def tr(self, text):
        return QCoreApplication.translate("exalgo", text)
    def createInstance(self):
        return type(self)()

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFeatureSource(
            self.INPUT,
            self.tr("Input layer"),
            [QgsProcessing.TypeVectorAnyGeometry]))
        self.addParameter(QgsProcessingParameterFeatureSink(
            self.OUTPUT,
            self.tr("Output layer"),
            QgsProcessing.TypeVectorAnyGeometry))

    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(QgsFeatureRequest())
        for feat in features:
            out_feat = QgsFeature()
            out_feat.setGeometry(feat.geometry())
            out_feat.setAttributes(feat.attributes())
            sink.addFeature(out_feat, QgsFeatureSink.FastInsert)

        # to get hold of the layer in post processing:
        self.dest_id=dest_id

        return {self.OUTPUT: dest_id}

    #Changes suggested by Fran Raga:   
    def postProcessAlgorithm(self, context, feedback):
        output = QgsProcessingUtils.mapLayerFromString(self.dest_id, context)
        path='./path/to/style.qml'
        output.loadNamedStyle(path)
        output.triggerRepaint()
        return {self.OUTPUT: self.dest_id}

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.