Esempio n. 1
0
def runAndLoadResults(algOrName, parameters, feedback=None, context=None):
    """
    Executes given algorithm and load its results into the current QGIS project
    when possible.

    :param algOrName: Either an instance of an algorithm, or an algorithm's ID
    :param parameters: Algorithm parameters dictionary
    :param feedback: Processing feedback object
    :param context: Processing context object

    :returns algorithm results as a dictionary, or None if execution failed
    :rtype: Union[dict, None]
    """
    if isinstance(algOrName, QgsProcessingAlgorithm):
        alg = algOrName
    else:
        alg = QgsApplication.processingRegistry().createAlgorithmById(algOrName)

    # output destination parameters to point to current project
    for param in alg.parameterDefinitions():
        if not param.name() in parameters:
            continue

        if isinstance(param, (QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination,
                              QgsProcessingParameterRasterDestination)):
            p = parameters[param.name()]
            if not isinstance(p, QgsProcessingOutputLayerDefinition):
                parameters[param.name()] = QgsProcessingOutputLayerDefinition(p, QgsProject.instance())
            else:
                p.destinationProject = QgsProject.instance()
                parameters[param.name()] = p

    return Processing.runAlgorithm(alg, parameters=parameters, onFinish=handleAlgorithmResults, feedback=feedback,
                                   context=context)
Esempio n. 2
0
def runAndLoadResults(algOrName, parameters, feedback=None, context=None):
    """Executes given algorithm and load its results into QGIS project
    when possible.
    """
    if isinstance(algOrName, QgsProcessingAlgorithm):
        alg = algOrName
    else:
        alg = QgsApplication.processingRegistry().createAlgorithmById(
            algOrName)

    # output destination parameters to point to current project
    for param in alg.parameterDefinitions():
        if not param.name() in parameters:
            continue

        if isinstance(param, (QgsProcessingParameterFeatureSink,
                              QgsProcessingParameterVectorDestination,
                              QgsProcessingParameterRasterDestination)):
            p = parameters[param.name()]
            if not isinstance(p, QgsProcessingOutputLayerDefinition):
                parameters[param.name()] = QgsProcessingOutputLayerDefinition(
                    p, QgsProject.instance())
            else:
                p.destinationProject = QgsProject.instance()
                parameters[param.name()] = p

    return Processing.runAlgorithm(alg,
                                   parameters=parameters,
                                   onFinish=handleAlgorithmResults,
                                   feedback=feedback,
                                   context=context)
Esempio n. 3
0
    def getParamValues(self):
        if self.mUpdateExistingGroupBox.isChecked():
            fieldName = self.mExistingFieldComboBox.currentText()
        else:
            fieldName = self.mOutputFieldNameLineEdit.text()

        layer = self.cmbInputLayer.currentLayer()

        context = dataobjects.createContext()

        parameters = {}
        parameters['INPUT'] = layer
        parameters['FIELD_NAME'] = fieldName
        parameters['FIELD_TYPE'] = self.mOutputFieldTypeComboBox.currentIndex()
        parameters['FIELD_LENGTH'] = self.mOutputFieldWidthSpinBox.value()
        parameters[
            'FIELD_PRECISION'] = self.mOutputFieldPrecisionSpinBox.value()
        parameters['NEW_FIELD'] = self.mNewFieldGroupBox.isChecked()
        parameters['FORMULA'] = self.builder.expressionText()
        output = QgsProcessingOutputLayerDefinition()
        if self.leOutputFile.text().strip():
            output.sink = QgsProperty.fromValue(
                self.leOutputFile.text().strip())
        else:
            output.sink = QgsProperty.fromValue('memory:')
        output.destinationProject = context.project()
        parameters['OUTPUT'] = output

        ok, msg = self.alg.checkParameterValues(parameters, context)
        if not ok:
            QMessageBox.warning(self, self.tr('Unable to execute algorithm'),
                                msg)
            return {}
        return parameters
