mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			229 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
***************************************************************************
 | 
						|
    grass_provider.py
 | 
						|
    ---------------------
 | 
						|
    Date                 : April 2014
 | 
						|
    Copyright            : (C) 2014 by Victor Olaya
 | 
						|
    Email                : volayaf at gmail dot com
 | 
						|
***************************************************************************
 | 
						|
*                                                                         *
 | 
						|
*   This program is free software; you can redistribute it and/or modify  *
 | 
						|
*   it under the terms of the GNU General Public License as published by  *
 | 
						|
*   the Free Software Foundation; either version 2 of the License, or     *
 | 
						|
*   (at your option) any later version.                                   *
 | 
						|
*                                                                         *
 | 
						|
***************************************************************************
 | 
						|
"""
 | 
						|
 | 
						|
__author__ = "Victor Olaya"
 | 
						|
__date__ = "April 2014"
 | 
						|
__copyright__ = "(C) 2014, Victor Olaya"
 | 
						|
 | 
						|
import json
 | 
						|
from typing import List
 | 
						|
from qgis.PyQt.QtCore import QCoreApplication
 | 
						|
from qgis.core import (
 | 
						|
    Qgis,
 | 
						|
    QgsApplication,
 | 
						|
    QgsProcessingAlgorithm,
 | 
						|
    QgsProcessingProvider,
 | 
						|
    QgsVectorFileWriter,
 | 
						|
    QgsMessageLog,
 | 
						|
    QgsRuntimeProfiler,
 | 
						|
)
 | 
						|
from processing.core.ProcessingConfig import ProcessingConfig, Setting
 | 
						|
from grassprovider.grass_utils import GrassUtils
 | 
						|
from grassprovider.grass_algorithm import GrassAlgorithm
 | 
						|
 | 
						|
 | 
						|
class GrassProvider(QgsProcessingProvider):
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        super().__init__()
 | 
						|
 | 
						|
    def load(self):
 | 
						|
        with QgsRuntimeProfiler.profile("Grass Provider"):
 | 
						|
            ProcessingConfig.settingIcons[self.name()] = self.icon()
 | 
						|
            ProcessingConfig.addSetting(
 | 
						|
                Setting(
 | 
						|
                    self.name(),
 | 
						|
                    GrassUtils.GRASS_LOG_COMMANDS,
 | 
						|
                    self.tr("Log execution commands"),
 | 
						|
                    False,
 | 
						|
                )
 | 
						|
            )
 | 
						|
            ProcessingConfig.addSetting(
 | 
						|
                Setting(
 | 
						|
                    self.name(),
 | 
						|
                    GrassUtils.GRASS_LOG_CONSOLE,
 | 
						|
                    self.tr("Log console output"),
 | 
						|
                    False,
 | 
						|
                )
 | 
						|
            )
 | 
						|
            ProcessingConfig.addSetting(
 | 
						|
                Setting(
 | 
						|
                    self.name(),
 | 
						|
                    GrassUtils.GRASS_HELP_URL,
 | 
						|
                    self.tr("Location of GRASS docs"),
 | 
						|
                    "",
 | 
						|
                )
 | 
						|
            )
 | 
						|
            # Add settings for using r.external/v.external instead of r.in.gdal/v.in.ogr
 | 
						|
            # but set them to False by default because the {r,v}.external implementations
 | 
						|
            # have some bugs on windows + there are algorithms that can't be used with
 | 
						|
            # external data (need a solid r.in.gdal/v.in.ogr).
 | 
						|
            # For more info have a look at e.g. https://trac.osgeo.org/grass/ticket/3927
 | 
						|
            ProcessingConfig.addSetting(
 | 
						|
                Setting(
 | 
						|
                    self.name(),
 | 
						|
                    GrassUtils.GRASS_USE_REXTERNAL,
 | 
						|
                    self.tr(
 | 
						|
                        "For raster layers, use r.external (faster) instead of r.in.gdal"
 | 
						|
                    ),
 | 
						|
                    False,
 | 
						|
                )
 | 
						|
            )
 | 
						|
            ProcessingConfig.addSetting(
 | 
						|
                Setting(
 | 
						|
                    self.name(),
 | 
						|
                    GrassUtils.GRASS_USE_VEXTERNAL,
 | 
						|
                    self.tr(
 | 
						|
                        "For vector layers, use v.external (faster) instead of v.in.ogr"
 | 
						|
                    ),
 | 
						|
                    False,
 | 
						|
                )
 | 
						|
            )
 | 
						|
            ProcessingConfig.readSettings()
 | 
						|
            self.refreshAlgorithms()
 | 
						|
 | 
						|
        return True
 | 
						|
 | 
						|
    def unload(self):
 | 
						|
        ProcessingConfig.removeSetting(GrassUtils.GRASS_LOG_COMMANDS)
 | 
						|
        ProcessingConfig.removeSetting(GrassUtils.GRASS_LOG_CONSOLE)
 | 
						|
        ProcessingConfig.removeSetting(GrassUtils.GRASS_HELP_URL)
 | 
						|
        ProcessingConfig.removeSetting(GrassUtils.GRASS_USE_REXTERNAL)
 | 
						|
        ProcessingConfig.removeSetting(GrassUtils.GRASS_USE_VEXTERNAL)
 | 
						|
 | 
						|
    def parse_algorithms(self) -> list[QgsProcessingAlgorithm]:
 | 
						|
        """
 | 
						|
        Parses all algorithm sources and returns a list of all GRASS
 | 
						|
        algorithms.
 | 
						|
        """
 | 
						|
        algs = []
 | 
						|
        for folder in GrassUtils.grassDescriptionFolders():
 | 
						|
            if (folder / "algorithms.json").exists():
 | 
						|
                # fast approach -- use aggregated JSON summary of algorithms
 | 
						|
                with open(folder / "algorithms.json", encoding="utf8") as f_in:
 | 
						|
                    algorithm_strings = f_in.read()
 | 
						|
 | 
						|
                algorithms_json = json.loads(algorithm_strings)
 | 
						|
                for algorithm_json in algorithms_json:
 | 
						|
                    try:
 | 
						|
                        alg = GrassAlgorithm(
 | 
						|
                            json_definition=algorithm_json, description_folder=folder
 | 
						|
                        )
 | 
						|
                        if alg.name().strip() != "":
 | 
						|
                            algs.append(alg)
 | 
						|
                        else:
 | 
						|
                            QgsMessageLog.logMessage(
 | 
						|
                                self.tr(
 | 
						|
                                    "Could not open GRASS GIS algorithm: {0}"
 | 
						|
                                ).format(algorithm_json.get("name")),
 | 
						|
                                self.tr("Processing"),
 | 
						|
                                Qgis.MessageLevel.Critical,
 | 
						|
                            )
 | 
						|
                    except Exception as e:
 | 
						|
                        QgsMessageLog.logMessage(
 | 
						|
                            self.tr(
 | 
						|
                                "Could not open GRASS GIS algorithm: {0}\n{1}"
 | 
						|
                            ).format(algorithm_json.get("name"), e),
 | 
						|
                            self.tr("Processing"),
 | 
						|
                            Qgis.MessageLevel.Critical,
 | 
						|
                        )
 | 
						|
            else:
 | 
						|
                # slow approach - pass txt files one by one
 | 
						|
                for descriptionFile in folder.glob("*.txt"):
 | 
						|
                    try:
 | 
						|
                        alg = GrassAlgorithm(description_file=descriptionFile)
 | 
						|
                        if alg.name().strip() != "":
 | 
						|
                            algs.append(alg)
 | 
						|
                        else:
 | 
						|
                            QgsMessageLog.logMessage(
 | 
						|
                                self.tr(
 | 
						|
                                    "Could not open GRASS GIS algorithm: {0}"
 | 
						|
                                ).format(descriptionFile),
 | 
						|
                                self.tr("Processing"),
 | 
						|
                                Qgis.MessageLevel.Critical,
 | 
						|
                            )
 | 
						|
                    except Exception as e:
 | 
						|
                        QgsMessageLog.logMessage(
 | 
						|
                            self.tr(
 | 
						|
                                "Could not open GRASS GIS algorithm: {0}\n{1}"
 | 
						|
                            ).format(descriptionFile, e),
 | 
						|
                            self.tr("Processing"),
 | 
						|
                            Qgis.MessageLevel.Critical,
 | 
						|
                        )
 | 
						|
        return algs
 | 
						|
 | 
						|
    def loadAlgorithms(self):
 | 
						|
        version = GrassUtils.installedVersion(True)
 | 
						|
        if version is None:
 | 
						|
            QgsMessageLog.logMessage(
 | 
						|
                self.tr(
 | 
						|
                    "Problem with GRASS installation: GRASS was not found or is not correctly installed"
 | 
						|
                ),
 | 
						|
                self.tr("Processing"),
 | 
						|
                Qgis.MessageLevel.Critical,
 | 
						|
            )
 | 
						|
            return
 | 
						|
 | 
						|
        for a in self.parse_algorithms():
 | 
						|
            self.addAlgorithm(a)
 | 
						|
 | 
						|
    def name(self):
 | 
						|
        return "GRASS"
 | 
						|
 | 
						|
    def longName(self):
 | 
						|
        version = GrassUtils.installedVersion()
 | 
						|
        return f"GRASS GIS ({version})" if version is not None else "GRASS GIS"
 | 
						|
 | 
						|
    def id(self):
 | 
						|
        return "grass"
 | 
						|
 | 
						|
    def helpId(self):
 | 
						|
        return "grass7"
 | 
						|
 | 
						|
    def icon(self):
 | 
						|
        return QgsApplication.getThemeIcon("/providerGrass.svg")
 | 
						|
 | 
						|
    def svgIconPath(self):
 | 
						|
        return QgsApplication.iconPath("/providerGrass.svg")
 | 
						|
 | 
						|
    def versionInfo(self):
 | 
						|
        return GrassUtils.installedVersion() or None
 | 
						|
 | 
						|
    def supportsNonFileBasedOutput(self):
 | 
						|
        """
 | 
						|
        GRASS Provider doesn't support non file based outputs
 | 
						|
        """
 | 
						|
        return False
 | 
						|
 | 
						|
    def supportedOutputVectorLayerExtensions(self):
 | 
						|
        # We use the same extensions as QGIS because:
 | 
						|
        # - QGIS is using OGR like GRASS
 | 
						|
        # - There are very few chances that OGR version used in GRASS is
 | 
						|
        # different from QGIS OGR version.
 | 
						|
        return super().supportedOutputVectorLayerExtensions()
 | 
						|
 | 
						|
    def supportedOutputRasterLayerExtensions(self):
 | 
						|
        return GrassUtils.getSupportedOutputRasterExtensions()
 | 
						|
 | 
						|
    def canBeActivated(self):
 | 
						|
        return not bool(GrassUtils.checkGrassIsInstalled())
 | 
						|
 | 
						|
    def tr(self, string, context=""):
 | 
						|
        if context == "":
 | 
						|
            context = "Grass7AlgorithmProvider"
 | 
						|
        return QCoreApplication.translate(context, string)
 |