From 55ce31b37170a577438fe70f6158d95fce0d2fe4 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 1 Jul 2017 20:04:36 +1000 Subject: [PATCH] When calling procesing.run(), map layer results are automatically converted to QgsMapLayer objects with the ownership transferred to the Python caller This should make it super-easy for PyQGIS scripts to run processing algorithms and immediately utilise the results, even if they are memory layers. They call processing.run(), and get a dict of results back which includes those layers ready for adding to the current project or doing some other processing or operations with, and if they don't transfer to ownership off then these layers will be correctly garbaged collected by Python. --- python/plugins/processing/algs/qgis/ConcaveHull.py | 6 ++---- python/plugins/processing/core/Processing.py | 14 +++++++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/python/plugins/processing/algs/qgis/ConcaveHull.py b/python/plugins/processing/algs/qgis/ConcaveHull.py index 38800d640d1..b91ed220250 100644 --- a/python/plugins/processing/algs/qgis/ConcaveHull.py +++ b/python/plugins/processing/algs/qgis/ConcaveHull.py @@ -87,8 +87,7 @@ class ConcaveHull(QgisAlgorithm): # Delaunay triangulation from input point layer feedback.setProgressText(self.tr('Creating Delaunay triangles...')) - delone_triangles = processing.run("qgis:delaunaytriangulation", {'INPUT': parameters[ConcaveHull.INPUT], 'OUTPUT': 'memory:'}, feedback=feedback, context=context)['OUTPUT'] - delaunay_layer = context.takeResultLayer(delone_triangles) + delaunay_layer = processing.run("qgis:delaunaytriangulation", {'INPUT': parameters[ConcaveHull.INPUT], 'OUTPUT': 'memory:'}, feedback=feedback, context=context)['OUTPUT'] # Get max edge length from Delaunay triangles feedback.setProgressText(self.tr('Computing edges max length...')) @@ -131,8 +130,7 @@ class ConcaveHull(QgisAlgorithm): # Dissolve all Delaunay triangles feedback.setProgressText(self.tr('Dissolving Delaunay triangles...')) - dissolved = processing.run("native:dissolve", {'INPUT': delaunay_layer, 'OUTPUT': 'memory:'}, feedback=feedback, context=context)['OUTPUT'] - dissolved_layer = context.takeResultLayer(dissolved) + dissolved_layer = processing.run("native:dissolve", {'INPUT': delaunay_layer, 'OUTPUT': 'memory:'}, feedback=feedback, context=context)['OUTPUT'] # Save result feedback.setProgressText(self.tr('Saving data...')) diff --git a/python/plugins/processing/core/Processing.py b/python/plugins/processing/core/Processing.py index 155f975ccb0..a38dadf2d2a 100755 --- a/python/plugins/processing/core/Processing.py +++ b/python/plugins/processing/core/Processing.py @@ -38,9 +38,12 @@ from qgis.PyQt.QtGui import QCursor from qgis.utils import iface from qgis.core import (QgsMessageLog, QgsApplication, + QgsMapLayer, QgsProcessingProvider, QgsProcessingAlgorithm, - QgsProcessingParameterDefinition) + QgsProcessingParameterDefinition, + QgsProcessingOutputVectorLayer, + QgsProcessingOutputRasterLayer) import processing from processing.script.ScriptUtils import ScriptUtils @@ -173,6 +176,15 @@ class Processing(object): if onFinish is not None: onFinish(alg, context, feedback) + else: + # auto convert layer references in results to map layers + for out in alg.outputDefinitions(): + if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer)): + result = results[out.name()] + if not isinstance(result, QgsMapLayer): + layer = context.takeResultLayer(result) # transfer layer ownership out of context + if layer: + results[out.name()] = layer # replace layer string ref with actual layer (+ownership) else: msg = Processing.tr("There were errors executing the algorithm.") feedback.reportError(msg)