mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
[processing] cleanup files from unused code and remove some files
This commit is contained in:
parent
ee8435a789
commit
3d4a59bb8b
@ -26,15 +26,10 @@ __copyright__ = '(C) 2015, Giovanni Manghi'
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||
from processing.core.parameters import ParameterString
|
||||
from processing.core.parameters import ParameterRaster
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.outputs import OutputRaster
|
||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||
|
||||
from processing.tools.system import isWindows
|
||||
|
||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||
|
||||
|
||||
class gdalcalc(GdalAlgorithm):
|
||||
|
||||
|
@ -27,12 +27,6 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.core import QgsSettings
|
||||
|
||||
from processing.core.parameters import ParameterString
|
||||
from processing.core.parameters import ParameterTable
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.parameters import ParameterBoolean
|
||||
from processing.core.parameters import ParameterTableField
|
||||
|
||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||
|
||||
|
@ -25,15 +25,6 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterString
|
||||
from processing.core.parameters import ParameterCrs
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.parameters import ParameterBoolean
|
||||
from processing.core.parameters import ParameterExtent
|
||||
from processing.core.parameters import ParameterTableField
|
||||
|
||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||
|
||||
|
@ -30,14 +30,6 @@ import os
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
|
||||
from processing.core.parameters import (ParameterVector,
|
||||
ParameterExtent,
|
||||
ParameterTableField,
|
||||
ParameterSelection,
|
||||
ParameterNumber,
|
||||
ParameterString)
|
||||
from processing.core.outputs import OutputRaster
|
||||
|
||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||
|
||||
|
@ -31,10 +31,6 @@ from qgis.core import QgsProcessingUtils
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterRaster
|
||||
from processing.core.parameters import ParameterTableField
|
||||
|
||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||
|
||||
|
@ -36,7 +36,6 @@ from processing.core.ProcessingConfig import (ProcessingConfig, Setting)
|
||||
from .Grass7Utils import Grass7Utils
|
||||
from .Grass7Algorithm import Grass7Algorithm
|
||||
from processing.tools.system import isWindows, isMac
|
||||
#from .nviz7 import nviz7
|
||||
|
||||
pluginPath = os.path.normpath(os.path.join(
|
||||
os.path.split(os.path.dirname(__file__))[0], os.pardir))
|
||||
@ -109,7 +108,6 @@ class Grass7AlgorithmProvider(QgsProcessingProvider):
|
||||
except Exception as e:
|
||||
QgsMessageLog.logMessage(
|
||||
self.tr('Could not open GRASS GIS 7 algorithm: {0}\n{1}').format(descriptionFile, str(e)), self.tr('Processing'), QgsMessageLog.CRITICAL)
|
||||
#algs.append(nviz7())
|
||||
return algs
|
||||
|
||||
def loadAlgorithms(self):
|
||||
|
@ -1,196 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
***************************************************************************
|
||||
nviz7.py
|
||||
---------------------
|
||||
Date : August 2012
|
||||
Copyright : (C) 2012 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__ = 'August 2012'
|
||||
__copyright__ = '(C) 2012, Victor Olaya'
|
||||
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
from qgis.core import (QgsProcessingAlgorithm,
|
||||
QgsRasterLayer,
|
||||
QgsProcessingUtils)
|
||||
|
||||
from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||
from processing.core.parameters import ParameterMultipleInput
|
||||
from processing.core.parameters import ParameterExtent
|
||||
from processing.core.parameters import ParameterNumber
|
||||
from processing.core.parameters import ParameterRaster
|
||||
from .Grass7Utils import Grass7Utils
|
||||
from processing.tools.system import getNumExportedLayers
|
||||
from processing.tools import dataobjects
|
||||
|
||||
pluginPath = os.path.normpath(os.path.join(
|
||||
os.path.split(os.path.dirname(__file__))[0], os.pardir))
|
||||
|
||||
|
||||
class nviz7(GeoAlgorithm):
|
||||
|
||||
ELEVATION = 'ELEVATION'
|
||||
VECTOR = 'VECTOR'
|
||||
COLOR = 'COLOR'
|
||||
GRASS_REGION_EXTENT_PARAMETER = 'GRASS_REGION_PARAMETER'
|
||||
GRASS_REGION_CELLSIZE_PARAMETER = 'GRASS_REGION_CELLSIZE_PARAMETER'
|
||||
|
||||
def icon(self):
|
||||
return QIcon(os.path.join(pluginPath, 'images', 'grass.png'))
|
||||
|
||||
def flags(self):
|
||||
return QgsProcessingAlgorithm.FlagHideFromModeler
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.addParameter(ParameterMultipleInput(
|
||||
nviz7.ELEVATION,
|
||||
self.tr('Raster file(s) for elevation'),
|
||||
dataobjects.TYPE_RASTER, True))
|
||||
self.addParameter(ParameterMultipleInput(
|
||||
nviz7.VECTOR,
|
||||
self.tr('Vector lines/areas overlay file(s)'),
|
||||
dataobjects.TYPE_VECTOR_ANY, True))
|
||||
self.addParameter(ParameterMultipleInput(
|
||||
nviz7.COLOR,
|
||||
self.tr('Raster file(s) for color'),
|
||||
dataobjects.TYPE_RASTER, True))
|
||||
self.addParameter(ParameterExtent(
|
||||
nviz7.GRASS_REGION_EXTENT_PARAMETER,
|
||||
self.tr('GRASS region extent')))
|
||||
self.addParameter(ParameterNumber(
|
||||
self.GRASS_REGION_CELLSIZE_PARAMETER,
|
||||
self.tr('GRASS region cellsize (leave 0 for default)'),
|
||||
0, None, 0.0))
|
||||
|
||||
def name(self):
|
||||
return 'nviz7'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('nviz7')
|
||||
|
||||
def group(self):
|
||||
return self.tr('Visualization(NVIZ)')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
commands = []
|
||||
vector = self.getParameterValue(self.VECTOR)
|
||||
elevation = self.getParameterValue(self.ELEVATION)
|
||||
color = self.getParameterValue(self.COLOR)
|
||||
|
||||
region = \
|
||||
str(self.getParameterValue(self.GRASS_REGION_EXTENT_PARAMETER))
|
||||
if not region:
|
||||
region = QgsProcessingUtils.combineLayerExtents(layers)
|
||||
|
||||
regionCoords = region.split(',')
|
||||
command = 'g.region '
|
||||
command += 'n=' + str(regionCoords[3])
|
||||
command += ' s=' + str(regionCoords[2])
|
||||
command += ' e=' + str(regionCoords[1])
|
||||
command += ' w=' + str(regionCoords[0])
|
||||
cellsize = self.getParameterValue(self.GRASS_REGION_CELLSIZE_PARAMETER)
|
||||
if cellsize:
|
||||
command += ' res=' + str(cellsize)
|
||||
else:
|
||||
command += ' res=' + str(self.getDefaultCellsize(parameters, context))
|
||||
commands.append(command)
|
||||
|
||||
command = 'nviz7'
|
||||
if vector:
|
||||
layers = vector.split(';')
|
||||
for layer in layers:
|
||||
(cmd, newfilename) = self.exportVectorLayer(layer)
|
||||
commands.append(cmd)
|
||||
vector = vector.replace(layer, newfilename)
|
||||
command += ' vector=' + vector.replace(';', ',')
|
||||
if color:
|
||||
layers = color.split(';')
|
||||
for layer in layers:
|
||||
(cmd, newfilename) = self.exportRasterLayer(layer)
|
||||
commands.append(cmd)
|
||||
color = color.replace(layer, newfilename)
|
||||
command += ' color=' + color.replace(';', ',')
|
||||
if elevation:
|
||||
layers = elevation.split(';')
|
||||
for layer in layers:
|
||||
(cmd, newfilename) = self.exportRasterLayer(layer)
|
||||
commands.append(cmd)
|
||||
elevation = elevation.replace(layer, newfilename)
|
||||
command += ' elevation=' + elevation.replace(';', ',')
|
||||
if elevation is None and vector is None:
|
||||
command += ' -q'
|
||||
commands.append(command)
|
||||
Grass7Utils.createTempMapset()
|
||||
Grass7Utils.executeGrass7(commands, feedback)
|
||||
|
||||
def getTempFilename(self):
|
||||
filename = 'tmp' + str(time.time()).replace('.', '') \
|
||||
+ str(getNumExportedLayers())
|
||||
return filename
|
||||
|
||||
def exportVectorLayer(self, layer):
|
||||
destFilename = self.getTempFilename()
|
||||
command = 'v.in.ogr'
|
||||
command += ' min_area=-1'
|
||||
command += ' input="' + os.path.dirname(layer) + '"'
|
||||
command += ' layer=' + os.path.basename(layer)[:-4]
|
||||
command += ' output=' + destFilename
|
||||
command += ' --overwrite -o'
|
||||
return (command, destFilename)
|
||||
|
||||
def exportRasterLayer(self, layer):
|
||||
destFilename = self.getTempFilename()
|
||||
command = 'r.in.gdal'
|
||||
command += ' input="' + layer + '"'
|
||||
command += ' band=1'
|
||||
command += ' out=' + destFilename
|
||||
command += ' --overwrite -o'
|
||||
return (command, destFilename)
|
||||
|
||||
def getDefaultCellsize(self, parameters, context):
|
||||
cellsize = 0
|
||||
for param in self.parameterDefinitions():
|
||||
if param.name() in parameters:
|
||||
value = parameters[param.name()]
|
||||
if isinstance(param, ParameterRaster):
|
||||
if isinstance(value, QgsRasterLayer):
|
||||
layer = value
|
||||
else:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(value, context)
|
||||
cellsize = max(cellsize, (layer.extent().xMaximum() -
|
||||
layer.extent().xMinimum()) /
|
||||
layer.width())
|
||||
elif isinstance(param, ParameterMultipleInput):
|
||||
|
||||
layers = value.split(';')
|
||||
for layername in layers:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(layername, context)
|
||||
if isinstance(layer, QgsRasterLayer):
|
||||
cellsize = max(cellsize, (
|
||||
layer.extent().xMaximum() -
|
||||
layer.extent().xMinimum()) /
|
||||
layer.width())
|
||||
|
||||
if cellsize == 0:
|
||||
cellsize = 1
|
||||
return cellsize
|
@ -35,7 +35,6 @@ from qgis.core import (QgsRasterFileWriter,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterRasterDestination)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -70,7 +69,7 @@ class Aspect(QgisAlgorithm):
|
||||
return self.tr('Aspect')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
inputFile = self.parameterAsRasterLayer(parameters, self.INPUT, context).source()
|
||||
zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
|
||||
outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
|
||||
|
@ -35,7 +35,6 @@ from qgis.core import (QgsRasterFileWriter,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterRasterDestination)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -78,7 +77,7 @@ class Hillshade(QgisAlgorithm):
|
||||
return self.tr('Hillshade')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
inputFile = self.parameterAsRasterLayer(parameters, self.INPUT, context).source()
|
||||
zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
azimuth = self.parameterAsDouble(parameters, self.AZIMUTH, context)
|
||||
vAngle = self.parameterAsDouble(parameters, self.V_ANGLE, context)
|
||||
|
@ -43,7 +43,6 @@ from qgis.core import (QgsRectangle,
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools import raster
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
|
||||
class HypsometricCurves(QgisAlgorithm):
|
||||
@ -82,7 +81,7 @@ class HypsometricCurves(QgisAlgorithm):
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_DEM, context)
|
||||
target_crs = raster_layer.crs()
|
||||
rasterPath = exportRasterLayer(raster_layer)
|
||||
rasterPath = raster_layer.source()
|
||||
|
||||
source = self.parameterAsSource(parameters, self.BOUNDARY_LAYER, context)
|
||||
step = self.parameterAsDouble(parameters, self.STEP, context)
|
||||
|
@ -41,7 +41,6 @@ from qgis.core import (QgsFeature,
|
||||
QgsProcessingParameterFeatureSink)
|
||||
from processing.tools import raster
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
|
||||
class PointsFromLines(QgisAlgorithm):
|
||||
@ -74,7 +73,7 @@ class PointsFromLines(QgisAlgorithm):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context)
|
||||
|
||||
raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
|
||||
rasterPath = exportRasterLayer(raster_layer)
|
||||
rasterPath = raster_layer.source()
|
||||
|
||||
rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
|
||||
geoTransform = rasterDS.GetGeoTransform()
|
||||
|
@ -42,7 +42,6 @@ from qgis.core import (QgsFeatureRequest,
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools import raster
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
|
||||
class PointsFromPolygons(QgisAlgorithm):
|
||||
@ -74,7 +73,7 @@ class PointsFromPolygons(QgisAlgorithm):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context)
|
||||
|
||||
raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
|
||||
rasterPath = exportRasterLayer(raster_layer)
|
||||
rasterPath = raster_layer.source()
|
||||
|
||||
rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
|
||||
geoTransform = rasterDS.GetGeoTransform()
|
||||
|
@ -39,7 +39,6 @@ from qgis.core import (QgsProcessingParameterDefinition,
|
||||
QgsRasterFileWriter,
|
||||
QgsProcessingException)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -126,7 +125,7 @@ class Relief(QgisAlgorithm):
|
||||
return self.tr('Relief')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
inputFile = self.parameterAsRasterLayer(parameters, self.INPUT, context).source()
|
||||
zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
automaticColors = self.parameterAsBool(parameters, self.AUTO_COLORS, context)
|
||||
outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
|
||||
|
@ -35,7 +35,6 @@ from qgis.core import (QgsRasterFileWriter,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterRasterDestination)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -71,7 +70,7 @@ class Ruggedness(QgisAlgorithm):
|
||||
return self.tr('Ruggedness index')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
inputFile = self.parameterAsRasterLayer(parameters, self.INPUT, context).source()
|
||||
zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
|
||||
outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
|
||||
|
@ -35,8 +35,6 @@ from qgis.core import (QgsRasterFileWriter,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterRasterDestination)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools.dataobjects import exportRasterLayer
|
||||
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -71,7 +69,7 @@ class Slope(QgisAlgorithm):
|
||||
return self.tr('Slope')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
inputFile = self.parameterAsRasterLayer(parameters, self.INPUT, context).source()
|
||||
zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
|
||||
outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
|
||||
|
@ -1,22 +1,25 @@
|
||||
from qgis.core import (QgsProcessingUtils,
|
||||
QgsProcessingParameterDefinition,
|
||||
QgsProject)
|
||||
from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_BATCH
|
||||
from processing.tools import dataobjects
|
||||
from processing.tools.system import userFolder
|
||||
from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel
|
||||
from qgis.PyQt.QtWidgets import (QLineEdit, QPushButton, QLabel,
|
||||
QComboBox, QSpacerItem, QSizePolicy)
|
||||
from qgis.PyQt.QtGui import QTextCursor
|
||||
from processing.core.outputs import OutputRaster
|
||||
from processing.core.parameters import ParameterRaster
|
||||
from processing.gui.wrappers import InvalidParameterValue
|
||||
import os
|
||||
from qgis.PyQt import uic
|
||||
from functools import partial
|
||||
import re
|
||||
import json
|
||||
|
||||
from qgis.PyQt import uic
|
||||
from qgis.PyQt.QtGui import QTextCursor
|
||||
from qgis.PyQt.QtWidgets import (QLineEdit, QPushButton, QLabel,
|
||||
QComboBox, QSpacerItem, QSizePolicy)
|
||||
|
||||
from qgis.core import (QgsProcessingUtils,
|
||||
QgsProcessingParameterDefinition,
|
||||
QgsProject)
|
||||
|
||||
from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_BATCH
|
||||
from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel
|
||||
from processing.tools import dataobjects
|
||||
from processing.tools.system import userFolder
|
||||
|
||||
|
||||
from processing.gui.wrappers import InvalidParameterValue
|
||||
|
||||
pluginPath = os.path.dirname(__file__)
|
||||
WIDGET_ADD_NEW, BASE_ADD_NEW = uic.loadUiType(
|
||||
os.path.join(pluginPath, 'AddNewExpressionDialog.ui'))
|
||||
@ -183,7 +186,7 @@ class ExpressionWidgetWrapper(WidgetWrapper):
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
return QLineEdit()
|
||||
else:
|
||||
layers = self.dialog.getAvailableValuesOfType(ParameterRaster, OutputRaster)
|
||||
layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterRasterLayer], [QgsProcessingOutputRasterLayer])
|
||||
options = {self.dialog.resolveValueDescription(lyr): "{}@1".format(lyr) for lyr in layers}
|
||||
return self._panel(options)
|
||||
|
||||
|
@ -1,340 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
***************************************************************************
|
||||
GeoAlgorithm.py
|
||||
---------------------
|
||||
Date : August 2012
|
||||
Copyright : (C) 2012 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__ = 'August 2012'
|
||||
__copyright__ = '(C) 2012, Victor Olaya'
|
||||
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import os.path
|
||||
import traceback
|
||||
import subprocess
|
||||
import copy
|
||||
|
||||
from qgis.PyQt.QtCore import QCoreApplication
|
||||
|
||||
from qgis.core import (QgsProcessingFeedback,
|
||||
QgsSettings,
|
||||
QgsProcessingAlgorithm,
|
||||
QgsProject,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingException,
|
||||
QgsProcessingParameterDefinition,
|
||||
QgsMessageLog)
|
||||
from qgis.gui import QgsHelp
|
||||
|
||||
from processing.core.ProcessingConfig import ProcessingConfig
|
||||
from processing.core.parameters import ParameterRaster, ParameterVector, ParameterMultipleInput, ParameterTable, Parameter
|
||||
from processing.core.outputs import OutputVector, OutputRaster, OutputTable, OutputHTML, Output
|
||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||
from processing.tools import dataobjects
|
||||
|
||||
|
||||
class GeoAlgorithm(QgsProcessingAlgorithm):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Outputs generated by the algorithm
|
||||
self.outputs = list()
|
||||
|
||||
# The crs taken from input layers (if possible), and used when
|
||||
# loading output layers
|
||||
self.crs = None
|
||||
|
||||
# If the algorithm is run as part of a model, the parent model
|
||||
# can be set in this variable, to allow for customized
|
||||
# behavior, in case some operations should be run differently
|
||||
# when running as part of a model
|
||||
self.model = None
|
||||
|
||||
# methods to overwrite when creating a custom geoalgorithm
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
"""Here goes the algorithm itself.
|
||||
|
||||
There is no return value from this method.
|
||||
A QgsProcessingException should be raised in case
|
||||
something goes wrong.
|
||||
:param parameters:
|
||||
:param context:
|
||||
"""
|
||||
pass
|
||||
|
||||
def getCustomModelerParametersDialog(self, modelAlg, algName=None):
|
||||
"""If the algorithm has a custom parameters dialog when called
|
||||
from the modeler, it should be returned here, ready to be
|
||||
executed.
|
||||
"""
|
||||
return None
|
||||
|
||||
def processBeforeAddingToModeler(self, alg, model):
|
||||
"""Add here any task that has to be performed before adding an algorithm
|
||||
to a model, such as changing the value of a parameter depending on value
|
||||
of another one"""
|
||||
pass
|
||||
|
||||
# =========================================================
|
||||
|
||||
def execute(self, parameters, context=None, feedback=None, model=None):
|
||||
"""The method to use to call a processing algorithm.
|
||||
|
||||
Although the body of the algorithm is in processAlgorithm(),
|
||||
it should be called using this method, since it performs
|
||||
some additional operations.
|
||||
|
||||
Raises a QgsProcessingException in case anything goes
|
||||
wrong.
|
||||
:param parameters:
|
||||
"""
|
||||
|
||||
if feedback is None:
|
||||
feedback = QgsProcessingFeedback()
|
||||
if context is None:
|
||||
context = dataobjects.createContext(feedback)
|
||||
|
||||
self.model = model
|
||||
try:
|
||||
self.setOutputCRS()
|
||||
self.resolveOutputs()
|
||||
self.runPreExecutionScript(feedback)
|
||||
self.processAlgorithm(parameters, context, feedback)
|
||||
feedback.setProgress(100)
|
||||
self.convertUnsupportedFormats(context, feedback)
|
||||
self.runPostExecutionScript(feedback)
|
||||
except QgsProcessingException as gaee:
|
||||
lines = [self.tr('Error while executing algorithm')]
|
||||
lines.append(traceback.format_exc())
|
||||
QgsMessageLog.logMessage(gaee.msg, self.tr('Processing'), QgsMessageLog.CRITICAL)
|
||||
raise QgsProcessingException(gaee.msg, lines, gaee)
|
||||
except Exception as e:
|
||||
# If something goes wrong and is not caught in the
|
||||
# algorithm, we catch it here and wrap it
|
||||
lines = [self.tr('Uncaught error while executing algorithm')]
|
||||
lines.append(traceback.format_exc())
|
||||
QgsMessageLog.logMessage('\n'.join(lines), self.tr('Processing'), QgsMessageLog.CRITICAL)
|
||||
raise QgsProcessingException(str(e) + self.tr('\nSee log for more details'), lines, e)
|
||||
|
||||
def runPostExecutionScript(self, feedback):
|
||||
scriptFile = ProcessingConfig.getSetting(
|
||||
ProcessingConfig.POST_EXECUTION_SCRIPT)
|
||||
self.runHookScript(scriptFile, feedback)
|
||||
|
||||
def runPreExecutionScript(self, feedback):
|
||||
scriptFile = ProcessingConfig.getSetting(
|
||||
ProcessingConfig.PRE_EXECUTION_SCRIPT)
|
||||
self.runHookScript(scriptFile, feedback)
|
||||
|
||||
def runHookScript(self, filename, feedback):
|
||||
if filename is None or not os.path.exists(filename):
|
||||
return
|
||||
try:
|
||||
script = 'import processing\n'
|
||||
ns = {}
|
||||
ns['feedback'] = feedback
|
||||
ns['alg'] = self
|
||||
with open(filename) as f:
|
||||
lines = f.readlines()
|
||||
for line in lines:
|
||||
script += line
|
||||
exec(script, ns)
|
||||
except Exception as e:
|
||||
QgsMessageLog.logMessage("Error in hook script: " + str(e), self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
# A wrong script should not cause problems, so we swallow
|
||||
# all exceptions
|
||||
pass
|
||||
|
||||
def convertUnsupportedFormats(self, context, feedback):
|
||||
i = 0
|
||||
feedback.setProgressText(self.tr('Converting outputs'))
|
||||
for out in self.outputs:
|
||||
if isinstance(out, OutputVector):
|
||||
if out.compatible is not None:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(out.compatible, context)
|
||||
if layer is None:
|
||||
# For the case of memory layer, if the
|
||||
# getCompatible method has been called
|
||||
continue
|
||||
writer = out.getVectorWriter(layer.fields(), layer.wkbType(), layer.crs(), context)
|
||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||
for feature in features:
|
||||
writer.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
elif isinstance(out, OutputRaster):
|
||||
if out.compatible is not None:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(out.compatible, context)
|
||||
format = self.getFormatShortNameFromFilename(out.value)
|
||||
orgFile = out.compatible
|
||||
destFile = out.value
|
||||
crsid = layer.crs().authid()
|
||||
settings = QgsSettings()
|
||||
path = str(settings.value('/GdalTools/gdalPath', ''))
|
||||
envval = str(os.getenv('PATH'))
|
||||
if not path.lower() in envval.lower().split(os.pathsep):
|
||||
envval += '%s%s' % (os.pathsep, path)
|
||||
os.putenv('PATH', envval)
|
||||
command = 'gdal_translate -of %s -a_srs %s %s %s' % (format, crsid, orgFile, destFile)
|
||||
if os.name == 'nt':
|
||||
command = command.split(" ")
|
||||
else:
|
||||
command = [command]
|
||||
proc = subprocess.Popen(
|
||||
command,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stdin=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=False,
|
||||
)
|
||||
proc.communicate()
|
||||
|
||||
elif isinstance(out, OutputTable):
|
||||
if out.compatible is not None:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(out.compatible, context)
|
||||
writer = out.getTableWriter(layer.fields())
|
||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||
for feature in features:
|
||||
writer.addRecord(feature)
|
||||
feedback.setProgress(100 * i / float(len(self.outputs)))
|
||||
|
||||
def getFormatShortNameFromFilename(self, filename):
|
||||
ext = filename[filename.rfind('.') + 1:]
|
||||
supported = GdalUtils.getSupportedRasters()
|
||||
for name in list(supported.keys()):
|
||||
exts = supported[name]
|
||||
if ext in exts:
|
||||
return name
|
||||
return 'GTiff'
|
||||
|
||||
def resolveOutputs(self):
|
||||
"""Sets temporary outputs (output.value = None) with a
|
||||
temporary file instead. Resolves expressions as well.
|
||||
"""
|
||||
try:
|
||||
for out in self.outputs:
|
||||
out.resolveValue(self)
|
||||
except ValueError as e:
|
||||
raise QgsProcessingException(str(e))
|
||||
|
||||
def setOutputCRS(self):
|
||||
context = dataobjects.createContext()
|
||||
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
|
||||
for param in self.parameterDefinitions():
|
||||
if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)):
|
||||
if param.value:
|
||||
if isinstance(param, ParameterMultipleInput):
|
||||
inputlayers = param.value.split(';')
|
||||
else:
|
||||
inputlayers = [param.value]
|
||||
for inputlayer in inputlayers:
|
||||
for layer in layers:
|
||||
if layer.source() == inputlayer:
|
||||
self.crs = layer.crs()
|
||||
return
|
||||
p = QgsProcessingUtils.mapLayerFromString(inputlayer, context)
|
||||
if p is not None:
|
||||
self.crs = p.crs()
|
||||
p = None
|
||||
return
|
||||
try:
|
||||
from qgis.utils import iface
|
||||
if iface is not None:
|
||||
self.crs = iface.mapCanvas().mapSettings().destinationCrs()
|
||||
except:
|
||||
pass
|
||||
|
||||
def addOutput(self, output):
|
||||
# TODO: check that name does not exist
|
||||
if isinstance(output, Output):
|
||||
self.outputs.append(output)
|
||||
|
||||
def addParameter(self, param):
|
||||
# TODO: check that name does not exist
|
||||
if isinstance(param, Parameter):
|
||||
self.parameters.append(param)
|
||||
|
||||
def setOutputValue(self, outputName, value):
|
||||
for out in self.outputs:
|
||||
if out.name == outputName:
|
||||
out.setValue(value)
|
||||
|
||||
def removeOutputFromName(self, name):
|
||||
for out in self.outputs:
|
||||
if out.name == name:
|
||||
self.outputs.remove(out)
|
||||
|
||||
def getOutputFromName(self, name):
|
||||
for out in self.outputs:
|
||||
if out.name == name:
|
||||
return out
|
||||
|
||||
def getParameterValue(self, name):
|
||||
for param in self.parameters:
|
||||
if param.name == name:
|
||||
return param.value
|
||||
return None
|
||||
|
||||
def getOutputValue(self, name):
|
||||
for out in self.outputs:
|
||||
if out.name == name:
|
||||
return out.value
|
||||
return None
|
||||
|
||||
def tr(self, string, context=''):
|
||||
if context == '':
|
||||
context = self.__class__.__name__
|
||||
return QCoreApplication.translate(context, string)
|
||||
|
||||
def trAlgorithm(self, string, context=''):
|
||||
if context == '':
|
||||
context = self.__class__.__name__
|
||||
return string, QCoreApplication.translate(context, string)
|
||||
|
||||
|
||||
def executeAlgorithm(alg, parameters, context=None, feedback=None, model=None):
|
||||
"""The method to use to call a processing algorithm.
|
||||
|
||||
Although the body of the algorithm is in processAlgorithm(),
|
||||
it should be called using this method, since it performs
|
||||
some additional operations.
|
||||
|
||||
Raises a QgsProcessingException in case anything goes
|
||||
wrong.
|
||||
:param parameters:
|
||||
"""
|
||||
|
||||
if feedback is None:
|
||||
feedback = QgsProcessingFeedback()
|
||||
if context is None:
|
||||
context = dataobjects.createContext(feedback)
|
||||
|
||||
#self.model = model
|
||||
|
||||
#self.setOutputCRS()
|
||||
#self.resolveOutputs()
|
||||
#self.evaluateParameterValues()
|
||||
#self.runPreExecutionScript(feedback)
|
||||
result, ok = alg.run(parameters, context, feedback)
|
||||
#self.processAlgorithm(parameters, context, feedback)
|
||||
feedback.setProgress(100)
|
||||
return result, ok
|
||||
#self.convertUnsupportedFormats(context, feedback)
|
||||
#self.runPostExecutionScript(feedback)
|
@ -47,7 +47,6 @@ from qgis.core import (QgsMessageLog,
|
||||
import processing
|
||||
from processing.script.ScriptUtils import ScriptUtils
|
||||
from processing.core.ProcessingConfig import ProcessingConfig
|
||||
from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||
from processing.gui.MessageBarProgress import MessageBarProgress
|
||||
from processing.gui.RenderingStyles import RenderingStyles
|
||||
from processing.gui.Postprocessing import handleAlgorithmResults
|
||||
|
@ -25,16 +25,8 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from qgis.PyQt.QtCore import QCoreApplication
|
||||
|
||||
from processing.core.ProcessingConfig import ProcessingConfig
|
||||
from processing.tools.system import isWindows, getTempDirInTempFolder
|
||||
from processing.tools.vector import TableWriter, NOGEOMETRY_EXTENSIONS
|
||||
from processing.tools import dataobjects
|
||||
|
||||
from qgis.core import (QgsExpressionContext,
|
||||
QgsExpressionContextUtils,
|
||||
QgsExpression,
|
||||
@ -53,341 +45,6 @@ from qgis.core import (QgsExpressionContext,
|
||||
QgsProcessingOutputFolder)
|
||||
|
||||
|
||||
def _expressionContext(alg):
|
||||
context = QgsExpressionContext()
|
||||
context.appendScope(QgsExpressionContextUtils.globalScope())
|
||||
context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance()))
|
||||
processingScope = QgsExpressionContextScope()
|
||||
for param in alg.parameters:
|
||||
processingScope.setVariable('%s_value' % param.name, '')
|
||||
context.appendScope(processingScope)
|
||||
return context
|
||||
|
||||
|
||||
class Output:
|
||||
|
||||
def __init__(self, name='', description='', hidden=False):
|
||||
self.name = name
|
||||
|
||||
# The value of an output is a string representing the location
|
||||
# of the output. For a file based output, it should be the
|
||||
# filepath to it.
|
||||
self.value = None
|
||||
|
||||
def __str__(self):
|
||||
return u'{} <{}>'.format(self.name, self.__class__.__name__)
|
||||
|
||||
def getValueAsCommandLineParameter(self):
|
||||
if self.value is None:
|
||||
return str(None)
|
||||
else:
|
||||
if not isWindows():
|
||||
return '"' + str(self.value) + '"'
|
||||
else:
|
||||
return '"' + str(self.value).replace('\\', '\\\\') + '"'
|
||||
|
||||
def setValue(self, value):
|
||||
try:
|
||||
if value is not None and isinstance(value, str):
|
||||
value = value.strip()
|
||||
self.value = value
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def _resolveTemporary(self, alg):
|
||||
ext = self.getDefaultFileExtension()
|
||||
return QgsProcessingUtils.generateTempFilename(self.name + '.' + ext)
|
||||
|
||||
def _supportedExtensions(self):
|
||||
return []
|
||||
|
||||
def resolveValue(self, alg):
|
||||
if self.flags() & QgsProcessingParameterDefinition.FlagHidden:
|
||||
return
|
||||
if not bool(self.value):
|
||||
self.value = self._resolveTemporary(alg)
|
||||
else:
|
||||
exp = QgsExpression(self.value)
|
||||
if not exp.hasParserError():
|
||||
value = exp.evaluate(_expressionContext(alg))
|
||||
if not exp.hasEvalError():
|
||||
self.value = value
|
||||
|
||||
if ":" not in self.value:
|
||||
if not os.path.isabs(self.value):
|
||||
self.value = os.path.join(ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER),
|
||||
self.value)
|
||||
supported = self._supportedExtensions()
|
||||
if supported:
|
||||
idx = self.value.rfind('.')
|
||||
if idx == -1:
|
||||
self.value = self.value + '.' + self.getDefaultFileExtension()
|
||||
else:
|
||||
ext = self.value[idx + 1:]
|
||||
if ext not in supported:
|
||||
self.value = self.value + '.' + self.getDefaultFileExtension()
|
||||
|
||||
def expressionContext(self, alg):
|
||||
return _expressionContext(alg)
|
||||
|
||||
def tr(self, string, context=''):
|
||||
if context == '':
|
||||
context = 'Output'
|
||||
return QCoreApplication.translate(context, string)
|
||||
|
||||
|
||||
class OutputDirectory(Output):
|
||||
|
||||
def resolveValue(self, alg):
|
||||
self.value = getTempDirInTempFolder()
|
||||
|
||||
|
||||
class OutputExtent(Output):
|
||||
|
||||
def __init__(self, name='', description=''):
|
||||
self.name = name
|
||||
self.value = None
|
||||
self.setFlags(self.flags() | QgsProcessingParameterDefinition.FlagHidden)
|
||||
|
||||
def setValue(self, value):
|
||||
try:
|
||||
if value is not None and isinstance(value, str):
|
||||
value = value.strip()
|
||||
else:
|
||||
self.value = ','.join([str(v) for v in value])
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
class OutputCrs(Output):
|
||||
|
||||
def __init__(self, name='', description=''):
|
||||
Output.__init__(self, name, description, True)
|
||||
|
||||
|
||||
class OutputFile(Output):
|
||||
|
||||
def __init__(self, name='', description='', ext=None):
|
||||
Output.__init__(self, name, description)
|
||||
self.ext = ext
|
||||
|
||||
def getFileFilter(self, alg):
|
||||
if self.ext is None:
|
||||
return self.tr('All files (*.*)', 'OutputFile')
|
||||
else:
|
||||
return self.tr('{0} files (*.{1})', 'OutputFile').format(self.ext, self.ext)
|
||||
|
||||
def getDefaultFileExtension(self):
|
||||
return self.ext or 'file'
|
||||
|
||||
|
||||
class OutputHTML(Output):
|
||||
|
||||
def getFileFilter(self, alg):
|
||||
return self.tr('HTML files (*.html)', 'OutputHTML')
|
||||
|
||||
def getDefaultFileExtension(self):
|
||||
return 'html'
|
||||
|
||||
|
||||
class OutputNumber(Output):
|
||||
|
||||
def __init__(self, name='', description=''):
|
||||
Output.__init__(self, name, description, True)
|
||||
|
||||
|
||||
class OutputRaster(Output):
|
||||
|
||||
compatible = None
|
||||
|
||||
def getFileFilter(self, alg):
|
||||
exts = dataobjects.getSupportedOutputRasterLayerExtensions()
|
||||
for i in range(len(exts)):
|
||||
exts[i] = self.tr('{0} files (*.{1})', 'OutputVector').format(exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
|
||||
def getDefaultFileExtension(self):
|
||||
return ProcessingConfig.getSetting(ProcessingConfig.DEFAULT_OUTPUT_RASTER_LAYER_EXT, True)
|
||||
|
||||
def getCompatibleFileName(self, alg):
|
||||
"""
|
||||
Returns a filename that is compatible with the algorithm
|
||||
that is going to generate this output. If the algorithm
|
||||
supports the file format of the current output value, it
|
||||
returns that value. If not, it returns a temporary file with
|
||||
a supported file format, to be used to generate the output
|
||||
result.
|
||||
"""
|
||||
|
||||
ext = self.value[self.value.rfind('.') + 1:]
|
||||
if ext in alg.provider().supportedOutputRasterLayerExtensions():
|
||||
return self.value
|
||||
else:
|
||||
if self.compatible is None:
|
||||
supported = alg.provider().supportedOutputRasterLayerExtensions()
|
||||
default = ProcessingConfig.getSetting(ProcessingConfig.DEFAULT_OUTPUT_RASTER_LAYER_EXT, True)
|
||||
ext = default if default in supported else supported[0]
|
||||
self.compatible = QgsProcessingUtils.generateTempFilename(self.name + '.' + ext)
|
||||
return self.compatible
|
||||
|
||||
|
||||
class OutputString(Output):
|
||||
|
||||
def __init__(self, name='', description=''):
|
||||
Output.__init__(self, name, description, True)
|
||||
|
||||
|
||||
class OutputTable(Output):
|
||||
|
||||
encoding = None
|
||||
compatible = None
|
||||
|
||||
def getFileFilter(self, alg):
|
||||
exts = ['dbf']
|
||||
for i in range(len(exts)):
|
||||
exts[i] = self.tr("{0} files (*.{1})").format(exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
|
||||
def getDefaultFileExtension(self):
|
||||
return "dbf"
|
||||
|
||||
def getCompatibleFileName(self, alg):
|
||||
"""Returns a filename that is compatible with the algorithm
|
||||
that is going to generate this output.
|
||||
|
||||
If the algorithm supports the file format of the current
|
||||
output value, it returns that value. If not, it returns a
|
||||
temporary file with a supported file format, to be used to
|
||||
generate the output result.
|
||||
"""
|
||||
|
||||
ext = self.value[self.value.rfind('.') + 1:]
|
||||
if ext in alg.provider().supportedOutputTableExtensions():
|
||||
return self.value
|
||||
else:
|
||||
if self.compatible is None:
|
||||
self.compatible = QgsProcessingUtils.generateTempFilename(
|
||||
self.name + '.' + alg.provider().supportedOutputTableExtensions()[0])
|
||||
return self.compatible
|
||||
|
||||
def getTableWriter(self, fields):
|
||||
"""
|
||||
Returns a suitable writer to which records can be added as a
|
||||
result of the algorithm. Use this to transparently handle
|
||||
output values instead of creating your own method.
|
||||
|
||||
@param fields a list of field titles
|
||||
|
||||
@return writer instance of the table writer class
|
||||
"""
|
||||
|
||||
if self.encoding is None:
|
||||
settings = QgsSettings()
|
||||
self.encoding = settings.value('/Processing/encoding', 'System')
|
||||
|
||||
return TableWriter(self.value, self.encoding, fields)
|
||||
|
||||
|
||||
class OutputVector(Output):
|
||||
|
||||
encoding = None
|
||||
compatible = None
|
||||
|
||||
def __init__(self, name='', description='', hidden=False, base_input=None, datatype=[-1]):
|
||||
Output.__init__(self, name, description, hidden)
|
||||
self.base_input = base_input
|
||||
self.base_layer = None
|
||||
if isinstance(datatype, int):
|
||||
datatype = [datatype]
|
||||
elif isinstance(datatype, str):
|
||||
datatype = [int(t) for t in datatype.split(',')]
|
||||
self.datatype = datatype
|
||||
|
||||
def hasGeometry(self):
|
||||
if self.base_layer is None:
|
||||
return True
|
||||
return self.base_layer.isSpatial()
|
||||
|
||||
def getSupportedOutputVectorLayerExtensions(self):
|
||||
exts = QgsVectorFileWriter.supportedFormatExtensions()
|
||||
if not self.hasGeometry():
|
||||
exts = ['dbf'] + [ext for ext in exts if ext in NOGEOMETRY_EXTENSIONS]
|
||||
return exts
|
||||
|
||||
def getFileFilter(self, alg):
|
||||
exts = self.getSupportedOutputVectorLayerExtensions()
|
||||
for i in range(len(exts)):
|
||||
exts[i] = self.tr('{0} files (*.{1})', 'OutputVector').format(exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
|
||||
def getDefaultFileExtension(self):
|
||||
if self.hasGeometry():
|
||||
default = ProcessingConfig.getSetting(ProcessingConfig.DEFAULT_OUTPUT_VECTOR_LAYER_EXT, True)
|
||||
else:
|
||||
default = 'dbf'
|
||||
return default
|
||||
|
||||
def getCompatibleFileName(self, alg):
|
||||
"""Returns a filename that is compatible with the algorithm
|
||||
that is going to generate this output.
|
||||
|
||||
If the algorithm supports the file format of the current
|
||||
output value, it returns that value. If not, it returns a
|
||||
temporary file with a supported file format, to be used to
|
||||
generate the output result.
|
||||
"""
|
||||
ext = self.value[self.value.rfind('.') + 1:]
|
||||
if ext in alg.provider().supportedOutputVectorLayerExtensions():
|
||||
return self.value
|
||||
else:
|
||||
if self.compatible is None:
|
||||
default = self.getDefaultFileExtension()
|
||||
supported = alg.provider().supportedOutputVectorLayerExtensions()
|
||||
ext = default if default in supported else supported[0]
|
||||
self.compatible = QgsProcessingUtils.generateTempFilename(self.name + '.' + ext)
|
||||
return self.compatible
|
||||
|
||||
def getVectorWriter(self, fields, geomType, crs, context):
|
||||
"""Returns a suitable writer to which features can be added as
|
||||
a result of the algorithm. Use this to transparently handle
|
||||
output values instead of creating your own method.
|
||||
|
||||
Executing this method might modify the object, adding additional
|
||||
information to it, so the writer can be later accessed and
|
||||
processed within QGIS. It should be called just once, since a
|
||||
new call might result in previous data being replaced, thus
|
||||
rendering a previously obtained writer useless.
|
||||
|
||||
@param fields a list of QgsField
|
||||
@param geomType a suitable geometry type, as it would be passed
|
||||
to a QgsVectorFileWriter constructor
|
||||
@param crs the crs of the layer to create
|
||||
|
||||
@return writer instance of the vector writer class
|
||||
:param context:
|
||||
"""
|
||||
|
||||
if self.encoding is None:
|
||||
settings = QgsSettings()
|
||||
self.encoding = settings.value('/Processing/encoding', 'System', str)
|
||||
|
||||
w, w_dest = QgsProcessingUtils.createFeatureSink(self.value, context, fields, geomType, crs, {'fileEncoding': self.encoding})
|
||||
self.value = w_dest
|
||||
return w
|
||||
|
||||
def dataType(self):
|
||||
return dataobjects.vectorDataType(self)
|
||||
|
||||
def _resolveTemporary(self, alg):
|
||||
if alg.provider().supportsNonFileBasedOutput():
|
||||
return "memory:"
|
||||
else:
|
||||
ext = self.getDefaultFileExtension()
|
||||
return QgsProcessingUtils.generateTempFilename(self.name + '.' + ext)
|
||||
|
||||
|
||||
def getOutputFromString(s):
|
||||
try:
|
||||
if "|" in s and s.startswith("Output"):
|
||||
|
@ -26,21 +26,17 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import sys
|
||||
import os
|
||||
import math
|
||||
from inspect import isclass
|
||||
from copy import deepcopy
|
||||
import numbers
|
||||
|
||||
from qgis.core import QgsProcessingUtils
|
||||
|
||||
from qgis.PyQt.QtCore import QCoreApplication
|
||||
from qgis.core import (QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsCoordinateReferenceSystem,
|
||||
from qgis.core import (QgsRasterLayer,
|
||||
QgsVectorLayer,
|
||||
QgsMapLayer,
|
||||
QgsCoordinateReferenceSystem,
|
||||
QgsExpression,
|
||||
QgsProject,
|
||||
QgsRectangle,
|
||||
QgsVectorFileWriter,
|
||||
QgsProcessing,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameters,
|
||||
QgsProcessingParameterDefinition,
|
||||
QgsProcessingParameterRasterLayer,
|
||||
@ -63,522 +59,6 @@ from qgis.core import (QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsCoordinat
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterNumber)
|
||||
|
||||
from processing.tools.vector import resolveFieldIndex
|
||||
from processing.tools import dataobjects
|
||||
from processing.core.outputs import OutputNumber, OutputRaster, OutputVector
|
||||
|
||||
|
||||
def parseBool(s):
|
||||
if s is None or s == str(None).lower():
|
||||
return None
|
||||
return str(s).lower() == str(True).lower()
|
||||
|
||||
|
||||
def _splitParameterOptions(line):
|
||||
tokens = line.split('=', 1)
|
||||
if tokens[1].lower().strip().startswith('optional'):
|
||||
isOptional = True
|
||||
definition = tokens[1].strip()[len('optional') + 1:]
|
||||
else:
|
||||
isOptional = False
|
||||
definition = tokens[1]
|
||||
return isOptional, tokens[0], definition
|
||||
|
||||
|
||||
class Parameter:
|
||||
|
||||
"""
|
||||
Base class for all parameters that a geoalgorithm might
|
||||
take as input.
|
||||
"""
|
||||
|
||||
def __init__(self, name='', description='', default=None, optional=False,
|
||||
metadata={}):
|
||||
self.value = default
|
||||
|
||||
def __str__(self):
|
||||
return u'{} <{}>'.format(self.name(), self.__class__.__name__)
|
||||
|
||||
def todict(self):
|
||||
o = deepcopy(self.__dict__)
|
||||
del o['metadata']
|
||||
return o
|
||||
|
||||
def tr(self, string, context=''):
|
||||
if context == '':
|
||||
context = 'Parameter'
|
||||
return QCoreApplication.translate(context, string)
|
||||
|
||||
|
||||
class ParameterBoolean(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', default=None, optional=False, metadata={}):
|
||||
Parameter.__init__(self, name, description, parseBool(default), optional, metadata)
|
||||
|
||||
|
||||
class ParameterCrs(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', default=None, optional=False, metadata={}):
|
||||
'''The value is a string that uniquely identifies the
|
||||
coordinate reference system. Typically it is the auth id of the CRS
|
||||
(if the authority is EPSG) or proj4 string of the CRS (in case
|
||||
of other authorities or user defined projections).'''
|
||||
Parameter.__init__(self, name, description, default, optional, metadata)
|
||||
if self.value == 'ProjectCrs':
|
||||
self.value = QgsProject.instance().crs().authid()
|
||||
|
||||
|
||||
class ParameterExtent(Parameter):
|
||||
|
||||
USE_MIN_COVERING_EXTENT = 'USE_MIN_COVERING_EXTENT'
|
||||
|
||||
def __init__(self, name='', description='', default=None, optional=True):
|
||||
Parameter.__init__(self, name, description, default, optional)
|
||||
# The value is a string in the form "xmin, xmax, ymin, ymax"
|
||||
self.skip_crs_check = False
|
||||
|
||||
|
||||
class ParameterPoint(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', default=None, optional=False):
|
||||
Parameter.__init__(self, name, description, default, optional)
|
||||
# The value is a string in the form "x, y"
|
||||
|
||||
|
||||
class ParameterFile(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', isFolder=False, optional=True, ext=None):
|
||||
Parameter.__init__(self, name, description, None, parseBool(optional))
|
||||
self.ext = ext
|
||||
self.isFolder = parseBool(isFolder)
|
||||
|
||||
|
||||
class ParameterFixedTable(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', numRows=3,
|
||||
cols=['value'], fixedNumOfRows=False, optional=False):
|
||||
Parameter.__init__(self, name, description, None, optional)
|
||||
self.cols = cols
|
||||
if isinstance(cols, str):
|
||||
self.cols = self.cols.split(";")
|
||||
self.numRows = int(numRows)
|
||||
self.fixedNumOfRows = parseBool(fixedNumOfRows)
|
||||
|
||||
@staticmethod
|
||||
def tableToString(table):
|
||||
tablestring = ''
|
||||
for i in range(len(table)):
|
||||
for j in range(len(table[0])):
|
||||
tablestring = tablestring + table[i][j] + ','
|
||||
tablestring = tablestring[:-1]
|
||||
return tablestring
|
||||
|
||||
|
||||
class ParameterMultipleInput(Parameter):
|
||||
|
||||
"""A parameter representing several data objects.
|
||||
|
||||
Its value is a string with substrings separated by semicolons,
|
||||
each of which represents the data source location of each element.
|
||||
"""
|
||||
|
||||
exported = None
|
||||
|
||||
def __init__(self, name='', description='', datatype=-1, optional=False, metadata={}):
|
||||
Parameter.__init__(self, name, description, None, optional, metadata=metadata)
|
||||
self.datatype = int(float(datatype))
|
||||
self.exported = None
|
||||
self.minNumInputs = 0
|
||||
|
||||
""" Set minimum required number of inputs for parameter
|
||||
|
||||
By default minimal number of inputs is set to 1
|
||||
|
||||
@type _minNumInputs: numeric type or None
|
||||
@param _minNumInputs: required minimum number of inputs for parameter. \
|
||||
If user will pass None as parameter, we will use default minimal number of inputs (1)
|
||||
@return: result, if the minimum number of inputs were set.
|
||||
"""
|
||||
|
||||
def setMinNumInputs(self, _minNumInputs):
|
||||
if _minNumInputs is None:
|
||||
self.minNumInputs = 0
|
||||
return True
|
||||
|
||||
if _minNumInputs < 1 and not self.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
||||
# don't allow setting negative or null number of inputs if parameter isn't optional
|
||||
return False
|
||||
|
||||
self.minNumInputs = int(_minNumInputs)
|
||||
return True
|
||||
|
||||
""" Get minimum required number of inputs for parameter
|
||||
|
||||
@return: minimum number of inputs required for this parameter
|
||||
@see: setMinNumInputs()
|
||||
"""
|
||||
|
||||
def getMinNumInputs(self):
|
||||
return self.minNumInputs
|
||||
|
||||
def getSafeExportedLayers(self):
|
||||
"""
|
||||
Returns not the value entered by the user, but a string with
|
||||
semicolon-separated filenames which contains the data of the
|
||||
selected layers, but saved in a standard format (currently
|
||||
shapefiles for vector layers and GeoTiff for raster) so that
|
||||
they can be opened by most external applications.
|
||||
|
||||
If there is a selection and QGIS is configured to use just the
|
||||
selection, it exports the layer even if it is already in a
|
||||
suitable format.
|
||||
|
||||
Works only if the layer represented by the parameter value is
|
||||
currently loaded in QGIS. Otherwise, it will not perform any
|
||||
export and return the current value string.
|
||||
|
||||
If the current value represents a layer in a suitable format,
|
||||
it does no export at all and returns that value.
|
||||
|
||||
Currently, it works just for vector layer. In the case of
|
||||
raster layers, it returns the parameter value.
|
||||
|
||||
The layers are exported just the first time the method is
|
||||
called. The method can be called several times and it will
|
||||
always return the same string, performing the export only the
|
||||
first time.
|
||||
"""
|
||||
context = dataobjects.createContext()
|
||||
if self.exported:
|
||||
return self.exported
|
||||
self.exported = self.value
|
||||
layers = self.value.split(';')
|
||||
if layers is None or len(layers) == 0:
|
||||
return self.value
|
||||
if self.datatype == dataobjects.TYPE_RASTER:
|
||||
for layerfile in layers:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(layerfile, context, False)
|
||||
if layer:
|
||||
filename = dataobjects.exportRasterLayer(layer)
|
||||
self.exported = self.exported.replace(layerfile, filename)
|
||||
return self.exported
|
||||
elif self.datatype == dataobjects.TYPE_FILE:
|
||||
return self.value
|
||||
else:
|
||||
for layerfile in layers:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(layerfile, context, False)
|
||||
if layer:
|
||||
filename = dataobjects.exportVectorLayer(layer)
|
||||
self.exported = self.exported.replace(layerfile, filename)
|
||||
return self.exported
|
||||
|
||||
def getAsString(self, value):
|
||||
if self.datatype == dataobjects.TYPE_RASTER:
|
||||
if isinstance(value, QgsRasterLayer):
|
||||
return str(value.dataProvider().dataSourceUri())
|
||||
else:
|
||||
s = str(value)
|
||||
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
|
||||
for layer in layers:
|
||||
if layer.name() == s:
|
||||
return str(layer.dataProvider().dataSourceUri())
|
||||
return s
|
||||
|
||||
if self.datatype == dataobjects.TYPE_FILE:
|
||||
return str(value)
|
||||
else:
|
||||
if isinstance(value, QgsVectorLayer):
|
||||
return str(value.source())
|
||||
else:
|
||||
s = str(value)
|
||||
if self.datatype != dataobjects.TYPE_VECTOR_ANY:
|
||||
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.datatype], False)
|
||||
else:
|
||||
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
|
||||
for layer in layers:
|
||||
if layer.name() == s:
|
||||
return str(layer.source())
|
||||
return s
|
||||
|
||||
def dataType(self):
|
||||
if self.datatype == dataobjects.TYPE_VECTOR_POINT:
|
||||
return 'points'
|
||||
elif self.datatype == dataobjects.TYPE_VECTOR_LINE:
|
||||
return 'lines'
|
||||
elif self.datatype == dataobjects.TYPE_VECTOR_POLYGON:
|
||||
return 'polygons'
|
||||
elif self.datatype == dataobjects.TYPE_RASTER:
|
||||
return 'rasters'
|
||||
elif self.datatype == dataobjects.TYPE_FILE:
|
||||
return 'files'
|
||||
else:
|
||||
return 'any vectors'
|
||||
|
||||
|
||||
class ParameterNumber(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', minValue=None, maxValue=None,
|
||||
default=None, optional=False, metadata={}):
|
||||
Parameter.__init__(self, name, description, default, optional, metadata)
|
||||
|
||||
if default is not None:
|
||||
try:
|
||||
self.default = int(str(default))
|
||||
self.isInteger = True
|
||||
except ValueError:
|
||||
self.default = float(default)
|
||||
self.isInteger = False
|
||||
else:
|
||||
self.isInteger = False
|
||||
|
||||
if minValue is not None:
|
||||
self.min = int(float(minValue)) if self.isInteger else float(minValue)
|
||||
else:
|
||||
self.min = None
|
||||
if maxValue is not None:
|
||||
self.max = int(float(maxValue)) if self.isInteger else float(maxValue)
|
||||
else:
|
||||
self.max = None
|
||||
self.value = self.default
|
||||
|
||||
def _layerVariables(self, element, alg=None):
|
||||
variables = {}
|
||||
context = createContext()
|
||||
layer = QgsProcessingUtils.mapLayerFromString(element.value, context)
|
||||
if layer is not None:
|
||||
name = element.name if alg is None else "%s_%s" % (alg.name, element.name)
|
||||
variables['@%s_minx' % name] = layer.extent().xMinimum()
|
||||
variables['@%s_miny' % name] = layer.extent().yMinimum()
|
||||
variables['@%s_maxx' % name] = layer.extent().yMaximum()
|
||||
variables['@%s_maxy' % name] = layer.extent().yMaximum()
|
||||
if isinstance(element, (ParameterRaster, OutputRaster)):
|
||||
stats = layer.dataProvider().bandStatistics(1)
|
||||
variables['@%s_avg' % name] = stats.mean
|
||||
variables['@%s_stddev' % name] = stats.stdDev
|
||||
variables['@%s_min' % name] = stats.minimumValue
|
||||
variables['@%s_max' % name] = stats.maximumValue
|
||||
return variables
|
||||
|
||||
|
||||
class ParameterRange(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', default=None, optional=False):
|
||||
Parameter.__init__(self, name, description, default, optional)
|
||||
|
||||
if default is not None:
|
||||
values = default.split(',')
|
||||
try:
|
||||
int(values[0])
|
||||
int(values[1])
|
||||
self.isInteger = True
|
||||
except:
|
||||
self.isInteger = False
|
||||
else:
|
||||
self.isInteger = False
|
||||
|
||||
|
||||
class ParameterRaster(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', optional=False, showSublayersDialog=True):
|
||||
Parameter.__init__(self, name, description, None, optional)
|
||||
self.showSublayersDialog = parseBool(showSublayersDialog)
|
||||
|
||||
|
||||
class ParameterSelection(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', options=[], default=None, isSource=False,
|
||||
multiple=False, optional=False, metadata={}):
|
||||
Parameter.__init__(self, name, description, default, optional, metadata)
|
||||
self.multiple = multiple
|
||||
isSource = parseBool(isSource)
|
||||
self.options = options
|
||||
if isSource:
|
||||
self.options = []
|
||||
layer = QgsVectorLayer(options[0], "layer", "ogr")
|
||||
if layer.isValid():
|
||||
try:
|
||||
index = resolveFieldIndex(layer, options[1])
|
||||
feats = QgsProcessingUtils.getFeatures(layer, dataobjects.createContext())
|
||||
for feature in feats:
|
||||
self.options.append(str(feature.attributes()[index]))
|
||||
except ValueError:
|
||||
pass
|
||||
elif isinstance(self.options, str):
|
||||
self.options = self.options.split(";")
|
||||
|
||||
# compute options as (value, text)
|
||||
options = []
|
||||
for i, option in enumerate(self.options):
|
||||
if option is None or isinstance(option, str):
|
||||
options.append((i, option))
|
||||
else:
|
||||
options.append((option[0], option[1]))
|
||||
self.options = options
|
||||
self.values = [option[0] for option in options]
|
||||
|
||||
self.value = None
|
||||
|
||||
@classmethod
|
||||
def fromScriptCode(self, line):
|
||||
isOptional, name, definition = _splitParameterOptions(line)
|
||||
descName = QgsProcessingParameters.descriptionFromName(name)
|
||||
if definition.lower().strip().startswith('selectionfromfile'):
|
||||
options = definition.strip()[len('selectionfromfile '):].split(';')
|
||||
return ParameterSelection(name, descName, options, isSource=True, optional=isOptional)
|
||||
elif definition.lower().strip().startswith('selection'):
|
||||
options = definition.strip()[len('selection '):].split(';')
|
||||
return ParameterSelection(name, descName, options, optional=isOptional)
|
||||
elif definition.lower().strip().startswith('multipleselectionfromfile'):
|
||||
options = definition.strip()[len('multipleselectionfromfile '):].split(';')
|
||||
return ParameterSelection(name, descName, options, isSource=True,
|
||||
multiple=True, optional=isOptional)
|
||||
elif definition.lower().strip().startswith('multipleselection'):
|
||||
options = definition.strip()[len('multipleselection '):].split(';')
|
||||
return ParameterSelection(name, descName, options, multiple=True, optional=isOptional)
|
||||
|
||||
|
||||
class ParameterEvaluationException(Exception):
|
||||
|
||||
def __init__(self, param, msg):
|
||||
Exception.__init__(msg)
|
||||
self.param = param
|
||||
|
||||
|
||||
class ParameterString(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', default=None, multiline=False,
|
||||
optional=False, evaluateExpressions=False, metadata={}):
|
||||
Parameter.__init__(self, name, description, default, optional, metadata)
|
||||
self.multiline = parseBool(multiline)
|
||||
|
||||
|
||||
class ParameterExpression(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', default=None, optional=False, parent_layer=None):
|
||||
Parameter.__init__(self, name, description, default, optional)
|
||||
self.parent_layer = parent_layer
|
||||
|
||||
|
||||
class ParameterTable(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', optional=False):
|
||||
Parameter.__init__(self, name, description, None, optional)
|
||||
self.exported = None
|
||||
|
||||
def getSafeExportedTable(self):
|
||||
"""Returns not the value entered by the user, but a string with
|
||||
a filename which contains the data of this table, but saved in
|
||||
a standard format (currently always a DBF file) so that it can
|
||||
be opened by most external applications.
|
||||
|
||||
Works only if the table represented by the parameter value is
|
||||
currently loaded in QGIS. Otherwise, it will not perform any
|
||||
export and return the current value string.
|
||||
|
||||
If the current value represents a table in a suitable format,
|
||||
it does not export at all and returns that value.
|
||||
|
||||
The table is exported just the first time the method is called.
|
||||
The method can be called several times and it will always
|
||||
return the same file, performing the export only the first
|
||||
time.
|
||||
"""
|
||||
context = dataobjects.createContext()
|
||||
if self.exported:
|
||||
return self.exported
|
||||
table = QgsProcessingUtils.mapLayerFromString(self.value, context, False)
|
||||
if table:
|
||||
self.exported = dataobjects.exportTable(table)
|
||||
else:
|
||||
self.exported = self.value
|
||||
return self.exported
|
||||
|
||||
|
||||
class ParameterTableField(Parameter):
|
||||
|
||||
"""A parameter representing a table field.
|
||||
Its value is a string that represents the name of the field.
|
||||
"""
|
||||
|
||||
DATA_TYPE_NUMBER = 0
|
||||
DATA_TYPE_STRING = 1
|
||||
DATA_TYPE_DATETIME = 2
|
||||
DATA_TYPE_ANY = -1
|
||||
|
||||
def __init__(self, name='', description='', parent=None, datatype=-1,
|
||||
optional=False, multiple=False):
|
||||
Parameter.__init__(self, name, description, None, optional)
|
||||
self.parent = parent
|
||||
self.multiple = multiple
|
||||
self.datatype = int(datatype)
|
||||
|
||||
def __str__(self):
|
||||
return self.name() + ' <' + self.__module__.split('.')[-1] + ' from ' \
|
||||
+ self.parent + '>'
|
||||
|
||||
def dataType(self):
|
||||
if self.datatype == self.DATA_TYPE_NUMBER:
|
||||
return 'numeric'
|
||||
elif self.datatype == self.DATA_TYPE_STRING:
|
||||
return 'string'
|
||||
elif self.datatype == self.DATA_TYPE_DATETIME:
|
||||
return 'datetime'
|
||||
else:
|
||||
return 'any'
|
||||
|
||||
|
||||
class ParameterVector(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', datatype=[-1],
|
||||
optional=False):
|
||||
Parameter.__init__(self, name, description, None, optional)
|
||||
if isinstance(datatype, int):
|
||||
datatype = [datatype]
|
||||
elif isinstance(datatype, str):
|
||||
datatype = [int(t) for t in datatype.split(',')]
|
||||
self.datatype = datatype
|
||||
self.exported = None
|
||||
self.allowOnlyOpenedLayers = False
|
||||
|
||||
def getSafeExportedLayer(self):
|
||||
"""Returns not the value entered by the user, but a string with
|
||||
a filename which contains the data of this layer, but saved in
|
||||
a standard format (currently always a shapefile) so that it can
|
||||
be opened by most external applications.
|
||||
|
||||
If there is a selection and QGIS is configured to use just the
|
||||
selection, if exports the layer even if it is already in a
|
||||
suitable format.
|
||||
|
||||
Works only if the layer represented by the parameter value is
|
||||
currently loaded in QGIS. Otherwise, it will not perform any
|
||||
export and return the current value string.
|
||||
|
||||
If the current value represents a layer in a suitable format,
|
||||
it does not export at all and returns that value.
|
||||
|
||||
The layer is exported just the first time the method is called.
|
||||
The method can be called several times and it will always
|
||||
return the same file, performing the export only the first
|
||||
time.
|
||||
"""
|
||||
context = dataobjects.createContext()
|
||||
|
||||
if self.exported:
|
||||
return self.exported
|
||||
layer = QgsProcessingUtils.mapLayerFromString(self.value, context, False)
|
||||
if layer:
|
||||
self.exported = dataobjects.exportVectorLayer(layer)
|
||||
else:
|
||||
self.exported = self.value
|
||||
return self.exported
|
||||
|
||||
def dataType(self):
|
||||
return dataobjects.vectorDataType(self)
|
||||
|
||||
|
||||
paramClasses = [c for c in list(sys.modules[__name__].__dict__.values()) if isclass(c) and issubclass(c, Parameter)]
|
||||
|
||||
|
||||
def getParameterFromString(s):
|
||||
# Try the parameter definitions used in description files
|
||||
@ -715,12 +195,3 @@ def getParameterFromString(s):
|
||||
param = QgsProcessingParameters.parameterFromScriptCode(s)
|
||||
if param:
|
||||
return param
|
||||
|
||||
# try Python duck-typed method
|
||||
for paramClass in paramClasses:
|
||||
try:
|
||||
param = paramClass.fromScriptCode(s)
|
||||
if param is not None:
|
||||
return param
|
||||
except:
|
||||
pass
|
||||
|
@ -55,11 +55,6 @@ from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
|
||||
from processing.gui.AlgorithmExecutor import executeIterating
|
||||
from processing.gui.Postprocessing import handleAlgorithmResults
|
||||
|
||||
from processing.core.parameters import ParameterRaster
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterExtent
|
||||
from processing.core.parameters import ParameterMultipleInput
|
||||
|
||||
from processing.tools import dataobjects
|
||||
|
||||
|
||||
|
@ -35,20 +35,10 @@ from qgis.core import (QgsApplication,
|
||||
QgsSettings,
|
||||
QgsProcessingParameterDefinition)
|
||||
from qgis.gui import QgsMessageBar
|
||||
from processing.gui.wrappers import WidgetWrapperFactory
|
||||
|
||||
from processing.gui.wrappers import WidgetWrapperFactory
|
||||
from processing.gui.BatchOutputSelectionPanel import BatchOutputSelectionPanel
|
||||
|
||||
from processing.core.parameters import ParameterFile # NOQA
|
||||
from processing.core.parameters import ParameterRaster # NOQA
|
||||
from processing.core.parameters import ParameterTable # NOQA
|
||||
from processing.core.parameters import ParameterVector # NOQA
|
||||
from processing.core.parameters import ParameterExtent # NOQA
|
||||
from processing.core.parameters import ParameterCrs # NOQA
|
||||
from processing.core.parameters import ParameterPoint # NOQA
|
||||
from processing.core.parameters import ParameterSelection # NOQA
|
||||
from processing.core.parameters import ParameterFixedTable # NOQA
|
||||
from processing.core.parameters import ParameterMultipleInput # NOQA
|
||||
from processing.tools import dataobjects
|
||||
|
||||
pluginPath = os.path.split(os.path.dirname(__file__))[0]
|
||||
|
@ -97,28 +97,13 @@ from qgis.gui import (
|
||||
from qgis.PyQt.QtCore import pyqtSignal, QObject, QVariant, Qt
|
||||
from qgis.utils import iface
|
||||
|
||||
from processing.core.ProcessingConfig import ProcessingConfig
|
||||
from processing.modeler.MultilineTextPanel import MultilineTextPanel
|
||||
|
||||
from processing.gui.NumberInputPanel import NumberInputPanel, ModellerNumberInputPanel
|
||||
from processing.gui.RangePanel import RangePanel
|
||||
from processing.modeler.MultilineTextPanel import MultilineTextPanel
|
||||
from processing.gui.PointSelectionPanel import PointSelectionPanel
|
||||
from processing.core.parameters import (ParameterBoolean,
|
||||
ParameterPoint,
|
||||
ParameterFile,
|
||||
ParameterRaster,
|
||||
ParameterVector,
|
||||
ParameterNumber,
|
||||
ParameterString,
|
||||
ParameterExpression,
|
||||
ParameterTable,
|
||||
ParameterTableField,
|
||||
ParameterExtent,
|
||||
ParameterFixedTable,
|
||||
ParameterCrs)
|
||||
from processing.core.ProcessingConfig import ProcessingConfig
|
||||
from processing.gui.FileSelectionPanel import FileSelectionPanel
|
||||
from processing.core.outputs import (OutputFile, OutputRaster, OutputVector,
|
||||
OutputString, OutputTable, OutputExtent)
|
||||
from processing.tools import dataobjects
|
||||
from processing.gui.CheckboxesPanel import CheckboxesPanel
|
||||
from processing.gui.MultipleInputPanel import MultipleInputPanel
|
||||
from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel
|
||||
@ -126,6 +111,8 @@ from processing.gui.FixedTablePanel import FixedTablePanel
|
||||
from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel
|
||||
from processing.gui.ParameterGuiUtils import getFileFilter
|
||||
|
||||
from processing.tools import dataobjects
|
||||
|
||||
DIALOG_STANDARD = 'standard'
|
||||
DIALOG_BATCH = 'batch'
|
||||
DIALOG_MODELER = 'modeler'
|
||||
|
@ -68,7 +68,7 @@ class ModelerParametersDialog(QDialog):
|
||||
def __init__(self, alg, model, algName=None):
|
||||
QDialog.__init__(self)
|
||||
self.setModal(True)
|
||||
# The algorithm to define in this dialog. It is an instance of GeoAlgorithm
|
||||
# The algorithm to define in this dialog. It is an instance of QgsProcessingModelAlgorithm
|
||||
self._alg = alg
|
||||
# The model this algorithm is going to be added to
|
||||
self.model = model
|
||||
|
@ -39,7 +39,6 @@ from qgis.core import (QgsExpressionContextUtils,
|
||||
|
||||
from qgis.PyQt.QtCore import (QCoreApplication)
|
||||
|
||||
from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||
from processing.gui.Help2Html import getHtmlFromHelpFile
|
||||
from processing.core.parameters import getParameterFromString
|
||||
from processing.core.outputs import getOutputFromString
|
||||
|
@ -7,7 +7,6 @@ PLUGIN_INSTALL(processing tests/testdata ${TEST_DATA_FILES})
|
||||
IF(ENABLE_TESTS)
|
||||
INCLUDE(UsePythonTest)
|
||||
ADD_PYTHON_TEST(ProcessingGuiTest GuiTest.py)
|
||||
ADD_PYTHON_TEST(ProcessingParametersTest ParametersTest.py)
|
||||
ADD_PYTHON_TEST(ProcessingModelerTest ModelerTest.py)
|
||||
ADD_PYTHON_TEST(ProcessingToolsTest ToolsTest.py)
|
||||
ADD_PYTHON_TEST(ProcessingQgisAlgorithmsTest QgisAlgorithmsTest.py)
|
||||
|
@ -1,124 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
***************************************************************************
|
||||
ParametersTest
|
||||
---------------------
|
||||
Date : March 2013
|
||||
Copyright : (C) 2013 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__ = 'March 2013'
|
||||
__copyright__ = '(C) 2013, Victor Olaya'
|
||||
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import sys
|
||||
from inspect import isclass
|
||||
from qgis.testing import start_app, unittest
|
||||
|
||||
from processing.core.parameters import (Parameter,
|
||||
ParameterBoolean,
|
||||
ParameterCrs,
|
||||
ParameterExtent,
|
||||
ParameterFile,
|
||||
ParameterFixedTable,
|
||||
ParameterMultipleInput,
|
||||
ParameterNumber,
|
||||
ParameterPoint,
|
||||
ParameterString,
|
||||
ParameterVector,
|
||||
ParameterTable,
|
||||
ParameterTableField,
|
||||
ParameterSelection,
|
||||
ParameterExpression,
|
||||
getParameterFromString)
|
||||
from processing.tools import dataobjects
|
||||
from processing.tests.TestData import points
|
||||
|
||||
from qgis.core import (QgsRasterLayer,
|
||||
QgsVectorLayer)
|
||||
|
||||
start_app()
|
||||
|
||||
|
||||
class ParameterSelectionTest(unittest.TestCase):
|
||||
|
||||
def testTupleOptions(self):
|
||||
options = (
|
||||
('o1', 'option1'),
|
||||
('o2', 'option2'),
|
||||
('o3', 'option3'))
|
||||
|
||||
optionalParameter = ParameterSelection('myName', 'myDesc', options, default='o1')
|
||||
self.assertEqual(optionalParameter.value, 'o1')
|
||||
optionalParameter.setValue('o2')
|
||||
self.assertEqual(optionalParameter.value, 'o2')
|
||||
|
||||
optionalParameter = ParameterSelection('myName', 'myDesc', options, default=['o1', 'o2'], multiple=True)
|
||||
self.assertEqual(optionalParameter.value, ['o1', 'o2'])
|
||||
optionalParameter.setValue(['o2'])
|
||||
self.assertEqual(optionalParameter.value, ['o2'])
|
||||
|
||||
|
||||
class TestParameterFixedTable(unittest.TestCase):
|
||||
|
||||
def testTableToString(self):
|
||||
table = [
|
||||
['a0', 'a1', 'a2'],
|
||||
['b0', 'b1', 'b2']
|
||||
]
|
||||
self.assertEqual(ParameterFixedTable.tableToString(table), 'a0,a1,a2,b0,b1,b2')
|
||||
|
||||
table = [['a0']]
|
||||
self.assertEqual(ParameterFixedTable.tableToString(table), 'a0')
|
||||
|
||||
table = [[]]
|
||||
self.assertEqual(ParameterFixedTable.tableToString(table), '')
|
||||
|
||||
|
||||
class ParameterMultipleInputTest(unittest.TestCase):
|
||||
|
||||
def testGetAsStringWhenRaster(self):
|
||||
parameter = ParameterMultipleInput('myName', 'myDesc', datatype=dataobjects.TYPE_RASTER)
|
||||
|
||||
# With Path
|
||||
self.assertEqual(parameter.getAsString('/some/path'), '/some/path')
|
||||
|
||||
# With Layer
|
||||
layer = QgsRasterLayer('/path/to/myRaster.tif', 'myRaster')
|
||||
self.assertEqual(parameter.getAsString(layer), '/path/to/myRaster.tif')
|
||||
|
||||
# TODO With Layer Name, instead of Layer object
|
||||
|
||||
def testGetAsStringWhenFile(self):
|
||||
parameter = ParameterMultipleInput('myName', 'myDesc', datatype=dataobjects.TYPE_FILE)
|
||||
self.assertEqual(parameter.getAsString('/some/path'), '/some/path')
|
||||
|
||||
def testGetAsStringWhenVector(self):
|
||||
parameter = ParameterMultipleInput('myName', 'myDesc', datatype=dataobjects.TYPE_VECTOR_ANY)
|
||||
|
||||
# With Path
|
||||
self.assertEqual(parameter.getAsString('/some/path'), '/some/path')
|
||||
|
||||
# With Layer
|
||||
layer = QgsVectorLayer('/path/to/myVector.shp', 'myVector', 'memory')
|
||||
self.assertEqual(parameter.getAsString(layer), '/path/to/myVector.shp')
|
||||
|
||||
# TODO With Layer Name, instead of Layer object
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -6,7 +6,7 @@
|
||||
##INPUT_LAYER=source
|
||||
##OUTPUT_LAYER=sink point
|
||||
|
||||
from qgis.core import QgsWkbTypes, QgsProcessingUtils
|
||||
from qgis.core import QgsWkbTypes, QgsProcessingUtils, QgsProcessingException
|
||||
|
||||
fields = INPUT_LAYER.fields()
|
||||
|
||||
@ -16,7 +16,7 @@ fields = INPUT_LAYER.fields()
|
||||
features = INPUT_LAYER.getFeatures()
|
||||
count = INPUT_LAYER.featureCount()
|
||||
if count == 0:
|
||||
raise GeoAlgorithmExecutionException('Input layer contains no features.')
|
||||
raise QgsProcessingException('Input layer contains no features.')
|
||||
|
||||
total = 100.0 / count
|
||||
|
||||
|
@ -183,113 +183,6 @@ def load(fileName, name=None, crs=None, style=None, isRaster=False):
|
||||
return qgslayer
|
||||
|
||||
|
||||
def exportVectorLayer(layer, supported=None):
|
||||
"""Takes a QgsVectorLayer and returns the filename to refer to it,
|
||||
which allows external apps which support only file-based layers to
|
||||
use it. It performs the necessary export in case the input layer
|
||||
is not in a standard format suitable for most applications, it is
|
||||
a remote one or db-based (non-file based) one, or if there is a
|
||||
selection and it should be used, exporting just the selected
|
||||
features.
|
||||
|
||||
Currently, the output is restricted to shapefiles, so anything
|
||||
that is not in a shapefile will get exported. It also export to
|
||||
a new file if the original one contains non-ascii characters.
|
||||
"""
|
||||
|
||||
supported = supported or ["shp"]
|
||||
settings = QgsSettings()
|
||||
systemEncoding = settings.value('/UI/encoding', 'System')
|
||||
|
||||
output = getTempFilename('shp')
|
||||
basename = removeInvalidChars(os.path.basename(layer.source()))
|
||||
if basename:
|
||||
if not basename.endswith("shp"):
|
||||
basename = os.path.splitext(basename)[0] + ".shp"
|
||||
output = QgsProcessingUtils.generateTempFilename(basename)
|
||||
else:
|
||||
output = getTempFilename("shp")
|
||||
useSelection = False # TODO ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
|
||||
if useSelection and layer.selectedFeatureCount() != 0:
|
||||
writer = QgsVectorFileWriter(output, systemEncoding,
|
||||
layer.fields(),
|
||||
layer.wkbType(), layer.crs())
|
||||
selection = layer.selectedFeatures()
|
||||
for feat in selection:
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
del writer
|
||||
return output
|
||||
else:
|
||||
if not os.path.splitext(layer.source())[1].lower() in supported:
|
||||
writer = QgsVectorFileWriter(
|
||||
output, systemEncoding,
|
||||
layer.fields(), layer.wkbType(),
|
||||
layer.crs()
|
||||
)
|
||||
for feat in layer.getFeatures():
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
del writer
|
||||
return output
|
||||
else:
|
||||
return layer.source()
|
||||
|
||||
|
||||
def exportRasterLayer(layer):
|
||||
"""Takes a QgsRasterLayer and returns the filename to refer to it,
|
||||
which allows external apps which support only file-based layers to
|
||||
use it. It performs the necessary export in case the input layer
|
||||
is not in a standard format suitable for most applications, it is
|
||||
a remote one or db-based (non-file based) one.
|
||||
|
||||
Currently, the output is restricted to geotiff, but not all other
|
||||
formats are exported. Only those formats not supported by GDAL are
|
||||
exported, so it is assumed that the external app uses GDAL to read
|
||||
the layer.
|
||||
"""
|
||||
|
||||
# TODO: Do the conversion here
|
||||
return str(layer.source())
|
||||
|
||||
|
||||
def exportTable(table):
|
||||
"""Takes a QgsVectorLayer and returns the filename to refer to its
|
||||
attributes table, which allows external apps which support only
|
||||
file-based layers to use it.
|
||||
|
||||
It performs the necessary export in case the input layer is not in
|
||||
a standard format suitable for most applications, it isa remote
|
||||
one or db-based (non-file based) one.
|
||||
|
||||
Currently, the output is restricted to DBF. It also export to a new
|
||||
file if the original one contains non-ascii characters.
|
||||
"""
|
||||
|
||||
settings = QgsSettings()
|
||||
systemEncoding = settings.value('/UI/encoding', 'System')
|
||||
output = getTempFilename()
|
||||
isASCII = True
|
||||
try:
|
||||
str(table.source()).decode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
isASCII = False
|
||||
isDbf = str(table.source()).endswith('dbf') \
|
||||
or str(table.source()).endswith('shp')
|
||||
if not isDbf or not isASCII:
|
||||
writer = QgsVectorFileWriter(output, systemEncoding,
|
||||
table.fields(), QgsWkbTypes.NullGeometry,
|
||||
QgsCoordinateReferenceSystem('4326'))
|
||||
for feat in table.getFeatures():
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
del writer
|
||||
return output + '.dbf'
|
||||
else:
|
||||
filename = str(table.source())
|
||||
if str(table.source()).endswith('shp'):
|
||||
return filename[:-3] + 'dbf'
|
||||
else:
|
||||
return filename
|
||||
|
||||
|
||||
def getRasterSublayer(path, param):
|
||||
|
||||
layer = QgsRasterLayer(path)
|
||||
@ -342,18 +235,3 @@ def getRasterSublayer(path, param):
|
||||
except:
|
||||
# If the layer is not a raster layer, then just return the input path
|
||||
return path
|
||||
|
||||
|
||||
def vectorDataType(obj):
|
||||
types = ''
|
||||
for t in obj.datatype:
|
||||
if t == dataobjects.TYPE_VECTOR_POINT:
|
||||
types += 'point, '
|
||||
elif t == dataobjects.TYPE_VECTOR_LINE:
|
||||
types += 'line, '
|
||||
elif t == dataobjects.TYPE_VECTOR_POLYGON:
|
||||
types += 'polygon, '
|
||||
else:
|
||||
types += 'any, '
|
||||
|
||||
return types[:-2]
|
||||
|
@ -26,10 +26,7 @@ __copyright__ = '(C) 2013, Victor Olaya'
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
try:
|
||||
import configparser
|
||||
except ImportError:
|
||||
import configparser as configparser
|
||||
import configparser
|
||||
|
||||
from qgis.core import (QgsApplication,
|
||||
QgsProcessingAlgorithm,
|
||||
@ -40,7 +37,6 @@ from qgis.core import (QgsApplication,
|
||||
QgsProcessingOutputLayerDefinition,
|
||||
QgsProject)
|
||||
from processing.core.Processing import Processing
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.gui.Postprocessing import handleAlgorithmResults
|
||||
|
||||
|
||||
|
@ -107,38 +107,3 @@ def checkMinDistance(point, index, distance, points):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
NOGEOMETRY_EXTENSIONS = [
|
||||
u'csv',
|
||||
u'dbf',
|
||||
u'ods',
|
||||
u'xlsx',
|
||||
]
|
||||
|
||||
|
||||
class TableWriter(object):
|
||||
|
||||
def __init__(self, fileName, encoding, fields):
|
||||
self.fileName = fileName
|
||||
if not self.fileName.lower().endswith('csv'):
|
||||
self.fileName += '.csv'
|
||||
|
||||
self.encoding = encoding
|
||||
if self.encoding is None or encoding == 'System':
|
||||
self.encoding = 'utf-8'
|
||||
|
||||
with open(self.fileName, 'w', newline='', encoding=self.encoding) as f:
|
||||
self.writer = csv.writer(f)
|
||||
if len(fields) != 0:
|
||||
self.writer.writerow(fields)
|
||||
|
||||
def addRecord(self, values):
|
||||
with open(self.fileName, 'a', newline='', encoding=self.encoding) as f:
|
||||
self.writer = csv.writer(f)
|
||||
self.writer.writerow(values)
|
||||
|
||||
def addRecords(self, records):
|
||||
with open(self.fileName, 'a', newline='', encoding=self.encoding) as f:
|
||||
self.writer = csv.writer(f)
|
||||
self.writer.writerows(records)
|
||||
|
Loading…
x
Reference in New Issue
Block a user