5

I am trying to apply a style to the output file of a script that I´m running from the toolbox in QGIS 3.4.7. The last step is as described below.

        def processAlgorithm(self, parameters, context, feedback):

        if parameters['Input1'] is not None:
            source = self.parameterAsSource(parameters,'Input1',context)
            (sink, dest_id3) = self.parameterAsSink(parameters,'Output1',context,source.fields(),source.wkbType(),source.sourceCrs())
            total = 100.0 / source.featureCount() if source.featureCount() else 0
            features = source.getFeatures()
            for current, feature in enumerate(features):
                sink.addFeature(feature, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))

After that, I would like to apply a fixed style to the output file so that it will be displayed on Layers with the applied style. I reached the lines below:

                self.source.loadNamedStyle(u"C:\\Users\\ct279359\\Desktop\\Styles\\Roads.qml")
                self.source.triggerRepaint() 

I got this error:

AttributeError: 'InOut' object has no attribute 'source'

I would like to know the correct way to call the output file created in the first part.

I did some research on the subject Here, Here, Here, Here, Here and Here.

All explain ways to invoke the QML file or how to change the style of a file that is already in the Layers section. I need next to this, to invoke the correct output file.

-------------------------------------------------------------
Full code here.

from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
                       QgsFeatureSink,
                       QgsProcessingException,
                       QgsProcessingAlgorithm,
                       QgsProcessingParameterVectorLayer,
                       QgsProcessingParameterFeatureSink,
                       QgsProcessingParameterRasterLayer,
                       QgsProcessingParameterRasterDestination,
                       QgsVectorLayer,
                       QgsProject)
import processing

class InOut(QgsProcessingAlgorithm):

    def tr(self, string):
        return QCoreApplication.translate('Processing', string)

    def createInstance(self):
        return InOut()

    def name(self):
        return 'InOut2'

    def displayName(self):
        return self.tr('InOut2')

    def group(self):
        return self.tr('Auxiliares')

    def groupId(self):
        return 'auxiliares1'


    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterVectorLayer('Input1','Input1',optional=True, types=[QgsProcessing.TypeVector], defaultValue=None))
        self.addParameter(QgsProcessingParameterFeatureSink('Output1','Output1', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))

    def processAlgorithm(self, parameters, context, feedback):

        if parameters['Input1'] is not None:
            source = self.parameterAsSource(parameters,'Input1',context)
            (sink, dest_id3) = self.parameterAsSink(parameters,'Output1',context,source.fields(),source.wkbType(),source.sourceCrs())
            total = 100.0 / source.featureCount() if source.featureCount() else 0
            features = source.getFeatures()
            for current, feature in enumerate(features):
                sink.addFeature(feature, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))

                self.source.loadNamedStyle(u"C:\\Users\\ct279359\\Desktop\\Styles\\Roads.qml")
                self.source.triggerRepaint()

        return results

1 Answer 1

1

You need to turn the layer into a QGIS vector layer when importing it:

        #define vector layer  
        vlayer = QgsVectorLayer('your_output_file', 'layer_name', "ogr")
        # add the layer to the registry
        QgsProject.instance().addMapLayer(vlayer)
        # load style
        vlayer.loadNamedStyle('path_to_qml.qml')
9
  • 1
    Don't do that if your script is set to run in a background thread (which is the default). You'll get crashes and all kinds of unpredictable behaviour as a result.
    – ndawson
    Nov 18, 2019 at 22:04
  • @ndawson, could you explain what you mean? Interested to learn more about crashes that could occur. Never had a problem on my side when importing layers with styles.
    – B-C B.
    Nov 18, 2019 at 22:43
  • 3
    There's a few issues: 1. QgsProject cannot be accessed from anything but the main thread 2. If you create a QgsVectorLayer (or ANY QObject derived class) from a background thread, the object belongs to that thread and should only be accessed from that thread. By transferring it to the project instance (which lives in the main thread) the results will be unpredictable at best (and crashy at worst).
    – ndawson
    Nov 19, 2019 at 1:47
  • I see. What would be the correct way to import a layer into qgis with a style without using the main thread?
    – B-C B.
    Nov 19, 2019 at 2:45
  • @B-C B. Even with the ndawson's warning, it didn't work out. I edited the question and put in my full code, maybe I forgot to mention something important. Nov 19, 2019 at 14:21

Your Answer

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

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