2014-07-14 14:19:09 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
***************************************************************************
|
|
|
|
Parameters.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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************
|
|
|
|
"""
|
2016-09-21 18:24:26 +02:00
|
|
|
from builtins import str
|
|
|
|
from builtins import range
|
|
|
|
from builtins import object
|
2015-06-22 20:04:08 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
__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 sys
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
import os
|
2016-09-07 14:30:20 +02:00
|
|
|
from inspect import isclass
|
|
|
|
from copy import deepcopy
|
2016-09-12 06:17:23 +02:00
|
|
|
import numbers
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-09 07:02:54 +02:00
|
|
|
from qgis.utils import iface
|
2016-04-22 10:38:48 +02:00
|
|
|
from qgis.PyQt.QtCore import QCoreApplication
|
2016-09-09 07:02:54 +02:00
|
|
|
from qgis.core import (QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsCoordinateReferenceSystem,
|
|
|
|
QgsExpressionContext, QgsExpressionContextUtils, QgsExpression, QgsExpressionContextScope)
|
|
|
|
|
2016-08-23 19:33:42 +03:00
|
|
|
from processing.tools.vector import resolveFieldIndex, features
|
2014-07-14 14:19:09 +02:00
|
|
|
from processing.tools import dataobjects
|
2016-09-13 06:45:02 +02:00
|
|
|
from processing.core.outputs import OutputNumber, OutputRaster, OutputVector
|
|
|
|
from processing.tools.dataobjects import getObject
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def parseBool(s):
|
2016-09-21 18:24:26 +02:00
|
|
|
if s is None or s == str(None).lower():
|
2014-07-14 14:19:09 +02:00
|
|
|
return None
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(s).lower() == str(True).lower()
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
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
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
def _createDescriptiveName(s):
|
|
|
|
return s.replace('_', ' ')
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2016-09-09 07:02:54 +02:00
|
|
|
def _expressionContext():
|
|
|
|
context = QgsExpressionContext()
|
|
|
|
context.appendScope(QgsExpressionContextUtils.globalScope())
|
|
|
|
context.appendScope(QgsExpressionContextUtils.projectScope())
|
|
|
|
processingScope = QgsExpressionContextScope()
|
|
|
|
layers = dataobjects.getAllLayers()
|
|
|
|
for layer in layers:
|
|
|
|
name = layer.name()
|
|
|
|
processingScope.setVariable('%s_minx' % name, layer.extent().xMinimum())
|
|
|
|
processingScope.setVariable('%s_miny' % name, layer.extent().yMinimum())
|
|
|
|
processingScope.setVariable('%s_maxx' % name, layer.extent().xMaximum())
|
|
|
|
processingScope.setVariable('%s_maxy' % name, layer.extent().yMaximum())
|
|
|
|
if isinstance(layer, QgsRasterLayer):
|
|
|
|
cellsize = (layer.extent().xMaximum()
|
|
|
|
- layer.extent().xMinimum()) / layer.width()
|
|
|
|
processingScope.setVariable('%s_cellsize' % name, cellsize)
|
|
|
|
|
|
|
|
layers = dataobjects.getRasterLayers()
|
|
|
|
for layer in layers:
|
|
|
|
for i in range(layer.bandCount()):
|
|
|
|
stats = layer.dataProvider().bandStatistics(i + 1)
|
|
|
|
processingScope.setVariable('%s_band%i_avg' % (name, i + 1), stats.mean)
|
|
|
|
processingScope.setVariable('%s_band%i_stddev' % (name, i + 1), stats.stdDev)
|
|
|
|
processingScope.setVariable('%s_band%i_min' % (name, i + 1), stats.minimumValue)
|
|
|
|
processingScope.setVariable('%s_band%i_max' % (name, i + 1), stats.maximumValue)
|
|
|
|
|
|
|
|
extent = iface.mapCanvas().extent()
|
|
|
|
processingScope.setVariable('canvasextent_minx', extent.xMinimum())
|
|
|
|
processingScope.setVariable('canvasextent_miny', extent.yMinimum())
|
|
|
|
processingScope.setVariable('canvasextent_maxx', extent.xMaximum())
|
|
|
|
processingScope.setVariable('canvasextent_maxy', extent.yMaximum())
|
|
|
|
|
|
|
|
extent = iface.mapCanvas().fullExtent()
|
|
|
|
processingScope.setVariable('fullextent_minx', extent.xMinimum())
|
|
|
|
processingScope.setVariable('fullextent_miny', extent.yMinimum())
|
|
|
|
processingScope.setVariable('fullextent_maxx', extent.xMaximum())
|
|
|
|
processingScope.setVariable('fullextent_maxy', extent.yMaximum())
|
|
|
|
context.appendScope(processingScope)
|
|
|
|
return context
|
|
|
|
|
2016-09-14 09:49:04 +02:00
|
|
|
def _resolveLayers(value):
|
|
|
|
layers = dataobjects.getAllLayers()
|
|
|
|
if value:
|
|
|
|
inputlayers = value.split(';')
|
|
|
|
for i, inputlayer in enumerate(inputlayers):
|
|
|
|
for layer in layers:
|
|
|
|
if layer.name() == inputlayer:
|
|
|
|
inputlayers[i] = layer.source()
|
|
|
|
break
|
|
|
|
return ";".join(inputlayers)
|
|
|
|
|
2016-09-09 07:02:54 +02:00
|
|
|
class Parameter:
|
2015-08-22 14:29:41 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
"""
|
|
|
|
Base class for all parameters that a geoalgorithm might
|
|
|
|
take as input.
|
|
|
|
"""
|
|
|
|
|
2016-09-09 10:48:51 +02:00
|
|
|
default_metadata = {}
|
|
|
|
|
2016-08-23 10:44:57 +02:00
|
|
|
def __init__(self, name='', description='', default=None, optional=False,
|
|
|
|
metadata={}):
|
2014-07-14 14:19:09 +02:00
|
|
|
self.name = name
|
|
|
|
self.description = description
|
2015-12-16 17:33:43 +01:00
|
|
|
self.default = default
|
|
|
|
self.value = default
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
self.isAdvanced = False
|
|
|
|
|
|
|
|
# A hidden parameter can be used to set a hard-coded value.
|
|
|
|
# It can be used as any other parameter, but it will not be
|
|
|
|
# shown to the user
|
|
|
|
self.hidden = False
|
2015-11-08 23:12:13 +01:00
|
|
|
|
|
|
|
self.optional = parseBool(optional)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2016-08-23 10:44:57 +02:00
|
|
|
# TODO: make deep copy and deep update
|
2016-09-07 14:30:20 +02:00
|
|
|
self.metadata = deepcopy(self.default_metadata)
|
|
|
|
self.metadata.update(deepcopy(metadata))
|
2016-08-23 10:44:57 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
def setValue(self, obj):
|
|
|
|
"""
|
|
|
|
Sets the value of the parameter.
|
|
|
|
|
|
|
|
Returns true if the value passed is correct for the type
|
|
|
|
of parameter.
|
|
|
|
"""
|
2015-10-29 14:37:05 +01:00
|
|
|
if obj is None:
|
|
|
|
if not self.optional:
|
|
|
|
return False
|
|
|
|
self.value = None
|
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj)
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
|
2015-12-16 17:33:43 +01:00
|
|
|
def setDefaultValue(self):
|
|
|
|
"""
|
|
|
|
Sets the value of the parameter to the default one
|
|
|
|
|
|
|
|
Returns true if the default value is correct for the type
|
|
|
|
of parameter.
|
|
|
|
"""
|
|
|
|
return self.setValue(self.default)
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
def __str__(self):
|
2014-12-07 12:50:54 +02:00
|
|
|
return u'{} <{}>'.format(self.name, self.__class__.__name__)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
|
|
|
"""
|
|
|
|
Returns the value of this parameter as it should have been
|
|
|
|
entered in the console if calling an algorithm using the
|
|
|
|
Processing.runalg() method.
|
|
|
|
"""
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(self.value)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2014-11-25 16:55:31 +02:00
|
|
|
def typeName(self):
|
|
|
|
return self.__class__.__name__.replace('Parameter', '').lower()
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def todict(self):
|
2016-09-03 22:46:19 +02:00
|
|
|
o = self.__dict__
|
|
|
|
del o['metadata']
|
|
|
|
return o
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2014-10-03 14:44:01 +03:00
|
|
|
def tr(self, string, context=''):
|
|
|
|
if context == '':
|
|
|
|
context = 'Parameter'
|
2014-10-12 19:07:56 +02:00
|
|
|
return QCoreApplication.translate(context, string)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def wrapper(self, dialog, row=0, col=0):
|
|
|
|
wrapper = self.metadata.get('widget_wrapper', None)
|
|
|
|
# wrapper metadata should be a class path
|
|
|
|
if isinstance(wrapper, basestring):
|
|
|
|
tokens = wrapper.split('.')
|
|
|
|
mod = __import__('.'.join(tokens[:-1]), fromlist=[tokens[-1]])
|
|
|
|
wrapper = getattr(mod, tokens[-1])
|
|
|
|
# or directly a class object
|
|
|
|
if isclass(wrapper):
|
|
|
|
wrapper = wrapper(self, dialog, row, col)
|
|
|
|
# or a wrapper instance
|
|
|
|
return wrapper
|
2016-09-09 07:02:54 +02:00
|
|
|
|
|
|
|
def evaluate(self, alg):
|
|
|
|
pass
|
2016-09-12 06:17:23 +02:00
|
|
|
|
|
|
|
def evaluateForModeler(self, value, model):
|
|
|
|
return value
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterBoolean(Parameter):
|
|
|
|
|
2016-08-23 10:46:22 +02:00
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.BooleanWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
|
|
|
def __init__(self, name='', description='', default=None, optional=False, metadata={}):
|
|
|
|
Parameter.__init__(self, name, description, parseBool(default), optional, metadata)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
if value is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
2015-12-16 17:33:43 +01:00
|
|
|
self.value = None
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2016-09-21 18:24:26 +02:00
|
|
|
if isinstance(value, str):
|
|
|
|
self.value = str(value).lower() == str(True).lower()
|
2014-07-14 14:19:09 +02:00
|
|
|
else:
|
|
|
|
self.value = bool(value)
|
|
|
|
return True
|
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'boolean '
|
|
|
|
return '##' + self.name + '=' + param_type + str(self.default)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
if definition.startswith("boolean"):
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
default = definition.strip()[len('boolean') + 1:]
|
|
|
|
if default:
|
|
|
|
param = ParameterBoolean(name, descName, default)
|
|
|
|
else:
|
|
|
|
param = ParameterBoolean(name, descName)
|
|
|
|
param.optional = isOptional
|
|
|
|
return param
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
class ParameterCrs(Parameter):
|
|
|
|
|
2016-08-24 15:23:25 +02:00
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.CrsWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
|
|
|
def __init__(self, name='', description='', default=None, optional=False, metadata={}):
|
2015-01-22 14:38:47 +01:00
|
|
|
'''The value is a string that uniquely identifies the
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
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
|
2015-01-22 14:38:47 +01:00
|
|
|
of other authorities or user defined projections).'''
|
2016-08-24 15:23:25 +02:00
|
|
|
Parameter.__init__(self, name, description, default, optional, metadata)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, value):
|
2016-09-08 09:57:18 +02:00
|
|
|
if not bool(value):
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
2016-09-08 09:57:18 +02:00
|
|
|
self.value = None
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
|
2016-09-08 09:57:18 +02:00
|
|
|
if isinstance(value, QgsCoordinateReferenceSystem):
|
|
|
|
self.value = value.authid()
|
|
|
|
return True
|
|
|
|
if isinstance(value, QgsMapLayer):
|
|
|
|
self.value = value.crs().authid()
|
|
|
|
return True
|
|
|
|
try:
|
|
|
|
layer = dataobjects.getObjectFromUri(value)
|
|
|
|
if layer is not None:
|
|
|
|
self.value = layer.crs().authid()
|
|
|
|
return True
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
# TODO: check it is a valid authid
|
2016-09-08 09:57:18 +02:00
|
|
|
self.value = value
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return '"' + str(self.value) + '"'
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'crs '
|
|
|
|
return '##' + self.name + '=' + param_type + str(self.default)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
if definition.startswith("crs"):
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
default = definition.strip()[len('crs') + 1:]
|
|
|
|
if default:
|
|
|
|
return ParameterCrs(name, descName, default, isOptional)
|
|
|
|
else:
|
|
|
|
return ParameterCrs(name, descName, None, isOptional)
|
2015-11-10 20:21:10 +00:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterDataObject(Parameter):
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
|
|
|
if self.value is None:
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(None)
|
2014-07-14 14:19:09 +02:00
|
|
|
else:
|
2016-09-21 18:24:26 +02:00
|
|
|
s = dataobjects.normalizeLayerSource(str(self.value))
|
2015-06-22 20:04:08 +02:00
|
|
|
s = '"%s"' % s
|
2015-06-23 08:37:06 +02:00
|
|
|
return s
|
2016-09-14 09:49:04 +02:00
|
|
|
|
|
|
|
def evaluate(self, alg):
|
|
|
|
self.value = _resolveLayers(self.value)
|
2014-10-03 14:44:01 +03:00
|
|
|
|
2015-08-22 14:29:41 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterExtent(Parameter):
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.ExtentWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
USE_MIN_COVERING_EXTENT = 'USE_MIN_COVERING_EXTENT'
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def __init__(self, name='', description='', default=None, optional=True):
|
2015-12-16 17:33:43 +01:00
|
|
|
Parameter.__init__(self, name, description, default, optional)
|
2014-07-14 14:19:09 +02:00
|
|
|
# The value is a string in the form "xmin, xmax, ymin, ymax"
|
|
|
|
|
2016-09-08 09:57:18 +02:00
|
|
|
def setValue(self, value):
|
|
|
|
if value is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
|
|
|
self.value = None
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2016-09-08 09:57:18 +02:00
|
|
|
if isinstance(value, QgsMapLayer):
|
|
|
|
rect = value.extent()
|
|
|
|
self.value = '{},{},{},{}'.format(
|
|
|
|
rect.xMinimum(), rect.xMaximum(), rect.yMinimum(), rect.yMaximum())
|
|
|
|
return True
|
|
|
|
|
|
|
|
try:
|
|
|
|
layer = dataobjects.getObjectFromUri(value)
|
|
|
|
if layer is not None:
|
|
|
|
rect = layer.extent()
|
|
|
|
self.value = '{},{},{},{}'.format(
|
|
|
|
rect.xMinimum(), rect.xMaximum(), rect.yMinimum(), rect.yMaximum())
|
|
|
|
return True
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
tokens = str(value).split(',')
|
2014-07-14 14:19:09 +02:00
|
|
|
if len(tokens) != 4:
|
|
|
|
return False
|
|
|
|
try:
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
float(tokens[0])
|
|
|
|
float(tokens[1])
|
|
|
|
float(tokens[2])
|
|
|
|
float(tokens[3])
|
2016-09-08 09:57:18 +02:00
|
|
|
self.value = value
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return '"' + str(self.value) + '"'
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'extent'
|
|
|
|
return '##' + self.name + '=' + param_type
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
if definition.startswith("extent"):
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
default = definition.strip()[len('extent') + 1:] or None
|
|
|
|
return ParameterExtent(name, descName, default, isOptional)
|
2016-06-02 12:12:38 +02:00
|
|
|
|
2016-09-09 07:02:54 +02:00
|
|
|
def evaluate(self, alg):
|
|
|
|
if self.optional and not bool(self.value):
|
|
|
|
self.value = self.getMinCoveringExtent()
|
|
|
|
|
|
|
|
def getMinCoveringExtent(self, alg):
|
|
|
|
first = True
|
|
|
|
found = False
|
|
|
|
for param in alg.parameters:
|
|
|
|
if param.value:
|
|
|
|
if isinstance(param, (ParameterRaster, ParameterVector)):
|
|
|
|
if isinstance(param.value, (QgsRasterLayer,
|
|
|
|
QgsVectorLayer)):
|
|
|
|
layer = param.value
|
|
|
|
else:
|
|
|
|
layer = dataobjects.getObject(param.value)
|
|
|
|
if layer:
|
|
|
|
found = True
|
|
|
|
self.addToRegion(layer, first)
|
|
|
|
first = False
|
|
|
|
elif isinstance(param, ParameterMultipleInput):
|
|
|
|
layers = param.value.split(';')
|
|
|
|
for layername in layers:
|
|
|
|
layer = dataobjects.getObject(layername)
|
|
|
|
if layer:
|
|
|
|
found = True
|
|
|
|
self.addToRegion(layer, first)
|
|
|
|
first = False
|
|
|
|
if found:
|
|
|
|
return '{},{},{},{}'.format(
|
|
|
|
self.xmin, self.xmax, self.ymin, self.ymax)
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
def addToRegion(self, layer, first):
|
|
|
|
if first:
|
|
|
|
self.xmin = layer.extent().xMinimum()
|
|
|
|
self.xmax = layer.extent().xMaximum()
|
|
|
|
self.ymin = layer.extent().yMinimum()
|
|
|
|
self.ymax = layer.extent().yMaximum()
|
|
|
|
else:
|
|
|
|
self.xmin = min(self.xmin, layer.extent().xMinimum())
|
|
|
|
self.xmax = max(self.xmax, layer.extent().xMaximum())
|
|
|
|
self.ymin = min(self.ymin, layer.extent().yMinimum())
|
|
|
|
self.ymax = max(self.ymax, layer.extent().yMaximum())
|
|
|
|
|
2014-10-03 14:44:01 +03:00
|
|
|
|
2016-02-22 17:24:21 +02:00
|
|
|
class ParameterPoint(Parameter):
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.PointWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2016-02-22 17:24:21 +02:00
|
|
|
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"
|
|
|
|
|
|
|
|
def setValue(self, text):
|
|
|
|
if text is None:
|
|
|
|
if not self.optional:
|
|
|
|
return False
|
|
|
|
self.value = None
|
|
|
|
return True
|
|
|
|
|
2016-09-21 18:24:26 +02:00
|
|
|
tokens = str(text).split(',')
|
2016-02-22 17:24:21 +02:00
|
|
|
if len(tokens) != 2:
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
float(tokens[0])
|
|
|
|
float(tokens[1])
|
|
|
|
self.value = text
|
|
|
|
return True
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return '"' + str(self.value) + '"'
|
2016-02-22 17:24:21 +02:00
|
|
|
|
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'point'
|
|
|
|
return '##' + self.name + '=' + param_type
|
2016-02-22 17:24:21 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
if definition.startswith("point"):
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
default = definition.strip()[len('point') + 1:] or None
|
|
|
|
return ParameterPoint(name, descName, default, isOptional)
|
|
|
|
|
2016-02-22 17:24:21 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterFile(Parameter):
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.FileWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
def __init__(self, name='', description='', isFolder=False, optional=True, ext=None):
|
2015-12-23 10:57:59 +01:00
|
|
|
Parameter.__init__(self, name, description, None, parseBool(optional))
|
2014-07-14 14:19:09 +02:00
|
|
|
self.ext = ext
|
|
|
|
self.isFolder = parseBool(isFolder)
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return '"' + str(self.value) + '"'
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, obj):
|
2015-12-16 17:33:43 +01:00
|
|
|
if obj is None or obj.strip() == '':
|
2014-07-14 14:19:09 +02:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
2015-12-23 10:57:59 +01:00
|
|
|
self.value = None if obj is None else obj.strip()
|
2015-12-16 17:33:43 +01:00
|
|
|
return True
|
|
|
|
|
|
|
|
if self.ext is not None and obj != '' and not obj.endswith(self.ext):
|
|
|
|
return False
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj)
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
|
2014-11-25 16:55:31 +02:00
|
|
|
def typeName(self):
|
|
|
|
if self.isFolder:
|
|
|
|
return 'directory'
|
|
|
|
else:
|
|
|
|
return 'file'
|
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
2015-11-06 14:02:11 +01:00
|
|
|
if self.isFolder:
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type += 'folder'
|
2015-11-06 14:02:11 +01:00
|
|
|
else:
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type += 'file'
|
|
|
|
return '##' + self.name + '=' + param_type
|
2015-11-06 14:02:11 +01:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
if definition.startswith("file") or definition.startswith("folder"):
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
return ParameterFile(name, descName, definition.startswith("folder"), isOptional)
|
|
|
|
|
2014-10-03 14:44:01 +03:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterFixedTable(Parameter):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2014-07-18 09:58:41 +02:00
|
|
|
def __init__(self, name='', description='', numRows=3,
|
2015-11-04 09:42:22 +01:00
|
|
|
cols=['value'], fixedNumOfRows=False, optional=False):
|
2015-12-16 17:33:43 +01:00
|
|
|
Parameter.__init__(self, name, description, None, optional)
|
2014-07-14 14:19:09 +02:00
|
|
|
self.cols = cols
|
2016-09-21 18:24:26 +02:00
|
|
|
if isinstance(cols, str):
|
2014-07-14 14:19:09 +02:00
|
|
|
self.cols = self.cols.split(";")
|
|
|
|
self.numRows = int(numRows)
|
2015-11-08 23:12:13 +01:00
|
|
|
self.fixedNumOfRows = parseBool(fixedNumOfRows)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, obj):
|
2015-10-29 14:37:05 +01:00
|
|
|
if obj is None:
|
|
|
|
if not self.optional:
|
|
|
|
return False
|
|
|
|
self.value = None
|
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
# TODO: check that it contains a correct number of elements
|
2016-09-21 18:24:26 +02:00
|
|
|
if isinstance(obj, str):
|
2014-07-14 14:19:09 +02:00
|
|
|
self.value = obj
|
|
|
|
else:
|
|
|
|
self.value = ParameterFixedTable.tableToString(obj)
|
|
|
|
return True
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return '"' + str(self.value) + '"'
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
@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
|
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
if definition.startswith("point"):
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
default = definition.strip()[len('point') + 1:] or None
|
|
|
|
return ParameterPoint(name, descName, default, isOptional)
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
class ParameterMultipleInput(ParameterDataObject):
|
2015-08-22 14:29:41 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
"""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.
|
|
|
|
"""
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.MultipleInputWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
exported = None
|
|
|
|
|
|
|
|
def __init__(self, name='', description='', datatype=-1, optional=False):
|
2015-12-16 17:33:43 +01:00
|
|
|
ParameterDataObject.__init__(self, name, description, None, optional)
|
2014-07-18 09:58:41 +02:00
|
|
|
self.datatype = int(float(datatype))
|
2014-07-14 14:19:09 +02:00
|
|
|
self.exported = None
|
2016-03-23 01:15:38 +03:00
|
|
|
self.minNumInputs = 0
|
2016-03-22 02:24:27 +03:00
|
|
|
|
|
|
|
""" Set minimum required number of inputs for parameter
|
|
|
|
|
|
|
|
By default minimal number of inputs is set to 1
|
|
|
|
|
2016-03-23 15:01:49 +03:00
|
|
|
@type _minNumInputs: numeric type or None
|
2016-03-22 02:24:27 +03:00
|
|
|
@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.
|
|
|
|
"""
|
2016-03-23 05:43:59 +03:00
|
|
|
|
2016-03-22 02:24:27 +03:00
|
|
|
def setMinNumInputs(self, _minNumInputs):
|
|
|
|
if _minNumInputs is None:
|
2016-03-23 01:15:38 +03:00
|
|
|
self.minNumInputs = 0
|
|
|
|
return True
|
2016-03-22 02:24:27 +03:00
|
|
|
|
|
|
|
if _minNumInputs < 1 and not self.optional:
|
2016-05-31 02:55:01 +02:00
|
|
|
# don't allow to set negative or null number of inputs if parameter isn't optional
|
2016-03-22 02:24:27 +03:00
|
|
|
return False
|
|
|
|
|
2016-03-23 15:01:49 +03:00
|
|
|
self.minNumInputs = int(_minNumInputs)
|
2016-03-23 01:15:38 +03:00
|
|
|
return True
|
2016-03-22 02:24:27 +03:00
|
|
|
|
|
|
|
""" Get minimum required number of inputs for parameter
|
|
|
|
|
|
|
|
@return: minimum number of inputs required for this parameter
|
|
|
|
@see: setMinNumInputs()
|
|
|
|
"""
|
2016-03-23 05:43:59 +03:00
|
|
|
|
2016-03-22 02:24:27 +03:00
|
|
|
def getMinNumInputs(self):
|
|
|
|
return self.minNumInputs
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, obj):
|
|
|
|
self.exported = None
|
|
|
|
if obj is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
2014-07-14 14:19:09 +02:00
|
|
|
return False
|
2015-10-29 14:37:05 +01:00
|
|
|
self.value = None
|
|
|
|
return True
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
if isinstance(obj, list):
|
|
|
|
if len(obj) == 0:
|
|
|
|
if self.optional:
|
2016-03-23 01:15:38 +03:00
|
|
|
self.value = None
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
2016-03-22 02:24:27 +03:00
|
|
|
# prevent setting value if we didn't provide required minimal number of inputs
|
2016-03-23 15:01:49 +03:00
|
|
|
elif len(obj) < self.minNumInputs:
|
2016-03-22 02:24:27 +03:00
|
|
|
return False
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
self.value = ";".join([self.getAsString(lay) for lay in obj])
|
|
|
|
return True
|
|
|
|
else:
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj)
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
def getSafeExportedLayers(self):
|
2016-03-22 02:24:27 +03:00
|
|
|
"""
|
|
|
|
Returns not the value entered by the user, but a string with
|
2014-07-14 14:19:09 +02:00
|
|
|
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.
|
|
|
|
"""
|
|
|
|
|
|
|
|
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
|
2016-08-23 19:33:42 +03:00
|
|
|
if self.datatype == dataobjects.TYPE_RASTER:
|
2014-07-14 14:19:09 +02:00
|
|
|
for layerfile in layers:
|
|
|
|
layer = dataobjects.getObjectFromUri(layerfile, False)
|
|
|
|
if layer:
|
|
|
|
filename = dataobjects.exportRasterLayer(layer)
|
|
|
|
self.exported = self.exported.replace(layerfile, filename)
|
|
|
|
return self.exported
|
2016-08-23 19:33:42 +03:00
|
|
|
elif self.datatype == dataobjects.TYPE_FILE:
|
2014-07-14 14:19:09 +02:00
|
|
|
return self.value
|
|
|
|
else:
|
|
|
|
for layerfile in layers:
|
|
|
|
layer = dataobjects.getObjectFromUri(layerfile, False)
|
|
|
|
if layer:
|
|
|
|
filename = dataobjects.exportVectorLayer(layer)
|
|
|
|
self.exported = self.exported.replace(layerfile, filename)
|
|
|
|
return self.exported
|
|
|
|
|
|
|
|
def getAsString(self, value):
|
2016-08-23 19:33:42 +03:00
|
|
|
if self.datatype == dataobjects.TYPE_RASTER:
|
2014-07-14 14:19:09 +02:00
|
|
|
if isinstance(value, QgsRasterLayer):
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(value.dataProvider().dataSourceUri())
|
2014-07-14 14:19:09 +02:00
|
|
|
else:
|
2016-09-21 18:24:26 +02:00
|
|
|
s = str(value)
|
2014-07-14 14:19:09 +02:00
|
|
|
layers = dataobjects.getRasterLayers()
|
|
|
|
for layer in layers:
|
|
|
|
if layer.name() == s:
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(layer.dataProvider().dataSourceUri())
|
2014-07-14 14:19:09 +02:00
|
|
|
return s
|
2016-03-22 02:24:27 +03:00
|
|
|
|
2016-08-23 19:33:42 +03:00
|
|
|
if self.datatype == dataobjects.TYPE_FILE:
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(value)
|
2014-07-14 14:19:09 +02:00
|
|
|
else:
|
|
|
|
if isinstance(value, QgsVectorLayer):
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(value.source())
|
2014-07-14 14:19:09 +02:00
|
|
|
else:
|
2016-09-21 18:24:26 +02:00
|
|
|
s = str(value)
|
2014-07-14 14:19:09 +02:00
|
|
|
layers = dataobjects.getVectorLayers([self.datatype])
|
|
|
|
for layer in layers:
|
|
|
|
if layer.name() == s:
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(layer.source())
|
2014-07-14 14:19:09 +02:00
|
|
|
return s
|
|
|
|
|
|
|
|
def getFileFilter(self):
|
2016-08-23 19:33:42 +03:00
|
|
|
if self.datatype == dataobjects.TYPE_RASTER:
|
2014-07-14 14:19:09 +02:00
|
|
|
exts = dataobjects.getSupportedOutputRasterLayerExtensions()
|
2016-08-23 19:33:42 +03:00
|
|
|
elif self.datatype == dataobjects.TYPE_FILE:
|
2014-10-03 14:44:01 +03:00
|
|
|
return self.tr('All files (*.*)', 'ParameterMultipleInput')
|
2014-07-14 14:19:09 +02:00
|
|
|
else:
|
|
|
|
exts = dataobjects.getSupportedOutputVectorLayerExtensions()
|
|
|
|
for i in range(len(exts)):
|
2014-10-03 21:56:24 +03:00
|
|
|
exts[i] = self.tr('%s files(*.%s)', 'ParameterMultipleInput') % (exts[i].upper(), exts[i].lower())
|
2014-07-14 14:19:09 +02:00
|
|
|
return ';;'.join(exts)
|
|
|
|
|
2014-11-25 16:55:31 +02:00
|
|
|
def dataType(self):
|
2016-08-23 19:33:42 +03:00
|
|
|
if self.datatype == dataobjects.TYPE_VECTOR_POINT:
|
2014-11-25 16:55:31 +02:00
|
|
|
return 'points'
|
2016-08-23 19:33:42 +03:00
|
|
|
elif self.datatype == dataobjects.TYPE_VECTOR_LINE:
|
2014-11-25 16:55:31 +02:00
|
|
|
return 'lines'
|
2016-08-23 19:33:42 +03:00
|
|
|
elif self.datatype == dataobjects.TYPE_VECTOR_POLYGON:
|
2014-11-25 16:55:31 +02:00
|
|
|
return 'polygons'
|
2016-08-23 19:33:42 +03:00
|
|
|
elif self.datatype == dataobjects.TYPE_RASTER:
|
2014-11-25 16:55:31 +02:00
|
|
|
return 'rasters'
|
2016-08-23 19:33:42 +03:00
|
|
|
elif self.datatype == dataobjects.TYPE_FILE:
|
2014-11-25 16:55:31 +02:00
|
|
|
return 'files'
|
|
|
|
else:
|
|
|
|
return 'any vectors'
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
2016-08-23 19:33:42 +03:00
|
|
|
if self.datatype == dataobjects.TYPE_RASTER:
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type += 'multiple raster'
|
2016-08-23 19:33:42 +03:00
|
|
|
if self.datatype == dataobjects.TYPE_FILE:
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type += 'multiple file'
|
2015-11-06 14:02:11 +01:00
|
|
|
else:
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type += 'multiple vector'
|
|
|
|
return '##' + self.name + '=' + param_type
|
2015-08-22 14:29:41 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
if definition.lower().strip() == 'multiple raster':
|
|
|
|
return ParameterMultipleInput(name, descName,
|
2016-09-07 14:30:20 +02:00
|
|
|
dataobjects.TYPE_RASTER, isOptional)
|
2016-09-05 12:59:21 +02:00
|
|
|
elif definition.lower().strip() == 'multiple vector':
|
|
|
|
return ParameterMultipleInput(name, definition,
|
|
|
|
dataobjects.TYPE_VECTOR_ANY, isOptional)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-14 09:49:04 +02:00
|
|
|
def evaluate(self, alg):
|
|
|
|
self.value = _resolveLayers(self.value)
|
|
|
|
|
2015-11-10 20:21:10 +00:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterNumber(Parameter):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.NumberWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def __init__(self, name='', description='', minValue=None, maxValue=None,
|
2015-12-16 17:33:43 +01:00
|
|
|
default=None, optional=False):
|
|
|
|
Parameter.__init__(self, name, description, default, optional)
|
|
|
|
|
|
|
|
if default is not None:
|
|
|
|
try:
|
2016-09-21 18:24:26 +02:00
|
|
|
self.default = int(str(default))
|
2015-12-16 17:33:43 +01:00
|
|
|
self.isInteger = True
|
2016-02-09 20:07:32 +01:00
|
|
|
except ValueError:
|
2015-12-16 17:33:43 +01:00
|
|
|
self.default = float(default)
|
|
|
|
self.isInteger = False
|
|
|
|
else:
|
2014-07-14 14:19:09 +02:00
|
|
|
self.isInteger = False
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2014-08-06 14:59:35 +03:00
|
|
|
if minValue is not None:
|
2014-08-22 11:30:49 +02:00
|
|
|
self.min = int(float(minValue)) if self.isInteger else float(minValue)
|
2014-08-06 14:59:35 +03:00
|
|
|
else:
|
|
|
|
self.min = None
|
|
|
|
if maxValue is not None:
|
2014-08-22 11:30:49 +02:00
|
|
|
self.max = int(float(maxValue)) if self.isInteger else float(maxValue)
|
2014-08-06 14:59:35 +03:00
|
|
|
else:
|
|
|
|
self.max = None
|
2015-12-16 17:33:43 +01:00
|
|
|
self.value = self.default
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, n):
|
|
|
|
if n is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
2015-12-16 17:33:43 +01:00
|
|
|
self.value = None
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2016-09-09 07:02:54 +02:00
|
|
|
if isinstance(n, basestring):
|
|
|
|
try:
|
|
|
|
v = self._evaluate(n)
|
2016-09-09 10:48:51 +02:00
|
|
|
self.value = float(v)
|
2016-09-09 07:02:54 +02:00
|
|
|
return True
|
|
|
|
except:
|
2016-09-12 06:17:23 +02:00
|
|
|
raise
|
2016-09-09 07:02:54 +02:00
|
|
|
return False
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
if float(n) - int(float(n)) == 0:
|
|
|
|
value = int(float(n))
|
|
|
|
else:
|
|
|
|
value = float(n)
|
|
|
|
if self.min is not None:
|
|
|
|
if value < self.min:
|
|
|
|
return False
|
|
|
|
if self.max is not None:
|
|
|
|
if value > self.max:
|
|
|
|
return False
|
|
|
|
self.value = value
|
|
|
|
return True
|
|
|
|
except:
|
2016-09-12 06:17:23 +02:00
|
|
|
raise
|
2016-09-09 07:02:54 +02:00
|
|
|
return False
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'number'
|
|
|
|
return '##' + self.name + '=' + param_type + str(self.default)
|
2015-11-06 14:02:11 +01:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
if definition.lower().strip().startswith('number'):
|
|
|
|
default = definition.strip()[len('number') + 1:] or None
|
|
|
|
return ParameterNumber(name, descName, default=default, optional=isOptional)
|
2016-09-09 07:02:54 +02:00
|
|
|
|
2016-09-12 06:17:23 +02:00
|
|
|
def _evaluate(self, value):
|
|
|
|
exp = QgsExpression(value)
|
2016-09-09 07:02:54 +02:00
|
|
|
if exp.hasParserError():
|
|
|
|
raise ValueError(self.tr("Error in parameter expression: ") + exp.parserErrorString())
|
|
|
|
result = exp.evaluate(_expressionContext())
|
|
|
|
if exp.hasEvalError():
|
|
|
|
raise ValueError("Error evaluating parameter expression: " + exp.evalErrorString())
|
|
|
|
return result
|
|
|
|
|
|
|
|
def evaluate(self, alg):
|
2016-09-14 09:49:04 +02:00
|
|
|
if isinstance(self.value, basestring) and bool(self.value):
|
2016-09-12 06:17:23 +02:00
|
|
|
self.value = self._evaluate(self.value)
|
|
|
|
|
2016-09-13 06:45:02 +02:00
|
|
|
def _layerVariables(self, element, alg=None):
|
|
|
|
variables = {}
|
|
|
|
layer = getObject(element.value)
|
|
|
|
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
|
|
|
|
|
2016-09-12 06:17:23 +02:00
|
|
|
def evaluateForModeler(self, value, model):
|
|
|
|
if isinstance(value, numbers.Number):
|
|
|
|
return value
|
|
|
|
variables = {}
|
|
|
|
for param in model.parameters:
|
|
|
|
if isinstance(param, ParameterNumber):
|
|
|
|
variables["@" + param.name] = param.value
|
2016-09-13 06:45:02 +02:00
|
|
|
if isinstance(param, (ParameterRaster, ParameterVector)):
|
|
|
|
variables.update(self._layerVariables(param))
|
|
|
|
|
2016-09-12 06:17:23 +02:00
|
|
|
for alg in model.algs.values():
|
|
|
|
for out in alg.algorithm.outputs:
|
|
|
|
if isinstance(out, OutputNumber):
|
|
|
|
variables["@%s_%s" % (alg.name, out.name)] = out.value
|
2016-09-13 06:45:02 +02:00
|
|
|
if isinstance(out, (OutputRaster, OutputVector)):
|
|
|
|
variables.update(self._layerVariables(out, alg))
|
2016-09-12 06:17:23 +02:00
|
|
|
for k,v in variables.iteritems():
|
|
|
|
value = value.replace(k,unicode(v))
|
|
|
|
|
|
|
|
return value
|
2016-09-09 07:02:54 +02:00
|
|
|
|
|
|
|
def expressionContext(self):
|
|
|
|
return _expressionContext()
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
|
|
|
if self.value is None:
|
|
|
|
return str(None)
|
|
|
|
if isinstance(self.value, basestring):
|
2016-09-09 10:48:51 +02:00
|
|
|
return '"%s"' + self.value
|
2016-09-09 07:02:54 +02:00
|
|
|
return str(self.value)
|
|
|
|
|
|
|
|
|
2015-11-10 20:21:10 +00:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterRange(Parameter):
|
|
|
|
|
2015-12-16 17:33:43 +01:00
|
|
|
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:
|
2014-11-15 13:13:51 +02:00
|
|
|
self.isInteger = False
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
def setValue(self, text):
|
|
|
|
if text is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
|
|
|
self.value = None
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
tokens = text.split(',')
|
|
|
|
if len(tokens) != 2:
|
|
|
|
return False
|
|
|
|
try:
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
float(tokens[0])
|
|
|
|
float(tokens[1])
|
2014-07-14 14:19:09 +02:00
|
|
|
self.value = text
|
|
|
|
return True
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return '"' + str(self.value) + '"' if self.value is not None else str(None)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
class ParameterRaster(ParameterDataObject):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.RasterWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
def __init__(self, name='', description='', optional=False, showSublayersDialog=True):
|
2015-12-16 17:33:43 +01:00
|
|
|
ParameterDataObject.__init__(self, name, description, None, optional)
|
2015-01-20 12:36:46 +01:00
|
|
|
self.showSublayersDialog = parseBool(showSublayersDialog)
|
2014-07-14 14:19:09 +02:00
|
|
|
self.exported = None
|
|
|
|
|
|
|
|
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 geotiff file) so that it
|
|
|
|
can be opened by most external applications.
|
|
|
|
|
|
|
|
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.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if self.exported:
|
|
|
|
return self.exported
|
|
|
|
layer = dataobjects.getObjectFromUri(self.value, False)
|
|
|
|
if layer:
|
|
|
|
self.exported = dataobjects.exportRasterLayer(layer)
|
|
|
|
else:
|
|
|
|
self.exported = self.value
|
|
|
|
return self.exported
|
|
|
|
|
|
|
|
def setValue(self, obj):
|
|
|
|
self.exported = None
|
|
|
|
if obj is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
2014-07-14 14:19:09 +02:00
|
|
|
return False
|
2015-10-29 14:37:05 +01:00
|
|
|
self.value = None
|
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
if isinstance(obj, QgsRasterLayer):
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj.dataProvider().dataSourceUri())
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
else:
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj)
|
2015-06-23 08:37:06 +02:00
|
|
|
return True
|
2015-01-22 20:53:45 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
def getFileFilter(self):
|
|
|
|
exts = dataobjects.getSupportedOutputRasterLayerExtensions()
|
|
|
|
for i in range(len(exts)):
|
2014-10-03 21:56:24 +03:00
|
|
|
exts[i] = self.tr('%s files(*.%s)', 'ParameterRaster') % (exts[i].upper(), exts[i].lower())
|
2014-07-14 14:19:09 +02:00
|
|
|
return ';;'.join(exts)
|
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'raster'
|
|
|
|
return '##' + self.name + '=' + param_type
|
2015-11-06 14:02:11 +01:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
if definition.lower().strip().startswith('raster'):
|
|
|
|
return ParameterRaster(name, descName, optional=isOptional)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
class ParameterSelection(Parameter):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.SelectionWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2015-12-23 10:57:59 +01:00
|
|
|
def __init__(self, name='', description='', options=[], default=None, isSource=False,
|
2015-11-04 09:42:22 +01:00
|
|
|
optional=False):
|
2015-12-16 17:33:43 +01:00
|
|
|
Parameter.__init__(self, name, description, default, optional)
|
2015-11-08 23:12:13 +01:00
|
|
|
isSource = parseBool(isSource)
|
2014-07-14 14:19:09 +02:00
|
|
|
self.options = options
|
2015-05-21 09:05:10 +02:00
|
|
|
if isSource:
|
|
|
|
self.options = []
|
|
|
|
layer = QgsVectorLayer(options[0], "layer", "ogr")
|
|
|
|
if layer.isValid():
|
|
|
|
try:
|
|
|
|
index = resolveFieldIndex(layer, options[1])
|
|
|
|
feats = features(layer)
|
|
|
|
for feature in feats:
|
2016-09-21 18:24:26 +02:00
|
|
|
self.options.append(str(feature.attributes()[index]))
|
2015-05-21 09:05:10 +02:00
|
|
|
except ValueError:
|
|
|
|
pass
|
2016-09-21 18:24:26 +02:00
|
|
|
elif isinstance(self.options, str):
|
2014-07-14 14:19:09 +02:00
|
|
|
self.options = self.options.split(";")
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2015-12-23 10:57:59 +01:00
|
|
|
if default is not None:
|
|
|
|
try:
|
|
|
|
self.default = int(default)
|
|
|
|
except:
|
|
|
|
self.default = 0
|
|
|
|
self.value = self.default
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, n):
|
|
|
|
if n is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
2015-12-16 17:33:43 +01:00
|
|
|
self.value = 0
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
try:
|
|
|
|
n = int(n)
|
|
|
|
self.value = n
|
|
|
|
return True
|
|
|
|
except:
|
|
|
|
return False
|
2014-07-18 09:58:41 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(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)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
|
2016-09-09 07:02:54 +02:00
|
|
|
class ParameterEvaluationException(Exception):
|
|
|
|
|
|
|
|
def __init__(self, param, msg):
|
|
|
|
Exception.__init__(msg)
|
|
|
|
self.param = param
|
|
|
|
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterString(Parameter):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.StringWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
NEWLINE = '\n'
|
|
|
|
ESCAPED_NEWLINE = '\\n'
|
|
|
|
|
2015-12-23 10:57:59 +01:00
|
|
|
def __init__(self, name='', description='', default=None, multiline=False,
|
2016-05-23 14:05:03 +03:00
|
|
|
optional=False, evaluateExpressions=False):
|
2015-12-16 17:33:43 +01:00
|
|
|
Parameter.__init__(self, name, description, default, optional)
|
2015-09-22 15:35:26 +02:00
|
|
|
self.multiline = parseBool(multiline)
|
2016-05-23 14:05:03 +03:00
|
|
|
self.evaluateExpressions = parseBool(evaluateExpressions)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, obj):
|
2016-09-14 09:49:04 +02:00
|
|
|
if not bool(obj):
|
2015-12-23 10:57:59 +01:00
|
|
|
if not self.optional:
|
2015-11-04 09:42:22 +01:00
|
|
|
return False
|
2015-12-23 10:57:59 +01:00
|
|
|
self.value = None
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj).replace(
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
ParameterString.ESCAPED_NEWLINE,
|
|
|
|
ParameterString.NEWLINE
|
|
|
|
)
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return ('"' + str(self.value.replace(ParameterString.NEWLINE,
|
|
|
|
ParameterString.ESCAPED_NEWLINE)) + '"'
|
|
|
|
if self.value is not None else str(None))
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'string'
|
|
|
|
return '##' + self.name + '=' + param_type + self.default
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
if definition.lower().strip().startswith('string'):
|
|
|
|
default = definition.strip()[len('string') + 1:]
|
|
|
|
if default:
|
|
|
|
return ParameterString(name, descName, default, optional=isOptional)
|
|
|
|
else:
|
|
|
|
return ParameterString(name, descName, optional=isOptional)
|
|
|
|
elif definition.lower().strip().startswith('longstring'):
|
|
|
|
default = definition.strip()[len('longstring') + 1:]
|
|
|
|
if default:
|
|
|
|
return ParameterString(name, descName, default, multiline=True, optional=isOptional)
|
|
|
|
else:
|
|
|
|
return ParameterString(name, descName, multiline=True, optional=isOptional)
|
2016-09-09 07:02:54 +02:00
|
|
|
|
|
|
|
def evaluate(self, alg):
|
2016-09-14 09:49:04 +02:00
|
|
|
if isinstance(self.value, basestring) and bool(self.value) and self.evaluateExpressions:
|
|
|
|
exp = QgsExpression(self.value)
|
|
|
|
if exp.hasParserError():
|
|
|
|
raise ValueError(self.tr("Error in parameter expression: ") + exp.parserErrorString())
|
|
|
|
result = exp.evaluate(_expressionContext())
|
|
|
|
if exp.hasEvalError():
|
|
|
|
raise ValueError("Error evaluating parameter expression: " + exp.evalErrorString())
|
|
|
|
self.value = result
|
2016-09-09 07:02:54 +02:00
|
|
|
|
|
|
|
def expressionContext(self):
|
|
|
|
return _expressionContext()
|
2015-11-10 20:21:10 +00:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterTable(ParameterDataObject):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.TableWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def __init__(self, name='', description='', optional=False):
|
2015-12-16 17:33:43 +01:00
|
|
|
ParameterDataObject.__init__(self, name, description, None, optional)
|
2014-07-14 14:19:09 +02:00
|
|
|
self.exported = None
|
|
|
|
|
|
|
|
def setValue(self, obj):
|
|
|
|
self.exported = None
|
|
|
|
if obj is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
2014-07-14 14:19:09 +02:00
|
|
|
return False
|
2015-10-29 14:37:05 +01:00
|
|
|
self.value = None
|
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
if isinstance(obj, QgsVectorLayer):
|
2016-09-21 18:24:26 +02:00
|
|
|
source = str(obj.source())
|
2014-07-14 14:19:09 +02:00
|
|
|
self.value = source
|
|
|
|
return True
|
|
|
|
else:
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj)
|
2015-05-22 17:35:23 +02:00
|
|
|
layers = dataobjects.getTables()
|
2014-07-14 14:19:09 +02:00
|
|
|
for layer in layers:
|
2015-05-22 17:35:23 +02:00
|
|
|
if layer.name() == self.value or layer.source() == self.value:
|
2016-09-21 18:24:26 +02:00
|
|
|
source = str(layer.source())
|
2014-07-14 14:19:09 +02:00
|
|
|
self.value = source
|
|
|
|
return True
|
2016-09-21 18:24:26 +02:00
|
|
|
val = str(obj)
|
2014-07-14 14:19:09 +02:00
|
|
|
self.value = val
|
|
|
|
return os.path.exists(self.value)
|
|
|
|
|
|
|
|
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.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if self.exported:
|
|
|
|
return self.exported
|
|
|
|
table = dataobjects.getObjectFromUri(self.value, False)
|
|
|
|
if table:
|
|
|
|
self.exported = dataobjects.exportTable(table)
|
|
|
|
else:
|
|
|
|
self.exported = self.value
|
|
|
|
return self.exported
|
|
|
|
|
|
|
|
def getFileFilter(self):
|
|
|
|
exts = ['csv', 'dbf']
|
|
|
|
for i in range(len(exts)):
|
2014-10-03 21:56:24 +03:00
|
|
|
exts[i] = self.tr('%s files(*.%s)', 'ParameterTable') % (exts[i].upper(), exts[i].lower())
|
2014-07-14 14:19:09 +02:00
|
|
|
return ';;'.join(exts)
|
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'table'
|
|
|
|
return '##' + self.name + '=' + param_type
|
2015-11-06 14:02:11 +01:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
if definition.lower().strip().startswith('table'):
|
|
|
|
return ParameterTable(name, descName, isOptional)
|
|
|
|
|
2014-10-03 14:44:01 +03:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterTableField(Parameter):
|
2016-06-07 11:11:59 +10:00
|
|
|
|
2016-06-02 12:12:38 +02:00
|
|
|
"""A parameter representing a table field.
|
|
|
|
Its value is a string that represents the name of the field.
|
|
|
|
"""
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.TableFieldWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
DATA_TYPE_NUMBER = 0
|
|
|
|
DATA_TYPE_STRING = 1
|
|
|
|
DATA_TYPE_ANY = -1
|
|
|
|
|
|
|
|
def __init__(self, name='', description='', parent=None, datatype=-1,
|
2016-09-09 10:48:51 +02:00
|
|
|
optional=False, multiple = False):
|
2015-12-16 17:33:43 +01:00
|
|
|
Parameter.__init__(self, name, description, None, optional)
|
2014-07-14 14:19:09 +02:00
|
|
|
self.parent = parent
|
2016-09-15 10:00:40 +02:00
|
|
|
self.multiple = multiple
|
2014-07-14 14:19:09 +02:00
|
|
|
self.datatype = int(datatype)
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return '"' + str(self.value) + '"' if self.value is not None else str(None)
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, value):
|
2016-09-09 10:48:51 +02:00
|
|
|
if not bool(value):
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
|
|
|
self.value = None
|
|
|
|
return True
|
2016-09-09 10:48:51 +02:00
|
|
|
if isinstance(value, list):
|
|
|
|
if not self.multiple and len(value) > 1:
|
|
|
|
return False
|
|
|
|
self.value = ";".join(value)
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
self.value = str(value)
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return self.name + ' <' + self.__module__.split('.')[-1] + ' from ' \
|
|
|
|
+ self.parent + '>'
|
|
|
|
|
2014-11-25 16:55:31 +02:00
|
|
|
def dataType(self):
|
|
|
|
if self.datatype == self.DATA_TYPE_NUMBER:
|
|
|
|
return 'numeric'
|
|
|
|
elif self.datatype == self.DATA_TYPE_STRING:
|
|
|
|
return 'string'
|
|
|
|
else:
|
|
|
|
return 'any'
|
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'field'
|
|
|
|
return '##' + self.name + '=' + param_type + self.parent
|
2015-11-06 14:02:11 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
if definition.lower().strip().startswith('field'):
|
|
|
|
if definition.lower().strip().startswith('field number'):
|
|
|
|
parent = definition.strip()[len('field number') + 1:]
|
|
|
|
datatype = ParameterTableField.DATA_TYPE_NUMBER
|
|
|
|
elif definition.lower().strip().startswith('field string'):
|
|
|
|
parent = definition.strip()[len('field string') + 1:]
|
|
|
|
datatype = ParameterTableField.DATA_TYPE_STRING
|
|
|
|
else:
|
|
|
|
parent = definition.strip()[len('field') + 1:]
|
|
|
|
datatype = ParameterTableField.DATA_TYPE_ANY
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
return ParameterTableField(name, descName, parent, datatype, isOptional)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class ParameterVector(ParameterDataObject):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
default_metadata = {
|
|
|
|
'widget_wrapper': 'processing.gui.wrappers.VectorWidgetWrapper'
|
|
|
|
}
|
|
|
|
|
2016-08-08 15:37:33 +03:00
|
|
|
def __init__(self, name='', description='', datatype=[-1],
|
2014-07-14 14:19:09 +02:00
|
|
|
optional=False):
|
2015-12-16 17:33:43 +01:00
|
|
|
ParameterDataObject.__init__(self, name, description, None, optional)
|
2016-08-08 15:37:33 +03:00
|
|
|
if isinstance(datatype, int):
|
|
|
|
datatype = [datatype]
|
2016-09-21 18:24:26 +02:00
|
|
|
elif isinstance(datatype, str):
|
2016-08-08 15:37:33 +03:00
|
|
|
datatype = [int(t) for t in datatype.split(',')]
|
|
|
|
self.datatype = datatype
|
2014-07-14 14:19:09 +02:00
|
|
|
self.exported = None
|
2016-09-07 14:30:20 +02:00
|
|
|
self.allowOnlyOpenedLayers = False
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
def setValue(self, obj):
|
|
|
|
self.exported = None
|
|
|
|
if obj is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
2014-07-14 14:19:09 +02:00
|
|
|
return False
|
2015-10-29 14:37:05 +01:00
|
|
|
self.value = None
|
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
if isinstance(obj, QgsVectorLayer):
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj.source())
|
2014-07-14 14:19:09 +02:00
|
|
|
return True
|
|
|
|
else:
|
2016-09-21 18:24:26 +02:00
|
|
|
self.value = str(obj)
|
2015-06-23 08:37:06 +02:00
|
|
|
return True
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
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.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if self.exported:
|
|
|
|
return self.exported
|
|
|
|
layer = dataobjects.getObjectFromUri(self.value, False)
|
|
|
|
if layer:
|
|
|
|
self.exported = dataobjects.exportVectorLayer(layer)
|
|
|
|
else:
|
|
|
|
self.exported = self.value
|
|
|
|
return self.exported
|
|
|
|
|
|
|
|
def getFileFilter(self):
|
|
|
|
exts = dataobjects.getSupportedOutputVectorLayerExtensions()
|
|
|
|
for i in range(len(exts)):
|
2014-10-03 21:56:24 +03:00
|
|
|
exts[i] = self.tr('%s files(*.%s)', 'ParameterVector') % (exts[i].upper(), exts[i].lower())
|
2014-07-30 19:27:23 +03:00
|
|
|
return ';;'.join(exts)
|
2014-11-25 16:55:31 +02:00
|
|
|
|
|
|
|
def dataType(self):
|
2016-08-23 19:33:42 +03:00
|
|
|
return dataobjects.vectorDataType(self)
|
2015-01-09 17:23:49 +01:00
|
|
|
|
2015-11-06 14:02:11 +01:00
|
|
|
def getAsScriptCode(self):
|
2016-06-02 12:12:38 +02:00
|
|
|
param_type = ''
|
|
|
|
if self.optional:
|
|
|
|
param_type += 'optional '
|
|
|
|
param_type += 'vector'
|
|
|
|
return '##' + self.name + '=' + param_type
|
2015-11-06 14:02:11 +01:00
|
|
|
|
2016-09-05 12:59:21 +02:00
|
|
|
@classmethod
|
|
|
|
def fromScriptCode(self, line):
|
|
|
|
isOptional, name, definition = _splitParameterOptions(line)
|
|
|
|
descName = _createDescriptiveName(name)
|
|
|
|
if definition.lower().strip() == 'vector':
|
|
|
|
return ParameterVector(name, descName,
|
|
|
|
[dataobjects.TYPE_VECTOR_ANY], isOptional)
|
|
|
|
elif definition.lower().strip() == 'vector point':
|
|
|
|
return ParameterVector(name, descName,
|
|
|
|
[dataobjects.TYPE_VECTOR_POINT], isOptional)
|
|
|
|
elif definition.lower().strip() == 'vector line':
|
|
|
|
return ParameterVector(name, descName,
|
|
|
|
[dataobjects.TYPE_VECTOR_LINE], isOptional)
|
|
|
|
elif definition.lower().strip() == 'vector polygon':
|
|
|
|
return ParameterVector(name, descName,
|
|
|
|
[dataobjects.TYPE_VECTOR_POLYGON], isOptional)
|
2015-01-09 17:23:49 +01:00
|
|
|
|
|
|
|
class ParameterGeometryPredicate(Parameter):
|
|
|
|
|
|
|
|
predicates = ('intersects',
|
|
|
|
'contains',
|
|
|
|
'disjoint',
|
|
|
|
'equals',
|
|
|
|
'touches',
|
|
|
|
'overlaps',
|
|
|
|
'within',
|
|
|
|
'crosses')
|
|
|
|
|
|
|
|
def __init__(self, name='', description='', left=None, right=None,
|
|
|
|
optional=False, enabledPredicates=None):
|
2015-12-23 10:57:59 +01:00
|
|
|
Parameter.__init__(self, name, description, None, optional)
|
2015-01-09 17:23:49 +01:00
|
|
|
self.left = left
|
|
|
|
self.right = right
|
|
|
|
self.value = None
|
|
|
|
self.enabledPredicates = enabledPredicates
|
|
|
|
if self.enabledPredicates is None:
|
|
|
|
self.enabledPredicates = self.predicates
|
|
|
|
|
|
|
|
def getValueAsCommandLineParameter(self):
|
2016-09-21 18:24:26 +02:00
|
|
|
return str(self.value)
|
2015-01-09 17:23:49 +01:00
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
if value is None:
|
2015-10-29 14:37:05 +01:00
|
|
|
if not self.optional:
|
|
|
|
return False
|
|
|
|
self.value = None
|
|
|
|
return True
|
2015-12-16 17:33:43 +01:00
|
|
|
elif len(value) == 0 and not self.optional:
|
|
|
|
return False
|
|
|
|
|
2016-09-21 18:24:26 +02:00
|
|
|
if isinstance(value, str):
|
2016-03-21 04:58:12 +01:00
|
|
|
self.value = value.split(';') # relates to ModelerAlgorithm.resolveValue
|
2015-01-09 17:23:49 +01:00
|
|
|
else:
|
|
|
|
self.value = value
|
|
|
|
return True
|
2016-09-05 12:59:21 +02:00
|
|
|
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
paramClasses = [c for c in sys.modules[__name__].__dict__.values() if isclass(c) and issubclass(c, Parameter)]
|
2016-09-05 12:59:21 +02:00
|
|
|
|
|
|
|
def getParameterFromString(s):
|
2016-09-07 14:30:20 +02:00
|
|
|
# Try the parameter definitions used in description files
|
2016-09-05 12:59:21 +02:00
|
|
|
if '|' in s:
|
2016-09-08 10:30:30 +02:00
|
|
|
isAdvanced = False
|
|
|
|
if s.startswith("*"):
|
|
|
|
s = s[1:]
|
|
|
|
isAdvanced = True
|
2016-09-05 12:59:21 +02:00
|
|
|
tokens = s.split("|")
|
|
|
|
params = [t if unicode(t) != unicode(None) else None for t in tokens[1:]]
|
2016-09-12 06:17:23 +02:00
|
|
|
try:
|
|
|
|
clazz = getattr(sys.modules[__name__], tokens[0])
|
|
|
|
param = clazz(*params)
|
|
|
|
param.isAdvanced = isAdvanced
|
|
|
|
except:
|
|
|
|
return None
|
2016-09-07 14:30:20 +02:00
|
|
|
else: # try script syntax
|
2016-09-05 12:59:21 +02:00
|
|
|
for paramClass in paramClasses:
|
|
|
|
try:
|
2016-09-07 14:30:20 +02:00
|
|
|
param = paramClass.fromScriptCode(s)
|
2016-09-05 12:59:21 +02:00
|
|
|
if param is not None:
|
|
|
|
return param
|
|
|
|
except AttributeError:
|
|
|
|
pass
|