352 lines
13 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
2012-09-15 18:25:25 +03:00
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
import processing
from qgis.utils import iface
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.core.SilentProgress import SilentProgress
2013-08-12 20:44:27 +02:00
from processing.gui.AlgorithmClassification import AlgorithmDecorator
from processing.gui.MessageBarProgress import MessageBarProgress
2013-08-12 20:44:27 +02:00
from processing.gui.RenderingStyles import RenderingStyles
from processing.gui.Postprocessing import Postprocessing
from processing.gui.UnthreadedAlgorithmExecutor import \
UnthreadedAlgorithmExecutor
2013-08-12 20:44:27 +02:00
from processing.modeler.Providers import Providers
from processing.modeler.ModelerAlgorithmProvider import \
ModelerAlgorithmProvider
from processing.modeler.ModelerOnlyAlgorithmProvider import \
ModelerOnlyAlgorithmProvider
from processing.algs.qgis.QGISAlgorithmProvider import QGISAlgorithmProvider
from processing.algs.grass.GrassAlgorithmProvider import GrassAlgorithmProvider
from processing.algs.grass7.Grass7AlgorithmProvider import Grass7AlgorithmProvider
from processing.algs.lidar.LidarToolsAlgorithmProvider import \
LidarToolsAlgorithmProvider
from processing.algs.gdal.GdalOgrAlgorithmProvider import GdalOgrAlgorithmProvider
from processing.algs.otb.OTBAlgorithmProvider import OTBAlgorithmProvider
from processing.algs.r.RAlgorithmProvider import RAlgorithmProvider
from processing.algs.saga.SagaAlgorithmProvider import SagaAlgorithmProvider
2013-08-12 20:44:27 +02:00
from processing.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider
from processing.algs.taudem.TauDEMAlgorithmProvider import TauDEMAlgorithmProvider
from processing.tools import dataobjects
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 = []
modeler = ModelerAlgorithmProvider()
@staticmethod
def addProvider(provider, updateList=False):
"""Use this method to add algorithms from external providers.
"""
# Note: this might slow down the initialization process if
# there are many new providers added. Should think of a
# different solution
try:
provider.initializeSettings()
Processing.providers.append(provider)
ProcessingConfig.readSettings()
if updateList:
Processing.updateAlgsList()
except:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
'Could not load provider:'
+ provider.getDescription() + '\n'
+ unicode(sys.exc_info()[1]))
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)
ProcessingConfig.readSettings()
2013-08-12 20:44:27 +02:00
Processing.updateAlgsList()
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 found 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
2013-08-12 20:44:27 +02:00
Processing.addProvider(QGISAlgorithmProvider())
Processing.addProvider(ModelerOnlyAlgorithmProvider())
Processing.addProvider(GdalOgrAlgorithmProvider())
Processing.addProvider(LidarToolsAlgorithmProvider())
Processing.addProvider(OTBAlgorithmProvider())
Processing.addProvider(RAlgorithmProvider())
Processing.addProvider(SagaAlgorithmProvider())
2014-04-19 22:04:24 +02:00
Processing.addProvider(GrassAlgorithmProvider())
Processing.addProvider(Grass7AlgorithmProvider())
2013-08-12 20:44:27 +02:00
Processing.addProvider(ScriptAlgorithmProvider())
Processing.addProvider(TauDEMAlgorithmProvider())
Processing.modeler.initializeSettings()
# And initialize
AlgorithmDecorator.loadClassification()
2013-08-12 20:44:27 +02:00
ProcessingLog.startLogging()
ProcessingConfig.initialize()
ProcessingConfig.readSettings()
2013-02-28 22:08:32 +01:00
RenderingStyles.loadStyles()
2013-08-12 20:44:27 +02:00
Processing.loadFromProviders()
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.
"""
2013-08-12 20:44:27 +02:00
Processing.loadFromProviders()
Processing.fireAlgsListHasChanged()
2012-09-15 18:25:25 +03:00
@staticmethod
2013-02-07 01:09:39 +01:00
def loadFromProviders():
2013-08-12 20:44:27 +02:00
Processing.loadAlgorithms()
Processing.loadActions()
Processing.loadContextMenuActions()
2012-09-15 18:25:25 +03:00
@staticmethod
def updateProviders():
2013-08-12 20:44:27 +02:00
for provider in Processing.providers:
2012-09-15 18:25:25 +03:00
provider.loadAlgorithms()
@staticmethod
def addAlgListListener(listener):
"""Listener should implement a algsListHasChanged() method.
Whenever the list of algorithms changes, that method will be
called for all registered listeners.
"""
2013-08-12 20:44:27 +02:00
Processing.listeners.append(listener)
2012-09-15 18:25:25 +03:00
@staticmethod
def fireAlgsListHasChanged():
2013-08-12 20:44:27 +02:00
for listener in Processing.listeners:
2012-09-15 18:25:25 +03:00
listener.algsListHasChanged()
@staticmethod
def loadAlgorithms():
Processing.algs = {}
2013-08-12 20:44:27 +02:00
Processing.updateProviders()
for provider in Processing.providers:
2012-09-15 18:25:25 +03:00
providerAlgs = provider.algs
algs = {}
for alg in providerAlgs:
algs[alg.commandLineName()] = alg
2013-08-12 20:44:27 +02:00
Processing.algs[provider.getName()] = algs
2013-02-07 01:09:39 +01:00
# This is a special provider, since it depends on others.
# TODO: Fix circular imports, so this provider can be
# incorporated as a normal one.
2013-08-12 20:44:27 +02:00
provider = Processing.modeler
provider.setAlgsList(Processing.algs)
2012-09-15 18:25:25 +03:00
provider.loadAlgorithms()
providerAlgs = provider.algs
algs = {}
for alg in providerAlgs:
algs[alg.commandLineName()] = alg
2013-08-12 20:44:27 +02:00
Processing.algs[provider.getName()] = algs
# And we do it again, in case there are models containing
# models.
# TODO: Improve this
2013-08-12 20:44:27 +02:00
provider.setAlgsList(Processing.algs)
2012-09-15 18:25:25 +03:00
provider.loadAlgorithms()
providerAlgs = provider.algs
algs = {}
for alg in providerAlgs:
algs[alg.commandLineName()] = alg
2013-08-12 20:44:27 +02:00
Processing.algs[provider.getName()] = algs
2012-09-15 18:25:25 +03:00
provs = {}
2013-08-12 20:44:27 +02:00
for provider in Processing.providers:
2012-09-15 18:25:25 +03:00
provs[provider.getName()] = provider
2013-08-12 20:44:27 +02:00
provs[Processing.modeler.getName()] = Processing.modeler
2012-09-15 18:25:25 +03:00
Providers.providers = provs
@staticmethod
def loadActions():
2013-08-12 20:44:27 +02:00
for provider in Processing.providers:
2012-09-15 18:25:25 +03:00
providerActions = provider.actions
actions = list()
for action in providerActions:
actions.append(action)
2013-08-12 20:44:27 +02:00
Processing.actions[provider.getName()] = actions
2012-09-15 18:25:25 +03:00
2013-08-12 20:44:27 +02:00
provider = Processing.modeler
2012-09-15 18:25:25 +03:00
actions = list()
for action in provider.actions:
actions.append(action)
2013-08-12 20:44:27 +02:00
Processing.actions[provider.getName()] = actions
2012-09-15 18:25:25 +03:00
@staticmethod
def loadContextMenuActions():
2013-08-12 20:44:27 +02:00
Processing.contextMenuActions = []
for provider in Processing.providers:
2012-09-15 18:25:25 +03:00
providerActions = provider.contextMenuActions
for action in providerActions:
2013-08-12 20:44:27 +02:00
Processing.contextMenuActions.append(action)
2012-09-15 18:25:25 +03:00
2013-08-12 20:44:27 +02:00
provider = Processing.modeler
2012-09-15 18:25:25 +03:00
providerActions = provider.contextMenuActions
for action in providerActions:
2013-08-12 20:44:27 +02:00
Processing.contextMenuActions.append(action)
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):
Processing.runAlgorithm(name, Postprocessing.handleAlgorithmResults,
*args)
2012-09-15 18:25:25 +03:00
@staticmethod
def runAlgorithm(algOrName, onFinish, *args):
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'
2012-09-15 18:25:25 +03:00
return
if len(args) != alg.getVisibleParametersCount() \
+ alg.getVisibleOutputsCount():
print 'Error: Wrong number of parameters'
2013-08-12 20:44:27 +02:00
processing.alghelp(algOrName)
2012-09-15 18:25:25 +03:00
return
alg = alg.getCopy()
2012-09-15 18:25:25 +03:00
if isinstance(args, dict):
# Set params by name
for (name, value) in args.items():
2012-09-15 18:25:25 +03:00
if alg.getParameterFromName(name).setValue(value):
continue
2012-09-15 18:25:25 +03:00
if alg.getOutputFromName(name).setValue(value):
continue
print 'Error: Wrong parameter value %s for parameter %s.' \
% (value, name)
2012-09-15 18:25:25 +03:00
return
else:
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])
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])
2012-09-15 18:25:25 +03:00
return
i = i + 1
2012-09-15 18:25:25 +03:00
msg = alg.checkParameterValuesBeforeExecuting()
if msg:
print 'Unable to execute algorithm\n' + msg
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.'
2013-02-07 01:09:39 +01:00
2013-08-12 20:44:27 +02:00
ProcessingLog.addToLog(ProcessingLog.LOG_ALGORITHM, alg.getAsCommand())
2012-09-15 18:25:25 +03:00
# Don't set the wait cursor twice, because then when you
# restore it, it will still be a wait cursor.
cursor = QApplication.overrideCursor()
if cursor is None or cursor == 0:
2012-12-10 00:12:07 +01:00
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
elif cursor.shape() != Qt.WaitCursor:
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
2012-12-10 00:12:07 +01:00
progress = SilentProgress()
if iface is not None :
progress = MessageBarProgress()
ret = UnthreadedAlgorithmExecutor.runalg(alg, progress)
if onFinish is not None and ret:
onFinish(alg, progress)
QApplication.restoreOverrideCursor()
progress.close()
2012-09-15 18:25:25 +03:00
return alg