2013-01-26 23:55:14 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
***************************************************************************
|
|
|
|
GeoAlgorithmExecutionException.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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************
|
|
|
|
"""
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2015-06-22 07:44:21 +02:00
|
|
|
|
2013-01-26 23:55:14 +01:00
|
|
|
__author__ = 'Victor Olaya'
|
|
|
|
__date__ = 'August 2012'
|
|
|
|
__copyright__ = '(C) 2012, Victor Olaya'
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-01-26 23:55:14 +01:00
|
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-01-26 23:55:14 +01:00
|
|
|
__revision__ = '$Format:%H$'
|
|
|
|
|
|
|
|
import os.path
|
|
|
|
import traceback
|
2015-06-22 07:44:21 +02:00
|
|
|
import subprocess
|
2013-01-26 23:55:14 +01:00
|
|
|
import copy
|
2013-10-01 20:52:22 +03: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
|
|
|
from PyQt4.QtGui import QIcon
|
2015-06-22 07:44:21 +02:00
|
|
|
from PyQt4.QtCore import QCoreApplication, QSettings
|
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
|
|
|
from qgis.core import QGis, QgsRasterFileWriter
|
|
|
|
|
2013-08-12 20:44:27 +02:00
|
|
|
from processing.core.ProcessingLog import ProcessingLog
|
2013-10-01 20:52:22 +03:00
|
|
|
from processing.core.ProcessingConfig import ProcessingConfig
|
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
|
|
|
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
2015-07-03 08:18:16 +02:00
|
|
|
from processing.core.parameters import ParameterRaster, ParameterVector, ParameterMultipleInput, ParameterTable, Parameter
|
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
|
|
|
from processing.core.outputs import OutputVector, OutputRaster, OutputTable, OutputHTML, Output
|
2014-04-17 01:41:25 +02:00
|
|
|
from processing.algs.gdal.GdalUtils import GdalUtils
|
2013-10-01 20:52:22 +03:00
|
|
|
from processing.tools import dataobjects, vector
|
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
|
|
|
from processing.tools.system import setTempOutput
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
|
|
|
|
class GeoAlgorithm:
|
2014-07-13 17:16:24 +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
|
|
|
_icon = QIcon(os.path.dirname(__file__) + '/../images/alg.png')
|
2012-09-15 18:25:25 +03:00
|
|
|
|
|
|
|
def __init__(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
# Parameters needed by the algorithm
|
2012-09-15 18:25:25 +03:00
|
|
|
self.parameters = list()
|
2013-10-01 20:52:22 +03:00
|
|
|
|
|
|
|
# Outputs generated by the algorithm
|
2012-09-15 18:25:25 +03:00
|
|
|
self.outputs = list()
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-27 00:31:20 +02:00
|
|
|
# Name and group for normal toolbox display
|
2013-10-01 20:52:22 +03:00
|
|
|
self.name = ''
|
|
|
|
self.group = ''
|
|
|
|
|
|
|
|
# The crs taken from input layers (if possible), and used when
|
|
|
|
# loading output layers
|
2012-09-15 18:25:25 +03:00
|
|
|
self.crs = None
|
2013-10-01 20:52:22 +03:00
|
|
|
|
|
|
|
# Change any of the following if your algorithm should not
|
|
|
|
# appear in the toolbox or modeler
|
2012-09-15 18:25:25 +03:00
|
|
|
self.showInToolbox = True
|
|
|
|
self.showInModeler = True
|
2013-10-24 15:26:39 +02:00
|
|
|
#if true, will show only loaded layers in parameters dialog.
|
|
|
|
#Also, if True, the algorithm does not run on the modeler
|
2014-04-23 15:36:45 +03:00
|
|
|
#or batch ptocessing interface
|
2013-07-23 18:57:06 +02:00
|
|
|
self.allowOnlyOpenedLayers = False
|
2013-10-01 20:52:22 +03:00
|
|
|
|
|
|
|
# False if it should not be run a a batch process
|
2013-02-21 22:12:01 +01:00
|
|
|
self.canRunInBatchMode = True
|
2013-10-01 20:52:22 +03:00
|
|
|
|
|
|
|
# To be set by the provider when it loads the algorithm
|
2012-09-15 18:25:25 +03:00
|
|
|
self.provider = None
|
2013-09-17 12:33:57 +02:00
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
# If the algorithm is run as part of a model, the parent model
|
|
|
|
# can be set in this variable, to allow for customized
|
|
|
|
# behaviour, in case some operations should be run differently
|
|
|
|
# when running as part of a model
|
2013-09-14 17:41:08 +02:00
|
|
|
self.model = None
|
2012-09-15 18:25:25 +03:00
|
|
|
|
|
|
|
self.defineCharacteristics()
|
2013-03-26 14:15:12 +01:00
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
def getCopy(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns a new instance of this algorithm, ready to be used
|
|
|
|
for being executed.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
newone = copy.copy(self)
|
|
|
|
newone.parameters = copy.deepcopy(self.parameters)
|
|
|
|
newone.outputs = copy.deepcopy(self.outputs)
|
|
|
|
return newone
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
# methods to overwrite when creating a custom geoalgorithm
|
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
def getIcon(self):
|
2014-07-11 14:21:53 +02:00
|
|
|
return self._icon
|
2012-12-10 00:12:07 +01:00
|
|
|
|
2012-12-07 21:11:56 +01:00
|
|
|
@staticmethod
|
|
|
|
def getDefaultIcon():
|
2014-07-11 14:21:53 +02:00
|
|
|
return GeoAlgorithm._icon
|
2012-09-15 18:25:25 +03:00
|
|
|
|
2014-04-19 00:48:56 +02:00
|
|
|
def help(self):
|
|
|
|
"""Returns the help with the description of this algorithm.
|
2014-12-07 12:50:54 +02:00
|
|
|
It returns a tuple boolean, string. IF the boolean value is True,
|
|
|
|
it means that the string contains the actual description. If False,
|
|
|
|
it is an url or path to a file where the description is stored.
|
|
|
|
In both cases, the string or the content of the file have to be HTML,
|
|
|
|
ready to be set into the help display component.
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2014-04-19 00:48:56 +02:00
|
|
|
Returns None if there is no help file available.
|
2014-06-13 09:03:15 +02:00
|
|
|
|
2014-12-07 12:50:54 +02:00
|
|
|
The default implementation looks for an HTML page in the QGIS
|
|
|
|
documentation site taking into account QGIS version.
|
2013-10-01 20:52:22 +03:00
|
|
|
"""
|
2014-06-13 09:03:15 +02:00
|
|
|
|
2014-12-07 12:50:54 +02:00
|
|
|
qgsVersion = QGis.QGIS_VERSION_INT
|
|
|
|
major = qgsVersion / 10000
|
2015-05-21 15:43:47 +02:00
|
|
|
minor = (qgsVersion - major * 10000) / 100
|
2014-12-07 12:50:54 +02:00
|
|
|
if minor % 2 == 1:
|
|
|
|
qgsVersion = 'testing'
|
|
|
|
else:
|
|
|
|
qgsVersion = '{}.{}'.format(major, minor)
|
|
|
|
|
|
|
|
providerName = self.provider.getName().lower()
|
|
|
|
groupName = self.group.lower()
|
|
|
|
groupName = groupName.replace('[', '').replace(']', '').replace(' - ', '_')
|
|
|
|
groupName = groupName.replace(' ', '_')
|
|
|
|
cmdLineName = self.commandLineName()
|
|
|
|
algName = cmdLineName[cmdLineName.find(':') + 1:].lower()
|
|
|
|
validChars = \
|
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
|
|
|
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
|
2014-12-07 12:50:54 +02:00
|
|
|
safeGroupName = ''.join(c for c in groupName if c in validChars)
|
|
|
|
safeAlgName = ''.join(c for c in algName if c in validChars)
|
|
|
|
|
|
|
|
helpUrl = 'http://docs.qgis.org/{}/en/docs/user_manual/processing_algs/{}/{}/{}.html'.format(qgsVersion, providerName, safeGroupName, safeAlgName)
|
|
|
|
return False, helpUrl
|
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
|
2015-07-09 14:41:00 +02:00
|
|
|
def processAlgorithm(self, progress):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Here goes the algorithm itself.
|
|
|
|
|
2012-12-07 21:11:56 +01:00
|
|
|
There is no return value from this method.
|
2013-10-01 20:52:22 +03:00
|
|
|
A GeoAlgorithmExecutionException should be raised in case
|
|
|
|
something goes wrong.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
pass
|
|
|
|
|
|
|
|
def defineCharacteristics(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Here is where the parameters and outputs should be defined.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
pass
|
|
|
|
|
|
|
|
def getCustomParametersDialog(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""If the algorithm has a custom parameters dialog, it should
|
|
|
|
be returned here, ready to be executed.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
return None
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
def getCustomModelerParametersDialog(self, modelAlg, algIndex=None):
|
|
|
|
"""If the algorithm has a custom parameters dialog when called
|
|
|
|
from the modeler, it should be returned here, ready to be
|
|
|
|
executed.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
return None
|
|
|
|
|
|
|
|
def getParameterDescriptions(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns a dict with param names as keys and detailed
|
|
|
|
descriptions of each param as value. These descriptions are
|
|
|
|
used as tool tips in the parameters dialog.
|
|
|
|
|
|
|
|
If a description does not exist, the parameter's
|
|
|
|
human-readable name is used.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
descs = {}
|
|
|
|
return descs
|
|
|
|
|
|
|
|
def checkBeforeOpeningParametersDialog(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""If there is any check to perform before the parameters
|
|
|
|
dialog is opened, it should be done here.
|
|
|
|
|
|
|
|
This method returns an error message string if there is any
|
|
|
|
problem (for instance, an external app not configured yet),
|
|
|
|
or None if the parameters dialog can be opened.
|
|
|
|
|
|
|
|
Note that this check should also be done in the
|
|
|
|
processAlgorithm method, since algorithms can be called without
|
|
|
|
opening the parameters dialog.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
return None
|
|
|
|
|
|
|
|
def checkParameterValuesBeforeExecuting(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""If there is any check to do before launching the execution
|
|
|
|
of the algorithm, it should be done here.
|
|
|
|
|
|
|
|
If values are not correct, a message should be returned
|
|
|
|
explaining the problem.
|
|
|
|
|
|
|
|
This check is called from the parameters dialog, and also when
|
|
|
|
calling from the console.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
return None
|
2013-01-26 14:16:39 +01:00
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
# =========================================================
|
2013-01-26 14:16:39 +01:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
def execute(self, progress=None, model=None):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""The method to use to call a processing algorithm.
|
2013-09-17 12:33:57 +02:00
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
Although the body of the algorithm is in processAlgorithm(),
|
|
|
|
it should be called using this method, since it performs
|
|
|
|
some additional operations.
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2014-06-20 12:13:03 +02:00
|
|
|
Raises a GeoAlgorithmExecutionException in case anything goes
|
2013-10-01 20:52:22 +03:00
|
|
|
wrong.
|
|
|
|
"""
|
2013-09-14 17:41:08 +02:00
|
|
|
self.model = model
|
2012-09-15 18:25:25 +03:00
|
|
|
try:
|
2013-01-27 19:17:53 +01:00
|
|
|
self.setOutputCRS()
|
2013-01-21 23:05:17 +01:00
|
|
|
self.resolveTemporaryOutputs()
|
2015-07-03 08:18:16 +02:00
|
|
|
self.resolveDataObjects()
|
2013-01-21 23:05:17 +01:00
|
|
|
self.checkOutputFileExtensions()
|
|
|
|
self.runPreExecutionScript(progress)
|
2013-01-26 14:16:39 +01:00
|
|
|
self.processAlgorithm(progress)
|
2014-06-20 12:13:03 +02:00
|
|
|
progress.setPercentage(100)
|
2013-01-21 23:05:17 +01:00
|
|
|
self.convertUnsupportedFormats(progress)
|
2013-08-28 17:06:40 +03:00
|
|
|
self.runPostExecutionScript(progress)
|
2015-07-09 14:41:00 +02:00
|
|
|
except GeoAlgorithmExecutionException as gaee:
|
2013-08-12 20:44:27 +02:00
|
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, gaee.msg)
|
2012-09-15 18:25:25 +03:00
|
|
|
raise gaee
|
2015-07-09 14:41:00 +02:00
|
|
|
except Exception as e:
|
2013-10-01 20:52:22 +03:00
|
|
|
# If something goes wrong and is not caught in the
|
|
|
|
# algorithm, we catch it here and wrap it
|
2014-10-03 14:44:01 +03:00
|
|
|
lines = [self.tr('Uncaught error while executing algorithm')]
|
2012-09-15 18:25:25 +03:00
|
|
|
errstring = traceback.format_exc()
|
2013-10-01 20:52:22 +03:00
|
|
|
newline = errstring.find('\n')
|
2012-09-15 18:25:25 +03:00
|
|
|
if newline != -1:
|
|
|
|
lines.append(errstring[:newline])
|
|
|
|
else:
|
|
|
|
lines.append(errstring)
|
2013-10-01 20:52:22 +03:00
|
|
|
lines.append(errstring.replace('\n', '|'))
|
2013-08-12 20:44:27 +02:00
|
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, lines)
|
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
|
|
|
raise GeoAlgorithmExecutionException(
|
|
|
|
str(e) + self.tr('\nSee log for more details'))
|
2013-01-21 23:05:17 +01:00
|
|
|
|
2015-06-23 09:07:20 +02:00
|
|
|
def _checkParameterValuesBeforeExecuting(self):
|
|
|
|
for param in self.parameters:
|
|
|
|
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:
|
2015-07-03 08:18:16 +02:00
|
|
|
obj = dataobjects.getObject(inputlayer)
|
2015-06-23 09:07:20 +02:00
|
|
|
if obj is None:
|
|
|
|
return "Wrong parameter value: " + param.value
|
|
|
|
return self.checkParameterValuesBeforeExecuting()
|
|
|
|
|
2013-01-21 23:05:17 +01:00
|
|
|
def runPostExecutionScript(self, progress):
|
2013-10-01 20:52:22 +03:00
|
|
|
scriptFile = ProcessingConfig.getSetting(
|
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
|
|
|
ProcessingConfig.POST_EXECUTION_SCRIPT)
|
2013-10-01 20:52:22 +03:00
|
|
|
self.runHookScript(scriptFile, progress)
|
2013-01-26 14:16:39 +01:00
|
|
|
|
2013-01-21 23:05:17 +01:00
|
|
|
def runPreExecutionScript(self, progress):
|
2013-10-01 20:52:22 +03:00
|
|
|
scriptFile = ProcessingConfig.getSetting(
|
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
|
|
|
ProcessingConfig.PRE_EXECUTION_SCRIPT)
|
2013-10-01 20:52:22 +03:00
|
|
|
self.runHookScript(scriptFile, progress)
|
2013-01-26 14:16:39 +01:00
|
|
|
|
|
|
|
def runHookScript(self, filename, progress):
|
2014-05-08 18:48:25 +02:00
|
|
|
if filename is None or not os.path.exists(filename):
|
2013-01-21 23:05:17 +01:00
|
|
|
return
|
2013-01-26 14:16:39 +01:00
|
|
|
try:
|
2013-10-01 20:52:22 +03:00
|
|
|
script = 'import processing\n'
|
2013-01-21 23:05:17 +01:00
|
|
|
ns = {}
|
|
|
|
ns['progress'] = progress
|
2013-01-26 14:16:39 +01:00
|
|
|
ns['alg'] = self
|
2013-01-21 23:05:17 +01:00
|
|
|
f = open(filename)
|
|
|
|
lines = f.readlines()
|
|
|
|
for line in lines:
|
2013-10-01 20:52:22 +03:00
|
|
|
script += line
|
|
|
|
exec script in ns
|
|
|
|
except:
|
|
|
|
# A wrong script should not cause problems, so we swallow
|
|
|
|
# all exceptions
|
2013-01-21 23:05:17 +01:00
|
|
|
pass
|
2013-01-26 14:16:39 +01:00
|
|
|
|
2013-01-21 23:05:17 +01:00
|
|
|
def convertUnsupportedFormats(self, progress):
|
|
|
|
i = 0
|
2014-10-03 14:44:01 +03:00
|
|
|
progress.setText(self.tr('Converting outputs'))
|
2013-01-26 14:16:39 +01:00
|
|
|
for out in self.outputs:
|
|
|
|
if isinstance(out, OutputVector):
|
2013-01-21 23:05:17 +01:00
|
|
|
if out.compatible is not None:
|
2013-09-12 13:19:00 +02:00
|
|
|
layer = dataobjects.getObjectFromUri(out.compatible)
|
2013-10-01 20:52:22 +03:00
|
|
|
if layer is None:
|
|
|
|
# For the case of memory layer, if the
|
|
|
|
# getCompatible method has been called
|
2013-02-03 10:26:43 +01:00
|
|
|
continue
|
2013-01-21 23:05:17 +01:00
|
|
|
provider = layer.dataProvider()
|
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
|
|
|
writer = out.getVectorWriter(
|
|
|
|
provider.fields(),
|
|
|
|
provider.geometryType(), layer.crs()
|
|
|
|
)
|
2013-09-12 13:19:00 +02:00
|
|
|
features = vector.features(layer)
|
2013-01-21 23:05:17 +01:00
|
|
|
for feature in features:
|
|
|
|
writer.addFeature(feature)
|
2013-02-07 01:09:39 +01:00
|
|
|
elif isinstance(out, OutputRaster):
|
2013-01-21 23:05:17 +01:00
|
|
|
if out.compatible is not None:
|
2013-09-12 13:19:00 +02:00
|
|
|
layer = dataobjects.getObjectFromUri(out.compatible)
|
2013-01-21 23:05:17 +01:00
|
|
|
format = self.getFormatShortNameFromFilename(out.value)
|
2015-06-22 07:44:21 +02:00
|
|
|
orgFile = out.compatible
|
|
|
|
destFile = out.value
|
|
|
|
crsid = layer.crs().authid()
|
|
|
|
settings = QSettings()
|
|
|
|
path = unicode(settings.value('/GdalTools/gdalPath', ''))
|
|
|
|
envval = unicode(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]
|
2015-06-22 08:51:03 +02:00
|
|
|
proc = subprocess.Popen(
|
2015-06-22 07:44:21 +02:00
|
|
|
command,
|
|
|
|
shell=True,
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stdin=subprocess.PIPE,
|
|
|
|
stderr=subprocess.STDOUT,
|
|
|
|
universal_newlines=False,
|
|
|
|
)
|
2015-06-22 08:51:03 +02:00
|
|
|
proc.communicate()
|
2015-06-22 07:44:21 +02:00
|
|
|
|
|
|
|
|
2013-01-26 23:55:14 +01:00
|
|
|
elif isinstance(out, OutputTable):
|
|
|
|
if out.compatible is not None:
|
2013-09-12 13:19:00 +02:00
|
|
|
layer = dataobjects.getObjectFromUri(out.compatible)
|
2013-01-26 23:55:14 +01:00
|
|
|
provider = layer.dataProvider()
|
|
|
|
writer = out.getTableWriter(provider.fields())
|
2013-09-12 13:19:00 +02:00
|
|
|
features = vector.features(layer)
|
2013-01-26 23:55:14 +01:00
|
|
|
for feature in features:
|
2013-02-07 01:09:39 +01:00
|
|
|
writer.addRecord(feature)
|
2013-01-26 14:16:39 +01:00
|
|
|
progress.setPercentage(100 * i / float(len(self.outputs)))
|
|
|
|
|
2013-01-21 23:05:17 +01:00
|
|
|
def getFormatShortNameFromFilename(self, filename):
|
2013-10-01 20:52:22 +03:00
|
|
|
ext = filename[filename.rfind('.') + 1:]
|
2013-01-21 23:05:17 +01:00
|
|
|
supported = GdalUtils.getSupportedRasters()
|
|
|
|
for name in supported.keys():
|
|
|
|
exts = supported[name]
|
|
|
|
if ext in exts:
|
|
|
|
return name
|
2013-10-01 20:52:22 +03:00
|
|
|
return 'GTiff'
|
2013-01-26 14:16:39 +01:00
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
def checkOutputFileExtensions(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Checks if the values of outputs are correct and have one of
|
|
|
|
the supported output extensions.
|
|
|
|
|
|
|
|
If not, it adds the first one of the supported extensions, which
|
|
|
|
is assumed to be the default one.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
for out in self.outputs:
|
2013-10-01 20:52:22 +03:00
|
|
|
if not out.hidden and out.value is not None:
|
2012-09-15 18:25:25 +03:00
|
|
|
if not os.path.isabs(out.value):
|
|
|
|
continue
|
|
|
|
if isinstance(out, OutputRaster):
|
2013-10-01 20:52:22 +03:00
|
|
|
exts = \
|
|
|
|
dataobjects.getSupportedOutputRasterLayerExtensions()
|
2012-09-15 18:25:25 +03:00
|
|
|
elif isinstance(out, OutputVector):
|
2013-10-01 20:52:22 +03:00
|
|
|
exts = \
|
|
|
|
dataobjects.getSupportedOutputVectorLayerExtensions()
|
2012-09-15 18:25:25 +03:00
|
|
|
elif isinstance(out, OutputTable):
|
2013-09-12 13:19:00 +02:00
|
|
|
exts = dataobjects.getSupportedOutputTableExtensions()
|
2012-09-15 18:25:25 +03:00
|
|
|
elif isinstance(out, OutputHTML):
|
2013-10-01 20:52:22 +03:00
|
|
|
exts = ['html', 'htm']
|
2012-09-15 18:25:25 +03:00
|
|
|
else:
|
|
|
|
continue
|
2013-10-01 20:52:22 +03:00
|
|
|
idx = out.value.rfind('.')
|
2012-09-15 18:25:25 +03:00
|
|
|
if idx == -1:
|
2013-10-01 20:52:22 +03:00
|
|
|
out.value = out.value + '.' + exts[0]
|
2012-09-15 18:25:25 +03:00
|
|
|
else:
|
|
|
|
ext = out.value[idx + 1:]
|
|
|
|
if ext not in exts:
|
2013-10-01 20:52:22 +03:00
|
|
|
out.value = out.value + '.' + exts[0]
|
2012-09-15 18:25:25 +03:00
|
|
|
|
|
|
|
def resolveTemporaryOutputs(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Sets temporary outputs (output.value = None) with a
|
|
|
|
temporary file instead.
|
|
|
|
"""
|
2012-09-15 18:25:25 +03:00
|
|
|
for out in self.outputs:
|
2013-10-01 20:52:22 +03:00
|
|
|
if not out.hidden and out.value is None:
|
2013-09-12 13:19:00 +02:00
|
|
|
setTempOutput(out, self)
|
2012-09-15 18:25:25 +03:00
|
|
|
|
2013-01-27 19:17:53 +01:00
|
|
|
def setOutputCRS(self):
|
2013-09-12 13:19:00 +02:00
|
|
|
layers = dataobjects.getAllLayers()
|
2012-09-15 18:25:25 +03:00
|
|
|
for param in self.parameters:
|
2013-10-01 20:52:22 +03:00
|
|
|
if isinstance(param, (ParameterRaster, ParameterVector,
|
|
|
|
ParameterMultipleInput)):
|
2012-09-15 18:25:25 +03:00
|
|
|
if param.value:
|
2014-11-21 16:45:32 +01:00
|
|
|
if isinstance(param, ParameterMultipleInput):
|
|
|
|
inputlayers = param.value.split(';')
|
|
|
|
else:
|
|
|
|
inputlayers = [param.value]
|
2012-09-15 18:25:25 +03:00
|
|
|
for inputlayer in inputlayers:
|
|
|
|
for layer in layers:
|
|
|
|
if layer.source() == inputlayer:
|
|
|
|
self.crs = layer.crs()
|
|
|
|
return
|
2014-06-26 16:20:37 +02:00
|
|
|
p = dataobjects.getObjectFromUri(inputlayer)
|
2013-07-09 22:31:21 +02:00
|
|
|
if p is not None:
|
|
|
|
self.crs = p.crs()
|
2014-06-26 16:20:37 +02:00
|
|
|
p = None
|
2013-07-12 16:27:06 +02:00
|
|
|
return
|
2014-05-20 16:30:59 +02:00
|
|
|
try:
|
|
|
|
from qgis.utils import iface
|
|
|
|
self.crs = iface.mapCanvas().mapRenderer().destinationCrs()
|
|
|
|
except:
|
|
|
|
pass
|
2014-05-21 21:25:18 +02:00
|
|
|
|
2015-07-03 08:18:16 +02:00
|
|
|
def resolveDataObjects(self):
|
|
|
|
layers = dataobjects.getAllLayers()
|
|
|
|
for param in self.parameters:
|
|
|
|
if isinstance(param, (ParameterRaster, ParameterVector, ParameterTable,
|
|
|
|
ParameterMultipleInput)):
|
|
|
|
if param.value:
|
|
|
|
if isinstance(param, ParameterMultipleInput):
|
|
|
|
inputlayers = param.value.split(';')
|
|
|
|
else:
|
|
|
|
inputlayers = [param.value]
|
|
|
|
for i, inputlayer in enumerate(inputlayers):
|
|
|
|
for layer in layers:
|
|
|
|
if layer.name() == inputlayer:
|
|
|
|
inputlayers[i] = layer.source()
|
|
|
|
break
|
|
|
|
param.setValue(",".join(inputlayers))
|
|
|
|
|
2013-02-07 01:09:39 +01:00
|
|
|
|
2013-02-06 21:00:26 +01:00
|
|
|
def checkInputCRS(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""It checks that all input layers use the same CRS. If so,
|
|
|
|
returns True. False otherwise.
|
|
|
|
"""
|
2014-08-06 15:55:53 +03:00
|
|
|
crsList = []
|
2013-02-06 21:00:26 +01:00
|
|
|
for param in self.parameters:
|
2013-10-01 20:52:22 +03:00
|
|
|
if isinstance(param, (ParameterRaster, ParameterVector,
|
|
|
|
ParameterMultipleInput)):
|
2013-02-06 21:00:26 +01:00
|
|
|
if param.value:
|
2014-11-21 16:45:32 +01:00
|
|
|
if isinstance(param, ParameterMultipleInput):
|
|
|
|
layers = param.value.split(';')
|
|
|
|
else:
|
|
|
|
layers = [param.value]
|
2014-08-06 15:55:53 +03:00
|
|
|
for item in layers:
|
|
|
|
crs = dataobjects.getObject(item).crs()
|
|
|
|
if crs not in crsList:
|
|
|
|
crsList.append(crs)
|
2014-10-04 10:21:18 +02:00
|
|
|
return len(crsList) < 2
|
2012-09-15 18:25:25 +03:00
|
|
|
|
|
|
|
def addOutput(self, output):
|
2013-10-01 20:52:22 +03:00
|
|
|
# TODO: check that name does not exist
|
2012-09-15 18:25:25 +03:00
|
|
|
if isinstance(output, Output):
|
|
|
|
self.outputs.append(output)
|
|
|
|
|
|
|
|
def addParameter(self, param):
|
2013-10-01 20:52:22 +03:00
|
|
|
# TODO: check that name does not exist
|
2012-09-15 18:25:25 +03:00
|
|
|
if isinstance(param, Parameter):
|
|
|
|
self.parameters.append(param)
|
|
|
|
|
|
|
|
def setParameterValue(self, paramName, value):
|
|
|
|
for param in self.parameters:
|
|
|
|
if param.name == paramName:
|
|
|
|
return param.setValue(value)
|
|
|
|
|
|
|
|
def setOutputValue(self, outputName, value):
|
|
|
|
for out in self.outputs:
|
|
|
|
if out.name == outputName:
|
2013-09-01 11:39:04 +02:00
|
|
|
out.setValue(value)
|
2012-09-15 18:25:25 +03:00
|
|
|
|
|
|
|
def getVisibleOutputsCount(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns the number of non-hidden outputs.
|
|
|
|
"""
|
|
|
|
i = 0
|
2012-09-15 18:25:25 +03:00
|
|
|
for out in self.outputs:
|
|
|
|
if not out.hidden:
|
2013-10-01 20:52:22 +03:00
|
|
|
i += 1
|
|
|
|
return i
|
2013-03-26 14:15:12 +01:00
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
def getVisibleParametersCount(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns the number of non-hidden parameters.
|
|
|
|
"""
|
|
|
|
i = 0
|
2012-09-15 18:25:25 +03:00
|
|
|
for param in self.parameters:
|
|
|
|
if not param.hidden:
|
2013-10-01 20:52:22 +03:00
|
|
|
i += 1
|
|
|
|
return i
|
2012-09-15 18:25:25 +03:00
|
|
|
|
2013-03-10 00:20:25 +01:00
|
|
|
def getHTMLOutputsCount(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns the number of HTML outputs.
|
|
|
|
"""
|
|
|
|
i = 0
|
2013-03-10 00:20:25 +01:00
|
|
|
for out in self.outputs:
|
|
|
|
if isinstance(out, OutputHTML):
|
2013-10-01 20:52:22 +03:00
|
|
|
i += 1
|
|
|
|
return i
|
2013-03-10 00:20:25 +01:00
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
def getOutputValuesAsDictionary(self):
|
|
|
|
d = {}
|
|
|
|
for out in self.outputs:
|
|
|
|
d[out.name] = out.value
|
|
|
|
return d
|
|
|
|
|
|
|
|
def __str__(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
s = 'ALGORITHM: ' + self.name + '\n'
|
2012-09-15 18:25:25 +03:00
|
|
|
for param in self.parameters:
|
2013-10-01 20:52:22 +03:00
|
|
|
s += '\t' + str(param) + '\n'
|
2012-09-15 18:25:25 +03:00
|
|
|
for out in self.outputs:
|
2013-10-01 20:52:22 +03:00
|
|
|
s += '\t' + str(out) + '\n'
|
|
|
|
s += '\n'
|
2012-09-15 18:25:25 +03:00
|
|
|
return s
|
|
|
|
|
|
|
|
def commandLineName(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
name = self.provider.getName().lower() + ':' + self.name.lower()
|
|
|
|
validChars = \
|
|
|
|
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:'
|
2013-09-14 14:25:58 +02:00
|
|
|
name = ''.join(c for c in name if c in validChars)
|
2013-02-17 23:03:17 +01:00
|
|
|
return name
|
2013-02-28 22:08:32 +01:00
|
|
|
|
2012-09-15 18:25:25 +03:00
|
|
|
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 getParameterFromName(self, name):
|
|
|
|
for param in self.parameters:
|
|
|
|
if param.name == name:
|
|
|
|
return param
|
|
|
|
|
|
|
|
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 getAsCommand(self):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns the command that would run this same algorithm from
|
|
|
|
the console.
|
|
|
|
|
|
|
|
Should return None if the algorithm cannot be run from the
|
|
|
|
console.
|
|
|
|
"""
|
|
|
|
|
|
|
|
s = 'processing.runalg("' + self.commandLineName() + '",'
|
2012-09-15 18:25:25 +03:00
|
|
|
for param in self.parameters:
|
2013-10-01 20:52:22 +03:00
|
|
|
s += param.getValueAsCommandLineParameter() + ','
|
2012-09-15 18:25:25 +03:00
|
|
|
for out in self.outputs:
|
|
|
|
if not out.hidden:
|
2013-10-01 20:52:22 +03:00
|
|
|
s += out.getValueAsCommandLineParameter() + ','
|
|
|
|
s = s[:-1] + ')'
|
2012-09-15 18:25:25 +03:00
|
|
|
return s
|
2013-07-21 21:53:27 +02:00
|
|
|
|
2014-10-03 14:44:01 +03:00
|
|
|
def tr(self, string, context=''):
|
|
|
|
if context == '':
|
2015-01-13 10:49:08 +02:00
|
|
|
context = self.__class__.__name__
|
2014-10-03 21:56:24 +03:00
|
|
|
return QCoreApplication.translate(context, string)
|