Esempio n. 4
0
    def getValue(self):
        key = None
        if self.use_temporary and isinstance(
                self.parameter, QgsProcessingParameterFeatureSink):
            key = 'memory:'
        elif self.use_temporary and not self.default_selection:
            key = self.parameter.generateTemporaryDestination()
        else:
            key = self.leText.text()

        if not key and self.parameter.flags(
        ) & QgsProcessingParameterDefinition.FlagOptional:
            return None

        if key and not key.startswith('memory:') \
                and not key.startswith('ogr:') \
                and not key.startswith('postgres:') \
                and not key.startswith('postgis:'):
            # output should be a file path
            folder = QFileInfo(key).path()
            if folder == '.':
                # output name does not include a folder - use default
                default_folder = ProcessingConfig.getSetting(
                    ProcessingConfig.OUTPUT_FOLDER)
                key = QDir(default_folder).filePath(key)

        if isinstance(self.parameter, QgsProcessingParameterFolderDestination):
            return key

        if isinstance(self.parameter, QgsProcessingParameterFileDestination):
            return key

        value = QgsProcessingOutputLayerDefinition(key)
        value.createOptions = {'fileEncoding': self.encoding}
        return value
Esempio n. 5
0
    def getConsoleCommands(self, parameters, context, feedback):
        arguments = []
        arguments.append('-resolution')
        arguments.append(self.RESOLUTION_OPTIONS[self.parameterAsEnum(parameters, self.RESOLUTION, context)])
        if self.parameterAsBool(parameters, buildvrt.SEPARATE, context):
            arguments.append('-separate')
        if self.parameterAsBool(parameters, buildvrt.PROJ_DIFFERENCE, context):
            arguments.append('-allow_projection_difference')
        # Always write input files to a text file in case there are many of them and the
        # length of the command will be longer then allowed in command prompt
        listFile = os.path.join(QgsProcessingUtils.tempFolder(), 'buildvrtInputFiles.txt')
        with open(listFile, 'w') as f:
            layers = []
            for l in self.parameterAsLayerList(parameters, self.INPUT, context):
                layers.append(l.source())
            f.write('\n'.join(layers))
        arguments.append('-input_file_list')
        arguments.append(listFile)

        out = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
        # Ideally the file extensions should be limited to just .vrt but I'm not sure how
        # to do it simply so instead a check is performed.
        _, ext = os.path.splitext(out)
        if not ext.lower() == '.vrt':
            out = out[:-len(ext)] + '.vrt'
            if isinstance(parameters[self.OUTPUT], QgsProcessingOutputLayerDefinition):
                output_def = QgsProcessingOutputLayerDefinition(parameters[self.OUTPUT])
                output_def.sink = QgsProperty.fromValue(out)
                self.setOutputValue(self.OUTPUT, output_def)
            else:
                self.setOutputValue(self.OUTPUT, out)
        arguments.append(out)

        return ['gdalbuildvrt', GdalUtils.escapeAndJoin(arguments)]
Esempio n. 6
0
 def getValue(self):
     key = None
     if not self.leText.text():
         if isinstance(self.parameter, QgsProcessingParameterFeatureSink):
             key = 'memory:'
     else:
         key = self.leText.text()
     value = QgsProcessingOutputLayerDefinition(key)
     value.createOptions = {'fileEncoding': self.encoding}
     return value
Esempio n. 7
0
    def parametersForRow(self,
                         row,
                         destinationProject=None,
                         warnOnInvalid=True):
        """
        Returns the parameters dictionary corresponding to a row in the batch table
        """
        col = 0
        parameters = {}
        for param in self.alg.parameterDefinitions():
            if param.flags(
            ) & QgsProcessingParameterDefinition.FlagHidden or param.isDestination(
            ):
                continue
            wrapper = self.wrappers[row][col]
            parameters[param.name()] = wrapper.parameterValue()
            if warnOnInvalid and not param.checkValueIsAcceptable(
                    wrapper.parameterValue()):
                self.parent.messageBar().pushMessage(
                    "",
                    self.tr('Wrong or missing parameter value: {0} (row {1})'
                            ).format(param.description(), row + 1),
                    level=Qgis.Warning,
                    duration=5)
                return {}
            col += 1
        count_visible_outputs = 0
        for out in self.alg.destinationParameterDefinitions():
            if out.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            count_visible_outputs += 1
            widget = self.tblParameters.cellWidget(row + 1, col)
            text = widget.getValue()
            if not warnOnInvalid or out.checkValueIsAcceptable(text):
                if isinstance(out, (QgsProcessingParameterRasterDestination,
                                    QgsProcessingParameterVectorDestination,
                                    QgsProcessingParameterFeatureSink)):
                    # load rasters and sinks on completion
                    parameters[
                        out.name()] = QgsProcessingOutputLayerDefinition(
                            text, destinationProject)
                else:
                    parameters[out.name()] = text
                col += 1
            else:
                self.parent.messageBar().pushMessage(
                    "",
                    self.tr(
                        'Wrong or missing output value: {0} (row {1})').format(
                            out.description(), row + 1),
                    level=Qgis.Warning,
                    duration=5)
                return {}
        return parameters
