diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py index d20847ef7b9..18c5b105aa8 100755 --- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py +++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py @@ -63,6 +63,9 @@ from .PostGISExecuteSQL import PostGISExecuteSQL from .RandomExtract import RandomExtract from .RandomExtractWithinSubsets import RandomExtractWithinSubsets from .RegularPoints import RegularPoints +from .SaveSelectedFeatures import SaveSelectedFeatures +from .SelectByAttribute import SelectByAttribute +from .SelectByExpression import SelectByExpression from .SimplifyGeometries import SimplifyGeometries from .Smooth import Smooth from .SpatialiteExecuteSQL import SpatialiteExecuteSQL @@ -98,7 +101,6 @@ from .VectorSplit import VectorSplit # from .SpatialJoin import SpatialJoin # from .DeleteDuplicateGeometries import DeleteDuplicateGeometries # from .TextToFloat import TextToFloat -# from .SelectByAttribute import SelectByAttribute # from .GridLine import GridLine # from .Gridify import Gridify # from .HubDistancePoints import HubDistancePoints @@ -110,7 +112,6 @@ from .VectorSplit import VectorSplit # from .StatisticsByCategories import StatisticsByCategories # from .EquivalentNumField import EquivalentNumField # from .FieldsCalculator import FieldsCalculator -# from .SaveSelectedFeatures import SaveSelectedFeatures # from .Explode import Explode # from .FieldPyculator import FieldsPyculator # from .JoinAttributes import JoinAttributes @@ -128,7 +129,6 @@ from .VectorSplit import VectorSplit # from .PointsToPaths import PointsToPaths # from .SetVectorStyle import SetVectorStyle # from .SetRasterStyle import SetRasterStyle -# from .SelectByExpression import SelectByExpression # from .SelectByAttributeSum import SelectByAttributeSum # from .HypsometricCurves import HypsometricCurves # from .SplitWithLines import SplitWithLines @@ -202,11 +202,10 @@ class QGISAlgorithmProvider(QgsProcessingProvider): # ExtractByLocation(), # SpatialJoin(), # DeleteDuplicateGeometries(), TextToFloat(), - # SelectByAttribute(), # GridLine(), Gridify(), HubDistancePoints(), # HubDistanceLines(), HubLines(), # GeometryConvert(), FieldsCalculator(), - # SaveSelectedFeatures(), JoinAttributes(), + # JoinAttributes(), # Explode(), FieldsPyculator(), # EquivalentNumField(), PointsLayerFromTable(), # StatisticsByCategories(), ConcaveHull(), @@ -217,7 +216,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider): # RandomPointsPolygonsVariable(), # RandomPointsAlongLines(), PointsToPaths(), # SetVectorStyle(), SetRasterStyle(), - # SelectByExpression(), HypsometricCurves(), + # HypsometricCurves(), # SplitWithLines(), CreateConstantRaster(), # FieldsMapper(), SelectByAttributeSum(), Datasources2Vrt(), # OrientedMinimumBoundingBox(), @@ -265,6 +264,9 @@ class QGISAlgorithmProvider(QgsProcessingProvider): RandomExtract(), RandomExtractWithinSubsets(), RegularPoints(), + SaveSelectedFeatures(), + SelectByAttribute(), + SelectByExpression(), SimplifyGeometries(), Smooth(), SpatialiteExecuteSQL(), diff --git a/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py b/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py index 3d8e8184276..3abc6a0d05c 100644 --- a/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py +++ b/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py @@ -25,30 +25,29 @@ __copyright__ = '(C) 2012, Victor Olaya' __revision__ = '$Format:%H$' -from qgis.core import (QgsApplication, - QgsFeatureSink, - QgsProcessingUtils) +from qgis.core import (QgsFeatureSink, + QgsProcessingUtils, + QgsProcessingParameterVectorLayer, + QgsProcessingParameterFeatureSink, + QgsProcessingOutputVectorLayer) from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException -from processing.core.parameters import ParameterVector -from processing.core.outputs import OutputVector class SaveSelectedFeatures(QgisAlgorithm): - OUTPUT_LAYER = 'OUTPUT_LAYER' - INPUT_LAYER = 'INPUT_LAYER' + OUTPUT = 'OUTPUT' + INPUT = 'INPUT' def group(self): return self.tr('Vector general tools') def __init__(self): super().__init__() - self.addParameter(ParameterVector(self.INPUT_LAYER, - self.tr('Input layer'))) - self.addOutput(OutputVector(self.OUTPUT_LAYER, - self.tr('Selection'))) + self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT, self.tr('Input layer'))) + self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Selection'))) + self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Selection"))) def name(self): return 'saveselectedfeatures' @@ -57,20 +56,20 @@ class SaveSelectedFeatures(QgisAlgorithm): return self.tr('Save selected features') def processAlgorithm(self, parameters, context, feedback): - inputFilename = self.getParameterValue(self.INPUT_LAYER) - output = self.getOutputFromName(self.OUTPUT_LAYER) + vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context) - vectorLayer = QgsProcessingUtils.mapLayerFromString(inputFilename, context) - - writer = output.getVectorWriter(vectorLayer.fields(), vectorLayer.wkbType(), vectorLayer.crs(), context) + (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, + vectorLayer.fields(), vectorLayer.wkbType(), vectorLayer.sourceCrs()) features = vectorLayer.getSelectedFeatures() count = int(vectorLayer.selectedFeatureCount()) - if count == 0: - raise GeoAlgorithmExecutionException(self.tr('There are no selected features in the input layer.')) total = 100.0 / count if count else 1 for current, feat in enumerate(features): - writer.addFeature(feat, QgsFeatureSink.FastInsert) + if feedback.isCanceled(): + break + + sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) - del writer + + return {self.OUTPUT: dest_id} diff --git a/python/plugins/processing/algs/qgis/SelectByAttribute.py b/python/plugins/processing/algs/qgis/SelectByAttribute.py index 94b53a72709..3af9eb908c3 100644 --- a/python/plugins/processing/algs/qgis/SelectByAttribute.py +++ b/python/plugins/processing/algs/qgis/SelectByAttribute.py @@ -28,14 +28,14 @@ __revision__ = '$Format:%H$' from qgis.core import (QgsApplication) from qgis.PyQt.QtCore import QVariant from qgis.core import (QgsExpression, - QgsProcessingUtils) + QgsProcessingUtils, + QgsProcessingParameterVectorLayer, + QgsProcessingParameterField, + QgsProcessingParameterEnum, + QgsProcessingParameterString, + QgsProcessingOutputVectorLayer) from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException -from processing.core.parameters import ParameterVector -from processing.core.parameters import ParameterTableField -from processing.core.parameters import ParameterSelection -from processing.core.parameters import ParameterString -from processing.core.outputs import OutputVector class SelectByAttribute(QgisAlgorithm): @@ -82,15 +82,15 @@ class SelectByAttribute(QgisAlgorithm): self.tr('does not contain') ] - self.addParameter(ParameterVector(self.INPUT, - self.tr('Input Layer'))) - self.addParameter(ParameterTableField(self.FIELD, - self.tr('Selection attribute'), self.INPUT)) - self.addParameter(ParameterSelection(self.OPERATOR, - self.tr('Operator'), self.i18n_operators)) - self.addParameter(ParameterString(self.VALUE, self.tr('Value'))) + self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT, self.tr('Input layer'))) - self.addOutput(OutputVector(self.OUTPUT, self.tr('Selected (attribute)'), True)) + self.addParameter(QgsProcessingParameterField(self.FIELD, + self.tr('Selection attribute'), parentLayerParameterName=self.INPUT)) + self.addParameter(QgsProcessingParameterEnum(self.OPERATOR, + self.tr('Operator'), self.i18n_operators)) + self.addParameter(QgsProcessingParameterString(self.VALUE, self.tr('Value'))) + + self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (attribute)'))) def name(self): return 'selectbyattribute' @@ -99,11 +99,11 @@ class SelectByAttribute(QgisAlgorithm): return self.tr('Select by attribute') def processAlgorithm(self, parameters, context, feedback): - fileName = self.getParameterValue(self.INPUT) - layer = QgsProcessingUtils.mapLayerFromString(fileName, context) - fieldName = self.getParameterValue(self.FIELD) - operator = self.OPERATORS[self.getParameterValue(self.OPERATOR)] - value = self.getParameterValue(self.VALUE) + layer = self.parameterAsVectorLayer(parameters, self.INPUT, context) + + fieldName = self.parameterAsString(parameters, self.FIELD, context) + operator = self.OPERATORS[self.parameterAsEnum(parameters, self.OPERATOR, context)] + value = self.parameterAsString(parameters, self.VALUE, context) fields = layer.fields() @@ -135,4 +135,4 @@ class SelectByAttribute(QgisAlgorithm): raise GeoAlgorithmExecutionException(expression.parserErrorString()) layer.selectByExpression(expression_string) - self.setOutputValue(self.OUTPUT, fileName) + return {self.OUTPUT: parameters[self.INPUT]} diff --git a/python/plugins/processing/algs/qgis/SelectByExpression.py b/python/plugins/processing/algs/qgis/SelectByExpression.py index 421753eb80e..ac1f833ab2a 100644 --- a/python/plugins/processing/algs/qgis/SelectByExpression.py +++ b/python/plugins/processing/algs/qgis/SelectByExpression.py @@ -24,23 +24,21 @@ __copyright__ = '(C) 2014, Michael Douchin' __revision__ = '$Format:%H$' -from qgis.core import (QgsApplication, - QgsExpression, +from qgis.core import (QgsExpression, QgsVectorLayer, - QgsProcessingUtils) + QgsProcessingParameterVectorLayer, + QgsProcessingParameterExpression, + QgsProcessingParameterEnum, + QgsProcessingOutputVectorLayer) from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException -from processing.core.parameters import ParameterVector -from processing.core.parameters import ParameterSelection -from processing.core.outputs import OutputVector from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm -from processing.core.parameters import ParameterExpression class SelectByExpression(QgisAlgorithm): - LAYERNAME = 'LAYERNAME' + INPUT = 'INPUT' EXPRESSION = 'EXPRESSION' - RESULT = 'RESULT' + OUTPUT = 'OUTPUT' METHOD = 'METHOD' def group(self): @@ -53,13 +51,14 @@ class SelectByExpression(QgisAlgorithm): self.tr('removing from current selection'), self.tr('selecting within current selection')] - self.addParameter(ParameterVector(self.LAYERNAME, - self.tr('Input Layer'))) - self.addParameter(ParameterExpression(self.EXPRESSION, - self.tr("Expression"), parent_layer=self.LAYERNAME)) - self.addParameter(ParameterSelection(self.METHOD, - self.tr('Modify current selection by'), self.methods, 0)) - self.addOutput(OutputVector(self.RESULT, self.tr('Selected (expression)'), True)) + self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT, self.tr('Input layer'))) + + self.addParameter(QgsProcessingParameterExpression(self.EXPRESSION, + self.tr('Expression'), parentLayerParameterName=self.INPUT)) + self.addParameter(QgsProcessingParameterEnum(self.METHOD, + self.tr('Modify current selection by'), self.methods, 0)) + + self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (attribute)'))) def name(self): return 'selectbyexpression' @@ -68,9 +67,9 @@ class SelectByExpression(QgisAlgorithm): return self.tr('Select by expression') def processAlgorithm(self, parameters, context, feedback): - filename = self.getParameterValue(self.LAYERNAME) - layer = QgsProcessingUtils.mapLayerFromString(filename, context) - method = self.getParameterValue(self.METHOD) + layer = self.parameterAsVectorLayer(parameters, self.INPUT, context) + + method = self.parameterAsEnum(parameters, self.METHOD, context) if method == 0: behavior = QgsVectorLayer.SetSelection @@ -81,10 +80,10 @@ class SelectByExpression(QgisAlgorithm): elif method == 3: behavior = QgsVectorLayer.IntersectSelection - expression = self.getParameterValue(self.EXPRESSION) + expression = self.parameterAsString(parameters, self.EXPRESSION, context) qExp = QgsExpression(expression) if qExp.hasParserError(): raise GeoAlgorithmExecutionException(qExp.parserErrorString()) layer.selectByExpression(expression, behavior) - self.setOutputValue(self.RESULT, filename) + return {self.OUTPUT: parameters[self.INPUT]} diff --git a/python/plugins/processing/core/Processing.py b/python/plugins/processing/core/Processing.py index 58c4481ddd6..155f975ccb0 100755 --- a/python/plugins/processing/core/Processing.py +++ b/python/plugins/processing/core/Processing.py @@ -39,7 +39,7 @@ from qgis.utils import iface from qgis.core import (QgsMessageLog, QgsApplication, QgsProcessingProvider, - QgsProcessingUtils, + QgsProcessingAlgorithm, QgsProcessingParameterDefinition) import processing @@ -51,12 +51,13 @@ from processing.gui.RenderingStyles import RenderingStyles from processing.gui.Postprocessing import handleAlgorithmResults from processing.gui.AlgorithmExecutor import execute from processing.tools import dataobjects +from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException from processing.algs.qgis.QGISAlgorithmProvider import QGISAlgorithmProvider # NOQA #from processing.algs.grass7.Grass7AlgorithmProvider import Grass7AlgorithmProvider # NOQA #from processing.algs.gdal.GdalAlgorithmProvider import GdalAlgorithmProvider # NOQA #from processing.algs.saga.SagaAlgorithmProvider import SagaAlgorithmProvider # NOQA -#from processing.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider # NOQA +from processing.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider # NOQA #from processing.preconfigured.PreconfiguredAlgorithmProvider import PreconfiguredAlgorithmProvider # NOQA # should be loaded last - ensures that all dependent algorithms are available when loading models @@ -122,128 +123,61 @@ class Processing(object): provider.refreshAlgorithms() @staticmethod - def runAlgorithm(algOrName, onFinish, *args, **kwargs): - if isinstance(algOrName, GeoAlgorithm): + def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None): + if isinstance(algOrName, QgsProcessingAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().algorithmById(algOrName) + + if feedback is None: + feedback = MessageBarProgress(alg.displayName() if alg else Processing.tr('Processing')) + if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') - QgsMessageLog.logMessage(Processing.tr('Error: Algorithm {0} not found\n').format(algOrName), - Processing.tr("Processing")) - return + msg = Processing.tr('Error: Algorithm {0} not found\n').format(algOrName) + feedback.reportError(msg) + raise GeoAlgorithmExecutionException(msg) - parameters = {} - if len(args) == 1 and isinstance(args[0], dict): - # Set params by name and try to run the alg even if not all parameter values are provided, - # by using the default values instead. - for (name, value) in list(args[0].items()): - param = alg.parameterDefinition(name) - if param: - parameters[param.name()] = value - continue - # fix_print_with_import - print('Error: Wrong parameter value %s for parameter %s.' % (value, name)) - QgsMessageLog.logMessage( - Processing.tr('Error: Wrong parameter value {0} for parameter {1}.').format(value, name), - Processing.tr("Processing")) - QgsMessageLog.logMessage(Processing.tr('Error in {0}. Wrong parameter value {1} for parameter {2}.').format( - alg.name(), value, name - ), Processing.tr("Processing"), - QgsMessageLog.CRITICAL - ) - return - # check for any manadatory parameters which were not specified - for param in alg.parameterDefinitions(): - if param.name() not in parameters: - if not param.flags() & QgsProcessingParameterDefinition.FlagOptional: - # fix_print_with_import - print('Error: Missing parameter value for parameter %s.' % param.name()) - QgsMessageLog.logMessage( - Processing.tr('Error: Missing parameter value for parameter {0}.').format(param.name()), - Processing.tr("Processing")) - return - else: - if len(args) != alg.countVisibleParameters(): - # fix_print_with_import - print('Error: Wrong number of parameters') - QgsMessageLog.logMessage(Processing.tr('Error: Wrong number of parameters'), - Processing.tr("Processing")) - processing.algorithmHelp(algOrName) - return - i = 0 - for param in alg.parameterDefinitions(): - if not param.flags() & QgsProcessingParameterDefinition.FlagHidden: - if not True: # TODO param.setValue(args[i]): - # fix_print_with_import - print('Error: Wrong parameter value: ' + str(args[i])) - QgsMessageLog.logMessage(Processing.tr('Error: Wrong parameter value: ') + str(args[i]), - Processing.tr("Processing")) - return - else: - parameters[param.name()] = args[i] - i = i + 1 + # check for any mandatory parameters which were not specified + for param in alg.parameterDefinitions(): + if param.name() not in parameters: + if not param.flags() & QgsProcessingParameterDefinition.FlagOptional: + # fix_print_with_import + msg = Processing.tr('Error: Missing parameter value for parameter {0}.').format(param.name()) + print('Error: Missing parameter value for parameter %s.' % param.name()) + feedback.reportError(msg) + raise GeoAlgorithmExecutionException(msg) - for output in alg.outputs: - if not output.flags() & QgsProcessingParameterDefinition.FlagHidden: - if not output.setValue(args[i]): - # fix_print_with_import - print('Error: Wrong output value: ' + str(args[i])) - QgsMessageLog.logMessage(Processing.tr('Error: Wrong output value: ') + str(args[i]), - Processing.tr("Processing")) - return - i = i + 1 - - feedback = None - if kwargs is not None and "feedback" in list(kwargs.keys()): - feedback = kwargs["feedback"] - elif iface is not None: - feedback = MessageBarProgress(alg.displayName()) - - context = None - if kwargs is not None and 'context' in list(kwargs.keys()): - context = kwargs["context"] - else: + if context is None: context = dataobjects.createContext(feedback) ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) - QgsMessageLog.logMessage(Processing.tr('Unable to execute algorithm\n{0}').format(msg), - Processing.tr("Processing")) - return + msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg) + feedback.reportError(msg) + raise GeoAlgorithmExecutionException(msg) if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') - QgsMessageLog.logMessage( - Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.'), - Processing.tr("Processing")) - - # Don't set the wait cursor twice, because then when you - # restore it, it will still be a wait cursor. - overrideCursor = False - if iface is not None: - cursor = QApplication.overrideCursor() - if cursor is None or cursor == 0: - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - overrideCursor = True - elif cursor.shape() != Qt.WaitCursor: - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - overrideCursor = True + feedback.pushInfo( + Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.')) ret, results = execute(alg, parameters, context, feedback) if ret: + feedback.pushInfo( + Processing.tr('Results: {}').format(results)) + if onFinish is not None: onFinish(alg, context, feedback) else: - QgsMessageLog.logMessage(Processing.tr("There were errors executing the algorithm."), - Processing.tr("Processing")) + msg = Processing.tr("There were errors executing the algorithm.") + feedback.reportError(msg) + raise GeoAlgorithmExecutionException(msg) - if overrideCursor: - QApplication.restoreOverrideCursor() if isinstance(feedback, MessageBarProgress): feedback.close() return results diff --git a/python/plugins/processing/gui/AlgorithmDialog.py b/python/plugins/processing/gui/AlgorithmDialog.py index bd2f2f1a97d..4220ea3b846 100644 --- a/python/plugins/processing/gui/AlgorithmDialog.py +++ b/python/plugins/processing/gui/AlgorithmDialog.py @@ -39,6 +39,8 @@ from qgis.core import (QgsProject, QgsProcessingParameterDefinition, QgsProcessingOutputRasterLayer, QgsProcessingOutputVectorLayer, + QgsProcessingOutputHtml, + QgsProcessingParameterVectorOutput, QgsProcessingOutputLayerDefinition, QgsProcessingParameterFeatureSink, QgsProcessingParameterRasterOutput, @@ -48,7 +50,7 @@ from qgis.utils import iface from processing.core.ProcessingLog import ProcessingLog from processing.core.ProcessingConfig import ProcessingConfig - +from processing.core.ProcessingResults import resultsList from processing.gui.ParametersPanel import ParametersPanel from processing.gui.BatchAlgorithmDialog import BatchAlgorithmDialog from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase @@ -82,7 +84,6 @@ class AlgorithmDialog(AlgorithmDialogBase): self.cornerWidget = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 5) - self.tabWidget.setStyleSheet("QTabBar::tab { height: 30px; }") self.runAsBatchButton = QPushButton(self.tr("Run as batch process...")) self.runAsBatchButton.clicked.connect(self.runAsBatch) layout.addWidget(self.runAsBatchButton) @@ -116,7 +117,7 @@ class AlgorithmDialog(AlgorithmDialogBase): else: dest_project = None if not param.flags() & QgsProcessingParameterDefinition.FlagHidden and \ - isinstance(param, (QgsProcessingParameterRasterOutput, QgsProcessingParameterFeatureSink, OutputTable)): + isinstance(param, (QgsProcessingParameterRasterOutput, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorOutput)): if self.mainWidget.checkBoxes[param.name()].isChecked(): dest_project = QgsProject.instance() @@ -273,6 +274,12 @@ class AlgorithmDialog(AlgorithmDialogBase): if self.iterateParam is None: + # add html results to results dock + for out in self.alg.outputDefinitions(): + if isinstance(out, QgsProcessingOutputHtml) and out.name() in result and result[out.name()]: + resultsList.addResult(icon=self.alg.icon(), name=out.description(), + result=result[out.name()]) + if not handleAlgorithmResults(self.alg, context, feedback, not keepOpen): self.resetGUI() return diff --git a/python/plugins/processing/gui/DestinationSelectionPanel.py b/python/plugins/processing/gui/DestinationSelectionPanel.py index 13e9827b1da..7dfa558f0fb 100644 --- a/python/plugins/processing/gui/DestinationSelectionPanel.py +++ b/python/plugins/processing/gui/DestinationSelectionPanel.py @@ -267,6 +267,8 @@ class DestinationSelectionPanel(BASE, WIDGET): key = None if self.use_temporary and isinstance(self.parameter, QgsProcessingParameterFeatureSink): key = 'memory:' + elif self.use_temporary: + key = self.parameter.generateTemporaryDestination() else: key = self.leText.text() diff --git a/python/plugins/processing/gui/wrappers.py b/python/plugins/processing/gui/wrappers.py index 0d8bf4ab5e2..d3194f6161a 100644 --- a/python/plugins/processing/gui/wrappers.py +++ b/python/plugins/processing/gui/wrappers.py @@ -1077,16 +1077,12 @@ class TableWidgetWrapper(WidgetWrapper): return BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog) else: self.combo = QComboBox() - layers = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer, QgsProcessingOutputRasterLayer) self.combo.setEditable(True) - tables = self.dialog.getAvailableValuesOfType(QgsProcessingParameterVectorLayer, OutputTable) - layers = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer) + tables = self.dialog.getAvailableValuesOfType(QgsProcessingParameterVectorLayer, QgsProcessingOutputVectorLayer) if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional: self.combo.addItem(self.NOT_SELECTED, None) for table in tables: self.combo.addItem(self.dialog.resolveValueDescription(table), table) - for layer in layers: - self.combo.addItem(self.dialog.resolveValueDescription(layer), layer) widget = QWidget() layout = QHBoxLayout() diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml index 657b24db719..d77503b5003 100644 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml @@ -2543,29 +2543,29 @@ tests: # MIN_DISTANCE: 0.0 # POINT_NUMBER: 5 # results: {} -# -# - algorithm: script:selectbyattribute -# name: Select by attribute -# params: -# INPUT_LAYER: -# name: points.gml -# type: vector -# results: -# OUTPUT_LAYER: -# name: expected/selected_points.gml -# type: vector -# -# - algorithm: script:selectbyexpression -# name: Select by expression -# params: -# INPUT_LAYER: -# name: points.gml -# type: vector -# results: -# OUTPUT_LAYER: -# name: expected/select_by_expression.gml -# type: vector -# + + - algorithm: script:selectbyattribute + name: Select by attribute + params: + INPUT_LAYER: + name: points.gml + type: vector + results: + OUTPUT_LAYER: + name: expected/selected_points.gml + type: vector + + - algorithm: script:selectbyexpression + name: Select by expression + params: + INPUT_LAYER: + name: points.gml + type: vector + results: + OUTPUT_LAYER: + name: expected/select_by_expression.gml + type: vector + - algorithm: qgis:randomextract name: Random extract by number params: diff --git a/python/plugins/processing/tests/testdata/script_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/script_algorithm_tests.yaml index 6ff51fe7fc5..1d417a17dc5 100644 --- a/python/plugins/processing/tests/testdata/script_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/script_algorithm_tests.yaml @@ -2,16 +2,16 @@ tests: -# - algorithm: script:centroids -# name: Centroids script test -# params: -# INPUT_LAYER: -# name: polys.gml -# type: vector -# results: -# OUTPUT_LAYER: -# name: expected/centroid_polys.gml -# type: vector -# compare: -# geometry: -# precision: 7 + - algorithm: script:centroids + name: Centroids script test + params: + INPUT_LAYER: + name: polys.gml + type: vector + results: + OUTPUT_LAYER: + name: expected/centroid_polys.gml + type: vector + compare: + geometry: + precision: 7 diff --git a/python/plugins/processing/tests/testdata/scripts/centroids.py b/python/plugins/processing/tests/testdata/scripts/centroids.py index 70b76dedb45..a8dc13be9e7 100644 --- a/python/plugins/processing/tests/testdata/scripts/centroids.py +++ b/python/plugins/processing/tests/testdata/scripts/centroids.py @@ -1,17 +1,24 @@ ##Centroids=name ##Geometry=group -##INPUT_LAYER=vector -##OUTPUT_LAYER=output vector + +#inputs + +##INPUT_LAYER=source +##OUTPUT_LAYER=sink point + +#outputs + +##OUTPUT_LAYER=output outputVector from qgis.core import QgsWkbTypes, QgsProcessingUtils -layer = QgsProcessingUtils.mapLayerFromString(INPUT_LAYER, context) -fields = layer.fields() +fields = INPUT_LAYER.fields() -writer, writer_dest = QgsProcessingUtils.createFeatureSink(OUTPUT_LAYER, context, fields, QgsWkbTypes.Point, layer.crs(), {'fileEncoding': 'utf-8'}) +(sink, OUTPUT_LAYER) = self.parameterAsSink(parameters, 'OUTPUT_LAYER', context, + fields, QgsWkbTypes.Point, INPUT_LAYER.sourceCrs()) -features = QgsProcessingUtils.getFeatures(layer, context) -count = QgsProcessingUtils.featureCount(layer, context) +features = INPUT_LAYER.getFeatures() +count = INPUT_LAYER.featureCount() if count == 0: raise GeoAlgorithmExecutionException('Input layer contains no features.') @@ -23,5 +30,5 @@ for count, f in enumerate(features): outputGeometry = f.geometry().centroid() outputFeature.setGeometry(outputGeometry) - writer.addFeature(outputFeature) + sink.addFeature(outputFeature) feedback.setProgress(int(count * total)) diff --git a/python/plugins/processing/tests/testdata/scripts/selectbyattribute.py b/python/plugins/processing/tests/testdata/scripts/selectbyattribute.py index be8c70d1213..28f0250a07c 100644 --- a/python/plugins/processing/tests/testdata/scripts/selectbyattribute.py +++ b/python/plugins/processing/tests/testdata/scripts/selectbyattribute.py @@ -1,16 +1,23 @@ ##Select by attribute=name ##Tests=group + +#inputs + ##INPUT_LAYER=vector -##OUTPUT_LAYER=output vector +##OUTPUT_LAYER=vectorOut + +#outputs + +##OUTPUT_LAYER=output outputVector import processing result = processing.run("qgis:selectbyattribute", - INPUT_LAYER, - "id2", - 0, - "2") - -processing.run("qgis:saveselectedfeatures", - result["OUTPUT"], - OUTPUT_LAYER) + {'INPUT': INPUT_LAYER, + 'FIELD': "id2", + 'OPERATOR': 0, + 'VALUE': "2"}, context=context, feedback=feedback) +result = processing.run("qgis:saveselectedfeatures", + {'INPUT': result["OUTPUT"], + 'OUTPUT': parameters['OUTPUT_LAYER']}, context=context, feedback=feedback) +OUTPUT_LAYER = result['OUTPUT'] diff --git a/python/plugins/processing/tests/testdata/scripts/selectbyexpression.py b/python/plugins/processing/tests/testdata/scripts/selectbyexpression.py index c45b5d1768d..25e693b9242 100644 --- a/python/plugins/processing/tests/testdata/scripts/selectbyexpression.py +++ b/python/plugins/processing/tests/testdata/scripts/selectbyexpression.py @@ -1,15 +1,25 @@ ##Select by expression=name ##Tests=group + +#inputs + ##INPUT_LAYER=vector -##OUTPUT_LAYER=output vector +##OUTPUT_LAYER=vectorOut + +#outputs + +##OUTPUT_LAYER=output outputVector + import processing result = processing.run("qgis:selectbyexpression", - INPUT_LAYER, - '"id2" = 0 and "id" > 7', - "1") + {'INPUT': INPUT_LAYER, + 'EXPRESSION': '"id2" = 0 and "id" > 7', + 'METHOD': 1}, context=context, feedback=feedback) -processing.run("qgis:saveselectedfeatures", - result["RESULT"], - OUTPUT_LAYER) +result = processing.run("qgis:saveselectedfeatures", + {'INPUT': result["OUTPUT"], + 'OUTPUT': parameters['OUTPUT_LAYER']}, + context=context, feedback=feedback) +OUTPUT_LAYER = result['OUTPUT'] diff --git a/python/plugins/processing/tools/general.py b/python/plugins/processing/tools/general.py index 323b515e59c..aa18f23ac56 100644 --- a/python/plugins/processing/tools/general.py +++ b/python/plugins/processing/tools/general.py @@ -69,11 +69,11 @@ def algorithmHelp(id): print('Algorithm "{}" not found.'.format(id)) -def run(algOrName, *args, **kwargs): +def run(algOrName, parameters, onFinish=None, feedback=None, context=None): """Executes given algorithm and returns its outputs as dictionary object. """ - return Processing.runAlgorithm(algOrName, None, *args, **kwargs) + return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context) def runAndLoadResults(name, *args, **kwargs): diff --git a/src/core/processing/qgsprocessingutils.cpp b/src/core/processing/qgsprocessingutils.cpp index c3d9c1ce8e6..ded185b973d 100644 --- a/src/core/processing/qgsprocessingutils.cpp +++ b/src/core/processing/qgsprocessingutils.cpp @@ -408,7 +408,7 @@ QString QgsProcessingUtils::tempFolder() sMutex.lock(); if ( sFolder.isEmpty() ) { - QString subPath = QUuid::createUuid().toString(); + QString subPath = QUuid::createUuid().toString().remove( '-' ).remove( '{' ).remove( '}' ); sFolder = QDir::tempPath() + QStringLiteral( "/processing_" ) + subPath; if ( !QDir( sFolder ).exists() ) QDir().mkpath( sFolder ); @@ -419,12 +419,12 @@ QString QgsProcessingUtils::tempFolder() QString QgsProcessingUtils::generateTempFilename( const QString &basename ) { - QString subPath = QUuid::createUuid().toString(); + QString subPath = QUuid::createUuid().toString().remove( '-' ).remove( '{' ).remove( '}' ); QString path = tempFolder() + '/' + subPath; if ( !QDir( path ).exists() ) //make sure the directory exists - it shouldn't, but lets be safe... { - QDir tmpDir( QDir::tempPath() ); - tmpDir.mkdir( subPath ); + QDir tmpDir; + tmpDir.mkdir( path ); } return path + '/' + basename; }