291 lines
11 KiB
Python
Raw Normal View History

2012-10-05 23:28:47 +02:00
# -*- coding: utf-8 -*-
"""
***************************************************************************
2013-08-12 20:44:27 +02:00
Processing.py
2012-10-05 23:28:47 +02:00
---------------------
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. *
* *
***************************************************************************
"""
2012-10-05 23:28:47 +02:00
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
2012-10-05 23:28:47 +02:00
# This will get replaced with a git SHA1 when you do a git archive
2012-10-05 23:28:47 +02:00
__revision__ = '$Format:%H$'
import sys
import traceback
2016-04-22 10:38:48 +02:00
from qgis.PyQt.QtCore import Qt, QCoreApplication, QObject, pyqtSignal
from qgis.PyQt.QtWidgets import QApplication
from qgis.PyQt.QtGui import QCursor
from qgis.utils import iface
from qgis.core import QgsMessageLog
import processing
from processing.core.AlgorithmProvider import AlgorithmProvider
2013-08-12 20:44:27 +02:00
from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.ProcessingLog import ProcessingLog
from processing.gui.MessageBarProgress import MessageBarProgress
2013-08-12 20:44:27 +02:00
from processing.gui.RenderingStyles import RenderingStyles
2014-06-08 23:15:33 +02:00
from processing.gui.Postprocessing import handleAlgorithmResults
from processing.gui.AlgorithmExecutor import runalg
from processing.tools import dataobjects
2016-04-27 15:40:56 +03:00
class AlgListWatcher(QObject):
providerAdded = pyqtSignal(str)
providerRemoved = pyqtSignal(str)
algListWatcher = AlgListWatcher()
2013-08-12 20:44:27 +02:00
2016-04-27 15:40:56 +03:00
2013-08-12 20:44:27 +02:00
class Processing:
2012-09-15 18:25:25 +03:00
listeners = []
providers = []
# A dictionary of algorithms. Keys are names of providers
# and values are list with all algorithms from that provider
2012-09-15 18:25:25 +03:00
algs = {}
# Same structure as algs
2012-09-15 18:25:25 +03:00
actions = {}
# All the registered context menu actions for the toolbox
2012-09-15 18:25:25 +03:00
contextMenuActions = []
@staticmethod
def addProvider(provider, update=True):
"""Use this method to add algorithms from external providers.
"""
if provider.getName() in [p.getName for p in Processing.providers]:
return
try:
provider.initializeSettings()
Processing.providers.append(provider)
ProcessingConfig.readSettings()
provider.loadAlgorithms()
Processing.algs[provider.getName()] = {a.commandLineName(): a for a in provider.algs}
Processing.actions[provider.getName()] = provider.actions
Processing.contextMenuActions.extend(provider.contextMenuActions)
algListWatcher.providerAdded.emit(provider.getName())
except:
ProcessingLog.addToLog(
ProcessingLog.LOG_ERROR,
2014-10-09 10:51:50 +03:00
Processing.tr('Could not load provider: %s\n%s')
% (provider.getDescription(), traceback.format_exc()))
Processing.removeProvider(provider)
2012-09-15 18:25:25 +03:00
@staticmethod
def removeProvider(provider):
"""Use this method to remove a provider.
This method should be called when unloading a plugin that
contributes a provider.
"""
2012-09-15 18:25:25 +03:00
try:
provider.unload()
2013-08-12 20:44:27 +02:00
Processing.providers.remove(provider)
del Processing.algs[provider.getName()]
algListWatcher.providerRemoved.emit(provider.getName())
2012-09-15 18:25:25 +03:00
except:
# This try catch block is here to avoid problems if the
# plugin with a provider is unloaded after the Processing
# framework itself has been unloaded. It is a quick fix
# before I find out how to properly avoid that.
pass
2012-09-15 18:25:25 +03:00
@staticmethod
def getProviderFromName(name):
"""Returns the provider with the given name."""
2013-08-12 20:44:27 +02:00
for provider in Processing.providers:
2012-09-15 18:25:25 +03:00
if provider.getName() == name:
return provider
2013-08-12 20:44:27 +02:00
return Processing.modeler
2012-09-15 18:25:25 +03:00
@staticmethod
def initialize():
# Add the basic providers
for c in AlgorithmProvider.__subclasses__():
Processing.addProvider(c())
# And initialize
2013-08-12 20:44:27 +02:00
ProcessingConfig.initialize()
ProcessingConfig.readSettings()
2013-02-28 22:08:32 +01:00
RenderingStyles.loadStyles()
2014-11-30 10:26:17 +01:00
2012-09-15 18:25:25 +03:00
@staticmethod
def updateAlgsList():
"""Call this method when there has been any change that
requires the list of algorithms to be created again from
algorithm providers.
"""
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
for p in Processing.providers:
Processing.reloadProvider(p)
QApplication.restoreOverrideCursor()
2012-09-15 18:25:25 +03:00
@staticmethod
def reloadProvider(providerName):
for p in Processing.providers:
if p.getName() == providerName:
p.loadAlgorithms()
Processing.algs[
p.getName()] = {a.commandLineName(): a for a in p.algs}
2012-09-15 18:25:25 +03:00
@staticmethod
def getAlgorithm(name):
2013-08-12 20:44:27 +02:00
for provider in Processing.algs.values():
2012-09-15 18:25:25 +03:00
if name in provider:
return provider[name]
return None
2013-05-01 23:45:20 +02:00
2013-04-13 15:05:19 +02:00
@staticmethod
def getAlgorithmFromFullName(name):
2013-08-12 20:44:27 +02:00
for provider in Processing.algs.values():
2013-04-13 15:05:19 +02:00
for alg in provider.values():
if alg.name == name:
return alg
return None
2012-09-15 18:25:25 +03:00
@staticmethod
def getObject(uri):
"""Returns the QGIS object identified by the given URI."""
return dataobjects.getObjectFromUri(uri)
2012-09-15 18:25:25 +03:00
@staticmethod
def runandload(name, *args):
2014-06-08 23:15:33 +02:00
Processing.runAlgorithm(name, handleAlgorithmResults, *args)
2012-09-15 18:25:25 +03:00
@staticmethod
def runAlgorithm(algOrName, onFinish, *args, **kwargs):
2012-09-15 18:25:25 +03:00
if isinstance(algOrName, GeoAlgorithm):
alg = algOrName
else:
2013-08-12 20:44:27 +02:00
alg = Processing.getAlgorithm(algOrName)
if alg is None:
print 'Error: Algorithm not found\n'
QgsMessageLog.logMessage(Processing.tr('Error: Algorithm {0} not found\n').format(algOrName), Processing.tr("Processing"))
2012-09-15 18:25:25 +03:00
return
alg = alg.getCopy()
2014-07-02 07:46:03 +02:00
if len(args) == 1 and isinstance(args[0], dict):
2014-07-02 07:46:03 +02:00
# Set params by name and try to run the alg even if not all parameter values are provided,
# by using the default values instead.
setParams = []
for (name, value) in args[0].items():
param = alg.getParameterFromName(name)
if param and param.setValue(value):
setParams.append(name)
continue
output = alg.getOutputFromName(name)
if output and output.setValue(value):
continue
print 'Error: Wrong parameter value %s for parameter %s.' % (value, name)
QgsMessageLog.logMessage(Processing.tr('Error: Wrong parameter value {0} for parameter {1}.').format(value, name), Processing.tr("Processing"))
ProcessingLog.addToLog(
ProcessingLog.LOG_ERROR,
Processing.tr('Error in %s. Wrong parameter value %s for parameter %s.') % (
alg.name, value, name)
)
2012-09-15 18:25:25 +03:00
return
# fill any missing parameters with default values if allowed
for param in alg.parameters:
if param.name not in setParams:
if not param.setDefaultValue():
print 'Error: Missing parameter value for parameter %s.' % param.name
QgsMessageLog.logMessage(Processing.tr('Error: Missing parameter value for parameter {0}.').format(param.name), Processing.tr("Processing"))
ProcessingLog.addToLog(
ProcessingLog.LOG_ERROR,
Processing.tr('Error in %s. Missing parameter value for parameter %s.') % (
alg.name, param.name)
)
return
2012-09-15 18:25:25 +03:00
else:
if len(args) != alg.getVisibleParametersCount() + alg.getVisibleOutputsCount():
print 'Error: Wrong number of parameters'
QgsMessageLog.logMessage(Processing.tr('Error: Wrong number of parameters'), Processing.tr("Processing"))
processing.alghelp(algOrName)
return
2012-09-15 18:25:25 +03:00
i = 0
for param in alg.parameters:
if not param.hidden:
if not param.setValue(args[i]):
print'Error: Wrong parameter value: ' + unicode(args[i])
QgsMessageLog.logMessage(Processing.tr('Error: Wrong parameter value: ') + unicode(args[i]), Processing.tr("Processing"))
2012-09-15 18:25:25 +03:00
return
i = i + 1
2012-09-15 18:25:25 +03:00
for output in alg.outputs:
if not output.hidden:
if not output.setValue(args[i]):
print 'Error: Wrong output value: ' + unicode(args[i])
QgsMessageLog.logMessage(Processing.tr('Error: Wrong output value: ') + unicode(args[i]), Processing.tr("Processing"))
2012-09-15 18:25:25 +03:00
return
i = i + 1
2012-09-15 18:25:25 +03:00
msg = alg._checkParameterValuesBeforeExecuting()
2012-09-15 18:25:25 +03:00
if msg:
print 'Unable to execute algorithm\n' + unicode(msg)
QgsMessageLog.logMessage(Processing.tr('Unable to execute algorithm\n{0}').format(msg), Processing.tr("Processing"))
return
2012-09-15 18:25:25 +03:00
if not alg.checkInputCRS():
print('Warning: Not all input layers use the same CRS.\n'
+ 'This can cause unexpected results.')
QgsMessageLog.logMessage(Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.'), Processing.tr("Processing"))
2013-02-07 01:09:39 +01:00
# Don't set the wait cursor twice, because then when you
# restore it, it will still be a wait cursor.
overrideCursor = False
if iface is not None:
cursor = QApplication.overrideCursor()
if cursor is None or cursor == 0:
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
overrideCursor = True
elif cursor.shape() != Qt.WaitCursor:
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
overrideCursor = True
2012-12-10 00:12:07 +01:00
progress = None
if kwargs is not None and "progress" in kwargs.keys():
2015-11-10 20:21:10 +00:00
progress = kwargs["progress"]
elif iface is not None:
progress = MessageBarProgress()
2015-11-10 20:21:10 +00:00
ret = runalg(alg, progress)
if ret:
if onFinish is not None:
onFinish(alg, progress)
else:
QgsMessageLog.logMessage(Processing.tr("There were errors executing the algorithm."), Processing.tr("Processing"))
if overrideCursor:
QApplication.restoreOverrideCursor()
if isinstance(progress, MessageBarProgress):
progress.close()
2012-09-15 18:25:25 +03:00
return alg
2014-10-09 10:51:50 +03:00
@staticmethod
def tr(string, context=''):
if context == '':
context = 'Processing'
2014-10-09 10:51:50 +03:00
return QCoreApplication.translate(context, string)