Esempio n. 8
0
def get_processing_value(param: QgsProcessingParameterDefinition,
                         inp: WPSInput, context: ProcessingContext) -> Any:
    """ Return processing values from WPS input data
    """
    if isinstance(param, DESTINATION_LAYER_TYPES):
        #
        # Destination layer: a new layer is created as file with the input name.
        # Do not supports memory layer because we need persistence
        #
        param.setSupportsNonFileBasedOutput(False)
        #
        # Enforce pushing created layers to layersToLoadOnCompletion list
        # i.e layer will be stored in the destination project

        # get extension from input metadata (should always exist for destination)
        extension = get_metadata(inp[0], 'processing:extension')[0]

        destination = inp[0].data

        if confservice.getboolean('processing',
                                  'unsafe.raw_destination_input_sink'):
            sink, destination = parse_root_destination_path(
                param, destination, extension)
        else:
            # Use canonical file name
            sink = "./%s.%s" % (get_valid_filename(param.name()), extension)

        value = QgsProcessingOutputLayerDefinition(sink,
                                                   context.destination_project)
        value.destinationName = destination

        LOGGER.debug("Handling destination layer: %s, details name: %s",
                     param.name(), value.destinationName)

    elif isinstance(param, QgsProcessingParameterFeatureSource):
        #
        # Support feature selection
        #
        value, has_selection = parse_layer_spec(inp[0].data,
                                                context,
                                                allow_selection=True)
        value = QgsProcessingFeatureSourceDefinition(
            value, selectedFeaturesOnly=has_selection)

    elif isinstance(param, INPUT_LAYER_TYPES):
        if len(inp) > 1:
            value = [parse_layer_spec(i.data, context)[0] for i in inp]
        else:
            value, _ = parse_layer_spec(inp[0].data, context)
    else:
        value = None

    return value
Esempio n. 9
0
def test_layer_destination():

    param = QgsProcessingParameterVectorDestination(
        "LAYER",
        "",
        defaultValue=QgsProcessingOutputLayerDefinition('foo.shp'))
    inp = parse_input_definition(param)
    assert inp.default == "foo"

    metadata = layersio.get_metadata(inp, 'processing:extension')
    assert len(metadata) == 1
    assert metadata[0] == 'shp'

    inp.data = "bar"

    context = QgsProcessingContext()
    context.destination_project = None

    inp.data = "bar"
    value = layersio.get_processing_value(param, [inp], context)
    assert isinstance(value, QgsProcessingOutputLayerDefinition)
    assert value.destinationName == 'bar'
    assert value.sink.staticValue() == './LAYER.shp'

    # Check unsafe option
    with chconfig('processing', 'unsafe.raw_destination_input_sink', 'yes'):
        inp.data = "/foobar.csv"
        value = layersio.get_processing_value(param, [inp], context)
        assert value.destinationName == 'foobar'
        assert value.sink.staticValue() == 'foobar.csv'

    # Check unsafe option with default extension
    with chconfig('processing', 'unsafe.raw_destination_input_sink', 'yes'):
        inp.data = "/foobar"
        value = layersio.get_processing_value(param, [inp], context)
        assert value.destinationName == 'foobar'
        assert value.sink.staticValue() == 'foobar.shp'

    # Check unsafe option with layername
    with chconfig('processing','unsafe.raw_destination_input_sink','yes'),\
         chconfig('processing','destination_root_path','/unsafe'):
        inp.data = "file:/path/to/foobar.csv|layername=foobaz"
        value = layersio.get_processing_value(param, [inp], context)
        assert value.destinationName == 'foobaz'
        assert value.sink.staticValue() == '/unsafe/path/to/foobar.csv'

    # Check unsafe option with url
    with chconfig('processing', 'unsafe.raw_destination_input_sink', 'yes'):
        inp.data = "postgres://service=foobar|layername=foobaz"
        value = layersio.get_processing_value(param, [inp], context)
        assert value.destinationName == 'foobaz'
        assert value.sink.staticValue() == 'postgres://service=foobar'
 def initAlgorithm(self, config=None):
     """ Virtual override
 
        see https://qgis.org/api/classQgsProcessingAlgorithm.html
     """
     self.addParameter(
         QgsProcessingParameterVectorLayer(self.INPUT, 'Vector Layer'))
     self.addParameter(
         QgsProcessingParameterVectorDestination(
             self.OUTPUT,
             'Output Layer',
             defaultValue=QgsProcessingOutputLayerDefinition(
                 f'{self.OUTPUT}.shp')))
Esempio n. 11
0
    def test_output_layer_definition(self):
        """
        Test that QgsProcessingOutputLayerDefinition values are correctly loaded and written
        """
        doc = QDomDocument("properties")

        definition = QgsProcessingOutputLayerDefinition(QgsProperty.fromValue('my sink'))
        definition.createOptions = {'opt': 1, 'opt2': 2}

        elem = QgsXmlUtils.writeVariant(definition, doc)
        c = QgsXmlUtils.readVariant(elem)
        self.assertEqual(c.sink.staticValue(), 'my sink')
        self.assertEqual(c.createOptions, {'opt': 1, 'opt2': 2})
Esempio n. 12
0
    def getValue(self):
        key = None
        if self.use_temporary and isinstance(
                self.parameter, QgsProcessingParameterFeatureSink):
            key = 'memory:'
        else:
            key = self.leText.text()

        if not key and self.parameter.flags(
        ) & QgsProcessingParameterDefinition.FlagOptional:
            return None

        value = QgsProcessingOutputLayerDefinition(key)
        value.createOptions = {'fileEncoding': self.encoding}
        return value
Esempio n. 13
0
    def getValue(self):
        key = None
        if self.use_temporary and isinstance(self.parameter, QgsProcessingParameterFeatureSink):
            key = 'memory:'
        elif self.use_temporary and not self.default_selection:
            key = self.parameter.generateTemporaryDestination()
        else:
            key = self.leText.text()

        if not key and self.parameter.flags() & QgsProcessingParameterDefinition.FlagOptional:
            return None

        if isinstance(self.parameter, QgsProcessingParameterFolderDestination):
            return key

        if isinstance(self.parameter, QgsProcessingParameterFileDestination):
            return key

        value = QgsProcessingOutputLayerDefinition(key)
        value.createOptions = {'fileEncoding': self.encoding}
        return value
    def __init__(
        self,
        algorithm_id: str,
        artifact_parameter_name: str,
        output_name: str,
        negate_output: bool,
        artifact_path: typing.Union[str, Path],
        model: QtCore.QAbstractItemModel,
        validated_idx: QtCore.QModelIndex,
        notes_idx: QtCore.QModelIndex,
        execution_params: typing.Optional[typing.Dict] = None,
        context: typing.Optional[QgsProcessingContext] = None,
        feedback: typing.Optional[QgsProcessingFeedback] = None,
    ):
        self.context = context or QgsProcessingContext()
        self.feedback = feedback or QgsProcessingFeedback()
        registry = QgsApplication.processingRegistry()
        algorithm = registry.createAlgorithmById(algorithm_id)
        if algorithm is None:
            raise RuntimeError(f"Invalid algorithm_id: {algorithm_id!r}")
        self.algorithm = algorithm
        self.output_name = output_name
        self.negate_output = negate_output
        self.model = model
        self.validated_idx = validated_idx
        self.notes_idx = notes_idx
        self.params = dict(execution_params) if execution_params else {}
        if isinstance(artifact_path, Path):
            input_ = str(artifact_path)
        else:
            input_ = artifact_path
        self.params.update({artifact_parameter_name: input_})

        for param_def in self.algorithm.parameterDefinitions():
            if isinstance(param_def, self._OUTPUT_TYPES):
                out_layer_definition = QgsProcessingOutputLayerDefinition(
                    "memory:")
                out_layer_definition.createOptions = {"fileEncoding": "utf-8"}
                self.params[param_def.name()] = out_layer_definition
Esempio n. 15
0
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(4, model_feedback)
        results = {}
        outputs = {}

        sections = self.parameterAsSource(parameters, self.SECTIONS, context)

        # Retreive first section longitudinal abscissa
        request = (QgsFeatureRequest().setFlags(
            QgsFeatureRequest.NoGeometry
            | QgsFeatureRequest.SubsetOfAttributes).setSubsetOfAttributes(
                ["abs_long"],
                sections.fields()).addOrderBy('"sec_id"', True,
                                              True).setLimit(1))
        first_section = next(sections.getFeatures(request))
        first_abs_long = first_section.attribute("abs_long")

        # Lines to points
        alg_params = {
            "INPUT":
            parameters[self.SECTIONS],
            "OUTPUT":
            QgsProcessingUtils.generateTempFilename("lines_to_points.shp"),
        }
        outputs["LinesToPoints"] = processing.run(
            "precourlis:lines_to_points",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["LinesToPoints"]["OUTPUT"]

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # Interpolate points
        alg_params = {
            "SECTIONS":
            current,
            "AXIS":
            parameters[self.AXIS],
            "CONSTRAINT_LINES":
            parameters.get(self.CONSTRAINT_LINES),
            "LONG_STEP":
            parameters[self.LONG_STEP],
            "LAT_STEP":
            parameters[self.LAT_STEP],
            "ATTR_CROSS_SECTION":
            "sec_id",
            "OUTPUT":
            QgsProcessingUtils.generateTempFilename("interpolate_points.shp"),
        }
        outputs["InterpolatePoints"] = processing.run(
            "precourlis:interpolate_points",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["InterpolatePoints"]["OUTPUT"]

        feedback.setCurrentStep(2)
        if feedback.isCanceled():
            return {}

        # assignprojection
        alg_params = {
            "INPUT": current,
            "CRS": sections.sourceCrs(),
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["AssignProjection"] = processing.run(
            "native:assignprojection",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["AssignProjection"]["OUTPUT"]

        feedback.setCurrentStep(3)
        if feedback.isCanceled():
            return {}

        output = QgsProcessingOutputLayerDefinition(parameters[self.OUTPUT])
        output.destinationName = self.tr("Interpolated")

        # Points to lines
        alg_params = {
            "INPUT": current,
            "AXIS": parameters[self.AXIS],
            "FIRST_SECTION_ABS_LONG": first_abs_long,
            "GROUP_FIELD": "abs_long",
            "ORDER_FIELD": "p_id",
            "OUTPUT": output,
        }
        outputs["PointsToLines"] = processing.run(
            "precourlis:points_to_lines",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["PointsToLines"]["OUTPUT"]

        results["OUTPUT"] = current
        return results
Esempio n. 16
0
    def accept(self):
        alg_parameters = []
        load = []

        feedback = self.createFeedback()
        context = dataobjects.createContext(feedback)

        for row in range(self.mainWidget.tblParameters.rowCount()):
            col = 0
            parameters = {}
            for param in self.alg.parameterDefinitions():
                if param.flags() & QgsProcessingParameterDefinition.FlagHidden or param.isDestination():
                    continue
                wrapper = self.mainWidget.wrappers[row][col]
                parameters[param.name()] = wrapper.value()
                if not param.checkValueIsAcceptable(wrapper.value(), context):
                    self.bar.pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format(
                                         param.description(), row + 1),
                                         level=QgsMessageBar.WARNING, duration=5)
                    return
                col += 1
            count_visible_outputs = 0
            for out in self.alg.destinationParameterDefinitions():
                if out.flags() & QgsProcessingParameterDefinition.FlagHidden:
                    continue

                count_visible_outputs += 1
                widget = self.mainWidget.tblParameters.cellWidget(row, col)
                text = widget.getValue()
                if param.checkValueIsAcceptable(text, context):
                    if isinstance(out, (QgsProcessingParameterRasterDestination,
                                        QgsProcessingParameterFeatureSink)):
                        # load rasters and sinks on completion
                        parameters[out.name()] = QgsProcessingOutputLayerDefinition(text, context.project())
                    else:
                        parameters[out.name()] = text
                    col += 1
                else:
                    self.bar.pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format(
                                         out.description(), row + 1),
                                         level=QgsMessageBar.WARNING, duration=5)
                    return

            alg_parameters.append(parameters)

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.mainWidget.setEnabled(False)
        self.buttonCancel.setEnabled(True)

        # Make sure the Log tab is visible before executing the algorithm
        try:
            self.tabWidget.setCurrentIndex(1)
            self.repaint()
        except:
            pass

        start_time = time.time()

        algorithm_results = []
        for count, parameters in enumerate(alg_parameters):
            if feedback.isCanceled():
                break
            self.setText(self.tr('\nProcessing algorithm {0}/{1}...').format(count + 1, len(alg_parameters)))
            self.setInfo(self.tr('<b>Algorithm {0} starting...</b>').format(self.alg.displayName()), escape_html=False)

            feedback.pushInfo(self.tr('Input parameters:'))
            feedback.pushCommandInfo(pformat(parameters))
            feedback.pushInfo('')

            alg_start_time = time.time()
            ret, results = execute(self.alg, parameters, context, feedback)
            if ret:
                self.setInfo(self.tr('Algorithm {0} correctly executed...').format(self.alg.displayName()), escape_html=False)
                feedback.setProgress(100)
                feedback.pushInfo(
                    self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - alg_start_time)))
                feedback.pushInfo(self.tr('Results:'))
                feedback.pushCommandInfo(pformat(results))
                feedback.pushInfo('')
                algorithm_results.append(results)
            else:
                break

        feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time)))

        handleAlgorithmResults(self.alg, context, feedback, False)

        self.finish(algorithm_results)
        self.buttonCancel.setEnabled(False)
Esempio n. 17
0
    def accept(self):
        alg_parameters = []

        feedback = self.createFeedback()

        load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked()
        project = QgsProject.instance() if load_layers else None

        for row in range(self.mainWidget().tblParameters.rowCount()):
            col = 0
            parameters = {}
            for param in self.algorithm().parameterDefinitions():
                if param.flags() & QgsProcessingParameterDefinition.FlagHidden or param.isDestination():
                    continue
                wrapper = self.mainWidget().wrappers[row][col]
                parameters[param.name()] = wrapper.value()
                if not param.checkValueIsAcceptable(wrapper.value()):
                    self.messageBar().pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format(
                        param.description(), row + 1),
                        level=Qgis.Warning, duration=5)
                    return
                col += 1
            count_visible_outputs = 0
            for out in self.algorithm().destinationParameterDefinitions():
                if out.flags() & QgsProcessingParameterDefinition.FlagHidden:
                    continue

                count_visible_outputs += 1
                widget = self.mainWidget().tblParameters.cellWidget(row, col)
                text = widget.getValue()
                if out.checkValueIsAcceptable(text):
                    if isinstance(out, (QgsProcessingParameterRasterDestination,
                                        QgsProcessingParameterFeatureSink)):
                        # load rasters and sinks on completion
                        parameters[out.name()] = QgsProcessingOutputLayerDefinition(text, project)
                    else:
                        parameters[out.name()] = text
                    col += 1
                else:
                    self.messageBar().pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format(
                        out.description(), row + 1),
                        level=Qgis.Warning, duration=5)
                    return

            alg_parameters.append(parameters)

        with OverrideCursor(Qt.WaitCursor):

            self.mainWidget().setEnabled(False)
            self.cancelButton().setEnabled(True)

            # Make sure the Log tab is visible before executing the algorithm
            try:
                self.showLog()
                self.repaint()
            except:
                pass

            start_time = time.time()

            algorithm_results = []
            for count, parameters in enumerate(alg_parameters):
                if feedback.isCanceled():
                    break
                self.setProgressText(QCoreApplication.translate('BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format(count + 1, len(alg_parameters)))
                self.setInfo(self.tr('<b>Algorithm {0} starting&hellip;</b>').format(self.algorithm().displayName()), escapeHtml=False)

                feedback.pushInfo(self.tr('Input parameters:'))
                feedback.pushCommandInfo(pformat(parameters))
                feedback.pushInfo('')

                # important - we create a new context for each iteration
                # this avoids holding onto resources and layers from earlier iterations,
                # and allows batch processing of many more items then is possible
                # if we hold on to these layers
                context = dataobjects.createContext(feedback)

                alg_start_time = time.time()
                ret, results = execute(self.algorithm(), parameters, context, feedback)
                if ret:
                    self.setInfo(QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format(self.algorithm().displayName()), escapeHtml=False)
                    feedback.setProgress(100)
                    feedback.pushInfo(
                        self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - alg_start_time)))
                    feedback.pushInfo(self.tr('Results:'))
                    feedback.pushCommandInfo(pformat(results))
                    feedback.pushInfo('')
                    algorithm_results.append(results)
                else:
                    break

                handleAlgorithmResults(self.algorithm(), context, feedback, False)

        feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time)))

        self.finish(algorithm_results)
        self.cancelButton().setEnabled(False)
Esempio n. 18
0
def input_to_processing(identifier: str, inp: WPSInput,
                        alg: QgsProcessingAlgorithm,
                        context: ProcessingContext) -> Tuple[str, Any]:
    """ Convert wps input to processing param

        see https://qgis.org/api/classQgsProcessingOutputLayerDefinition.html
        see https://qgis.org/api/qgsprocessingparameters_8cpp_source.html#L272

        see ./python/plugins/processing/tools/general.py:111
        see ./python/plugins/processing/gui/Postprocessing.py:50
        see ./python/plugins/processing/core/Processing.py:126
    """
    param = alg.parameterDefinition(identifier)

    typ = param.type()

    if isinstance(param, DESTINATION_LAYER_TYPES):
        # Do not supports memory: layer since we are storing destination project to file
        param.setSupportsNonFileBasedOutput(False)
        # Enforce pushing created layers to layersToLoadOnCompletion list
        sink = "./%s.%s" % (param.name(), param.defaultFileExtension())
        value = QgsProcessingOutputLayerDefinition(sink,
                                                   context.destination_project)
        value.destinationName = inp[0].data

    elif isinstance(param, QgsProcessingParameterFeatureSource):
        # Support feature selection
        value, has_selection = parse_layer_spec(inp[0].data,
                                                context,
                                                allow_selection=True)
        value = QgsProcessingFeatureSourceDefinition(
            value, selectedFeaturesOnly=has_selection)

    elif isinstance(param, INPUT_LAYER_TYPES):
        if len(inp) > 1:
            value = [parse_layer_spec(i.data, context)[0] for i in inp]
        else:
            value, _ = parse_layer_spec(inp[0].data, context)

    elif typ == 'enum':
        # XXX Processing wants the index of the value in option list
        if param.allowMultiple() and len(inp) > 1:
            opts = param.options()
            value = [opts.index(d.data) for d in inp]
        else:
            value = param.options().index(inp[0].data)

    elif typ == 'extent':
        value = input_to_extent(inp)

    elif typ == 'crs':
        # XXX CRS may be expressed as EPSG (or QgsProperty ?)
        value = inp[0].data

    elif typ in ('fileDestination', 'folderDestination'):
        # Normalize path
        value = basename(normpath(inp[0].data))
        if value != inp[0].data:
            LOGGER.warning(
                "Value for file or folder destination '%s' has been truncated from '%s' to '%s'",
                identifier, inp[0].data, value)

    elif len(inp):
        # Return raw value
        value = inp[0].data
    else:
        # Return undefined value
        if not _is_optional(param):
            LOGGER.warning("Required input %s has no value", identifier)
        value = None

    return param.name(), value