Merge pull request #1446 from volaya/new_modeler

[processing] overhaul of graphical modeler
This commit is contained in:
alexbruy 2014-06-29 12:34:27 +03:00
commit 6def4b60ff
37 changed files with 1038 additions and 2260 deletions

View File

@ -28,7 +28,6 @@ __revision__ = '$Format:%H$'
import stat
import shutil
import codecs
import traceback
import subprocess
from qgis.core import QgsApplication
from PyQt4.QtCore import *
@ -385,7 +384,6 @@ class GrassUtils:
configured in your system.\nPlease install it before \
running GRASS algorithms.'
except:
s = traceback.format_exc()
return 'Error while checking GRASS installation. GRASS might not \
be correctly configured.\n' + s

View File

@ -27,7 +27,6 @@ __revision__ = '$Format:%H$'
import stat
import shutil
import traceback
import subprocess
from qgis.core import QgsApplication
from PyQt4.QtCore import *
@ -387,7 +386,6 @@ class Grass7Utils:
configured in your system.\nPlease install it before \
running GRASS GIS 7 algorithms.'
except:
s = traceback.format_exc()
return 'Error while checking GRASS GIS 7 installation. GRASS GIS 7 might not \
be correctly configured.\n' + s

View File

@ -16,6 +16,7 @@
* *
***************************************************************************
"""
from processing.modeler.ModelerUtils import ModelerUtils
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
@ -41,7 +42,6 @@ from processing.gui.RenderingStyles import RenderingStyles
from processing.gui.Postprocessing import handleAlgorithmResults
from processing.gui.UnthreadedAlgorithmExecutor import \
UnthreadedAlgorithmExecutor
from processing.modeler.Providers import Providers
from processing.modeler.ModelerAlgorithmProvider import \
ModelerAlgorithmProvider
from processing.modeler.ModelerOnlyAlgorithmProvider import \
@ -119,8 +119,7 @@ class Processing:
@staticmethod
def getProviderFromName(name):
"""Returns the provider with the given name.
"""
"""Returns the provider with the given name."""
for provider in Processing.providers:
if provider.getName() == name:
return provider
@ -139,8 +138,9 @@ class Processing:
Processing.addProvider(SagaAlgorithmProvider())
Processing.addProvider(GrassAlgorithmProvider())
Processing.addProvider(Grass7AlgorithmProvider())
Processing.addProvider(ScriptAlgorithmProvider())
Processing.addProvider(ScriptAlgorithmProvider())
Processing.addProvider(TauDEMAlgorithmProvider())
Processing.addProvider(ModelerAlgorithmProvider())
Processing.modeler.initializeSettings()
# And initialize
@ -173,7 +173,8 @@ class Processing:
@staticmethod
def addAlgListListener(listener):
"""Listener should implement a algsListHasChanged() method.
"""
Listener should implement a algsListHasChanged() method.
Whenever the list of algorithms changes, that method will be
called for all registered listeners.
@ -196,33 +197,11 @@ class Processing:
algs[alg.commandLineName()] = alg
Processing.algs[provider.getName()] = algs
# This is a special provider, since it depends on others.
# TODO: Fix circular imports, so this provider can be
# incorporated as a normal one.
provider = Processing.modeler
provider.setAlgsList(Processing.algs)
provider.loadAlgorithms()
providerAlgs = provider.algs
algs = {}
for alg in providerAlgs:
algs[alg.commandLineName()] = alg
Processing.algs[provider.getName()] = algs
# And we do it again, in case there are models containing
# models.
# TODO: Improve this
provider.setAlgsList(Processing.algs)
provider.loadAlgorithms()
providerAlgs = provider.algs
algs = {}
for alg in providerAlgs:
algs[alg.commandLineName()] = alg
Processing.algs[provider.getName()] = algs
provs = {}
for provider in Processing.providers:
provs[provider.getName()] = provider
provs[Processing.modeler.getName()] = Processing.modeler
Providers.providers = provs
ModelerUtils.allAlgs = Processing.algs
ModelerUtils.providers = provs
@staticmethod
def loadActions():
@ -232,11 +211,7 @@ class Processing:
for action in providerActions:
actions.append(action)
Processing.actions[provider.getName()] = actions
provider = Processing.modeler
actions = list()
for action in provider.actions:
actions.append(action)
Processing.actions[provider.getName()] = actions
@staticmethod
@ -247,11 +222,6 @@ class Processing:
for action in providerActions:
Processing.contextMenuActions.append(action)
provider = Processing.modeler
providerActions = provider.contextMenuActions
for action in providerActions:
Processing.contextMenuActions.append(action)
@staticmethod
def getAlgorithm(name):
for provider in Processing.algs.values():
@ -269,8 +239,7 @@ class Processing:
@staticmethod
def getObject(uri):
"""Returns the QGIS object identified by the given URI.
"""
"""Returns the QGIS object identified by the given URI."""
return dataobjects.getObjectFromUri(uri)
@staticmethod

View File

@ -16,6 +16,7 @@
* *
***************************************************************************
"""
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
__author__ = 'Victor Olaya'
@ -44,21 +45,21 @@ class HelpEditionDialog(QDialog, Ui_DlgHelpEdition):
def __init__(self, alg):
QDialog.__init__(self)
self.setupUi(self)
self.alg = alg
self.descriptions = {}
if self.alg.descriptionFile is not None:
helpfile = alg.descriptionFile + '.help'
if os.path.exists(helpfile):
try:
with open(helpfile) as f:
self.descriptions = json.load(f)
except Exception, e:
print e
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, "Cannot open help file: " + helpfile)
if isinstance(self.alg, ModelerAlgorithm):
self.descriptions = self.alg.helpContent
else:
if self.alg.descriptionFile is not None:
helpfile = alg.descriptionFile + '.help'
if os.path.exists(helpfile):
try:
with open(helpfile) as f:
self.descriptions = json.load(f)
except Exception, e:
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, "Cannot open help file: " + helpfile)
self.currentName = self.ALG_DESC
if self.ALG_DESC in self.descriptions:
self.text.setText(self.descriptions[self.ALG_DESC])
@ -73,17 +74,20 @@ class HelpEditionDialog(QDialog, Ui_DlgHelpEdition):
def accept(self):
self.descriptions[self.currentName] = unicode(self.text.toPlainText())
if self.alg.descriptionFile is not None:
try:
with open(self.alg.descriptionFile + '.help', 'w') as f:
json.dump(self.descriptions, f)
except Exception, e:
QMessageBox.warning(self, 'Error saving help file',
'Help file could not be saved.\n'
'Check that you have permission to modify the help\n'
'file. You might not have permission if you are \n'
'editing an example model or script, since they \n'
'are stored on the installation folder')
if isinstance(self.alg, ModelerAlgorithm):
self.alg.helpContent = self.descriptions
else:
if self.alg.descriptionFile is not None:
try:
with open(self.alg.descriptionFile + '.help', 'w') as f:
json.dump(self.descriptions, f)
except Exception, e:
QMessageBox.warning(self, 'Error saving help file',
'Help file could not be saved.\n'
'Check that you have permission to modify the help\n'
'file. You might not have permission if you are \n'
'editing an example model or script, since they \n'
'are stored on the installation folder')
QDialog.accept(self)
@ -126,8 +130,7 @@ class HelpEditionDialog(QDialog, Ui_DlgHelpEdition):
item = self.tree.currentItem()
if isinstance(item, TreeDescriptionItem):
if self.currentName:
self.descriptions[self.currentName] = \
unicode(self.text.toPlainText())
self.descriptions[self.currentName] = unicode(self.text.toPlainText())
name = item.name
if name:
self.text.setEnabled(True)

View File

@ -25,7 +25,7 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
from PyQt4 import QtCore, QtGui
from PyQt4 import QtGui
from processing.gui.MultipleInputDialog import MultipleInputDialog

View File

@ -17,6 +17,7 @@
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
@ -28,6 +29,7 @@ __revision__ = '$Format:%H$'
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.utils import iface
from processing.modeler.ModelerUtils import ModelerUtils
from processing.core.Processing import Processing
from processing.core.ProcessingLog import ProcessingLog
from processing.core.ProcessingConfig import ProcessingConfig
@ -37,7 +39,6 @@ from processing.gui.AlgorithmClassification import AlgorithmDecorator
from processing.gui.ParametersDialog import ParametersDialog
from processing.gui.BatchProcessingDialog import BatchProcessingDialog
from processing.gui.EditRenderingStylesDialog import EditRenderingStylesDialog
from processing.modeler.Providers import Providers
from processing.ui.ui_ProcessingToolbox import Ui_ProcessingToolbox
@ -259,7 +260,7 @@ class ProcessingToolbox(QDockWidget, Ui_ProcessingToolbox):
if not ProcessingConfig.getSetting(name):
continue
if providerName in providersToExclude \
or len(Providers.providers[providerName].actions) != 0:
or len(ModelerUtils.providers[providerName].actions) != 0:
continue
algs = provider.values()

View File

@ -16,6 +16,7 @@
* *
***************************************************************************
"""
from processing.modeler.ModelerUtils import ModelerUtils
__author__ = 'Alexander Bruy'
__date__ = 'December 2012'
@ -38,7 +39,6 @@ from qgis.utils import iface
from processing.gui.ParametersDialog import ParametersDialog
from processing.gui.HelpEditionDialog import HelpEditionDialog
from processing.modeler.Providers import Providers
from processing.algs.r.RAlgorithm import RAlgorithm
from processing.algs.r.RUtils import RUtils
from processing.script.ScriptAlgorithm import ScriptAlgorithm
@ -180,10 +180,10 @@ class ScriptEditorDialog(QDialog, Ui_DlgScriptEditor):
def runAlgorithm(self):
if self.algType == self.SCRIPT_PYTHON:
alg = ScriptAlgorithm(None, unicode(self.editor.text()))
alg.provider = Providers.providers['script']
alg.provider = ModelerUtils.providers['script']
if self.algType == self.SCRIPT_R:
alg = RAlgorithm(None, unicode(self.editor.text()))
alg.provider = Providers.providers['r']
alg.provider = ModelerUtils.providers['r']
dlg = alg.getCustomParametersDialog()
if not dlg:

View File

@ -47,11 +47,12 @@ class AddModelFromFileAction(ToolboxAction):
'*.model')
if filename:
try:
model = ModelerAlgorithm()
model.openModel(filename)
ModelerAlgorithm.fromJsonFile(filename)
except WrongModelException:
QtGui.QMessageBox.warning(self.toolbox, "Error reading model", "The selected file does not contain a valid model")
return
except:
QtGui.QMessageBox.warning(self.toolbox, "Error reading model", "Cannot read file")
destFilename = os.path.join(ModelerUtils.modelsFolder(), os.path.basename(filename))
shutil.copyfile(filename,destFilename)
self.toolbox.updateProvider('script')

View File

@ -25,45 +25,114 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
from PyQt4 import QtCore, QtGui
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import \
GeoAlgorithmExecutionException
from processing.modeler.CalculatorModelerParametersDialog import \
CalculatorModelerParametersDialog
from processing.parameters.ParameterString import ParameterString
from processing.parameters.ParameterNumber import ParameterNumber
from processing.outputs.OutputNumber import OutputNumber
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
from processing.modeler.ModelerAlgorithm import Algorithm
FORMULA = 'FORMULA'
NUMBER = 'NUMBER'
RESULT = 'RESULT'
AVAILABLE_VARIABLES = 10
class CalculatorModelerAlgorithm(GeoAlgorithm):
FORMULA = 'FORMULA'
NUMBER = 'NUMBER'
RESULT = 'RESULT'
AVAILABLE_VARIABLES = 10
def defineCharacteristics(self):
self.showInModeler = True
self.showInToolbox = False
self.name = 'Calculator'
self.group = 'Modeler-only tools'
self.addParameter(ParameterString(self.FORMULA, 'Formula', ''))
for i in range(self.AVAILABLE_VARIABLES):
self.addParameter(ParameterNumber(CalculatorModelerAlgorithm.NUMBER
self.addParameter(ParameterString(FORMULA, 'Formula', ''))
for i in range(AVAILABLE_VARIABLES):
self.addParameter(ParameterNumber(NUMBER
+ str(i), 'dummy'))
self.addOutput(OutputNumber(self.RESULT, 'Result'))
self.addOutput(OutputNumber(RESULT, 'Result'))
def processAlgorithm(self, progress):
formula = self.getParameterValue(self.FORMULA)
for i in range(self.AVAILABLE_VARIABLES):
name = CalculatorModelerAlgorithm.NUMBER + str(i)
formula = self.getParameterValue(FORMULA)
for i in range(AVAILABLE_VARIABLES):
name = NUMBER + str(i)
num = self.getParameterValue(name)
formula = formula.replace(chr(97 + i), str(num))
try:
result = eval(formula)
self.setOutputValue(self.RESULT, result)
self.setOutputValue(RESULT, result)
except:
raise GeoAlgorithmExecutionException('Wrong formula: ' + formula)
def getCustomModelerParametersDialog(self, modelAlg, algIndex=None):
return CalculatorModelerParametersDialog(self, modelAlg, algIndex)
class CalculatorModelerParametersDialog(ModelerParametersDialog):
def setupUi(self):
self.valueItems = {}
self.dependentItems = {}
self.resize(650, 450)
self.buttonBox = QtGui.QDialogButtonBox()
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel
| QtGui.QDialogButtonBox.Ok)
self.infoText = QtGui.QTextEdit()
numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
text = ('You can refer to model values in you formula, using'
'single-letter variables, as follows:\n')
ichar = 97
for number in numbers:
text += chr(ichar) + '->' + self.resolveValueDescription(number) + '\n'
ichar += 1
self.infoText.setText(text)
self.infoText.setEnabled(False)
self.formulaText = QtGui.QLineEdit()
if hasattr(self.formulaText, 'setPlaceholderText'):
self.formulaText.setPlaceholderText('[Enter your formula here]')
self.setWindowTitle("Calculator")
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setSpacing(2)
self.verticalLayout.setMargin(0)
self.verticalLayout.addWidget(self.infoText)
self.verticalLayout.addWidget(self.formulaText)
self.verticalLayout.addWidget(self.buttonBox)
self.setLayout(self.verticalLayout)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL('accepted()'),
self.okPressed)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL('rejected()'),
self.cancelPressed)
QtCore.QMetaObject.connectSlotsByName(self)
def createAlgorithm(self):
alg = Algorithm('modelertools:calculator')
alg.setName(self.model)
alg.description = "Calculator"
formula = self.formulaText.text()
alg.params[FORMULA] = formula
for i in xrange(AVAILABLE_VARIABLES):
paramname = NUMBER + str(i)
alg.params[paramname] = None
numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
used = []
for i in range(len(numbers)):
if str(chr(i + 97)) in formula:
used.append(numbers[i])
for i, variable in enumerate(used):
paramname = NUMBER + str(i)
alg.params[paramname] = variable
#TODO check formula is correct
return alg

View File

@ -1,164 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
CalculatorModelerParametersDialog.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore, QtGui
from processing.parameters.ParameterNumber import ParameterNumber
from processing.modeler.ModelerAlgorithm import AlgorithmAndParameter
from processing.outputs.OutputNumber import OutputNumber
class CalculatorModelerParametersDialog(QtGui.QDialog):
def __init__(self, alg, model, algIndex):
QtGui.QDialog.__init__(self)
self.setModal(True)
self.alg = alg
self.model = model
self.algIndex = algIndex
self.setupUi()
self.params = None
def setupUi(self):
self.valueItems = {}
self.dependentItems = {}
self.resize(650, 450)
self.buttonBox = QtGui.QDialogButtonBox()
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel
| QtGui.QDialogButtonBox.Ok)
self.infoText = QtGui.QTextEdit()
numbers = self.getNumbers()
text = 'You can refer to model values in you formula, using \
single-letter variables, as follows:'
ichar = 97
for number in numbers:
text += chr(ichar) + '->' + number.name() + '\n'
ichar += 1
self.infoText.setText(text)
self.infoText.setEnabled(False)
self.formulaText = QtGui.QLineEdit()
if hasattr(self.formulaText, 'setPlaceholderText'):
self.formulaText.setPlaceholderText('[Enter your formula here]')
self.setWindowTitle(self.alg.name)
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setSpacing(2)
self.verticalLayout.setMargin(0)
self.verticalLayout.addWidget(self.infoText)
self.verticalLayout.addWidget(self.formulaText)
self.verticalLayout.addWidget(self.buttonBox)
self.setLayout(self.verticalLayout)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL('accepted()'),
self.okPressed)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL('rejected()'),
self.cancelPressed)
QtCore.QMetaObject.connectSlotsByName(self)
def getNumbers(self):
numbers = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterNumber):
numbers.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
dependent.append(self.algIndex)
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputNumber):
numbers.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return numbers
def setParamValues(self):
self.params = {}
self.values = {}
self.outputs = {}
name = self.getSafeNameForHarcodedParameter(
self.alg.getParameterFromName(self.alg.FORMULA))
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[self.alg.FORMULA] = value
formula = str(self.formulaText.text())
self.values[name] = formula
numbers = self.getNumbers()
used = []
for i in range(len(numbers)):
if str(chr(i + 97)) in formula:
used.append(numbers[i])
i = 0
for variable in used:
paramname = self.alg.NUMBER + str(i)
self.params[paramname] = variable
i += 1
# We create a dummy harcoded value for all unused variable slots
paramname = self.alg.NUMBER + str(i)
name = self.getSafeNameForHarcodedParameter(
self.alg.getParameterFromName(paramname))
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.values[name] = 0
for i in range(len(used), self.alg.AVAILABLE_VARIABLES):
paramname = self.alg.NUMBER + str(i)
self.params[paramname] = value
self.outputs[self.alg.RESULT] = None
self.dependencies = []
return True
def getSafeNameForHarcodedParameter(self, param):
if self.algIndex is not None:
return 'HARDCODEDPARAMVALUE_' + param.name + '_' \
+ str(self.algIndex)
else:
return 'HARDCODEDPARAMVALUE_' + param.name + '_' \
+ str(len(self.model.algs))
def okPressed(self):
if self.setParamValues():
self.close()
else:
QMessageBox.critical(self, 'Unable to add algorithm',
'Wrong or missing parameter values')
self.params = None
def cancelPressed(self):
self.params = None
self.close()

File diff suppressed because it is too large Load Diff

View File

@ -31,8 +31,6 @@ from PyQt4.QtGui import *
from processing.core.AlgorithmProvider import AlgorithmProvider
from processing.core.ProcessingConfig import ProcessingConfig, Setting
from processing.core.ProcessingLog import ProcessingLog
from processing.modeler.SaveAsPythonScriptAction import \
SaveAsPythonScriptAction
from processing.modeler.ModelerUtils import ModelerUtils
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
from processing.modeler.WrongModelException import WrongModelException
@ -48,8 +46,7 @@ class ModelerAlgorithmProvider(AlgorithmProvider):
def __init__(self):
AlgorithmProvider.__init__(self)
self.actions = [CreateNewModelAction(), AddModelFromFileAction(), GetModelsAction()]
self.contextMenuActions = [EditModelAction(), DeleteModelAction(),
SaveAsPythonScriptAction()]
self.contextMenuActions = [EditModelAction(), DeleteModelAction()]
def initializeSettings(self):
AlgorithmProvider.initializeSettings(self)
@ -75,8 +72,6 @@ class ModelerAlgorithmProvider(AlgorithmProvider):
def _loadAlgorithms(self):
folder = ModelerUtils.modelsFolder()
self.loadFromFolder(folder)
folder = os.path.join(os.path.dirname(__file__), 'models')
self.loadFromFolder(folder)
def loadFromFolder(self, folder):
if not os.path.exists(folder):
@ -84,14 +79,13 @@ class ModelerAlgorithmProvider(AlgorithmProvider):
for path, subdirs, files in os.walk(folder):
for descriptionFile in files:
if descriptionFile.endswith('model'):
try:
alg = ModelerAlgorithm()
try:
fullpath = os.path.join(path, descriptionFile)
alg.openModel(fullpath)
if alg.name.strip() != '':
alg = ModelerAlgorithm.fromJsonFile(fullpath)
if alg:
alg.provider = self
self.algs.append(alg)
except WrongModelException, e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
'Could not load model ' + descriptionFile + '\n'
+ e.msg)
'Could not load model ' + descriptionFile + '\n'
+ e.msg)

View File

@ -48,74 +48,65 @@
import math
from PyQt4 import QtCore, QtGui
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem
from processing.modeler.ModelerAlgorithm import Algorithm
class ModelerArrowItem(QtGui.QGraphicsPathItem):
def __init__(self, startItem, outputIndex, endItem, paramIndex,
def __init__(self, startItem, startIndex, endItem, endIndex,
parent=None, scene=None):
super(ModelerArrowItem, self).__init__(parent, scene)
self.arrowHead = QtGui.QPolygonF()
self.paramIndex = paramIndex
self.outputIndex = outputIndex
self.myStartItem = startItem
self.myEndItem = endItem
self.endIndex = endIndex
self.startIndex = startIndex
self.startItem = startItem
self.endItem = endItem
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, False)
self.myColor = QtCore.Qt.gray
self.setPen(QtGui.QPen(self.myColor, 1, QtCore.Qt.SolidLine,
QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
self.setZValue(0)
def startItem(self):
return self.myStartItem
def endItem(self):
return self.myEndItem
def paint(self, painter, option, widget=None):
startItem = self.myStartItem
endItem = self.myEndItem
myPen = self.pen()
myPen.setColor(self.myColor)
painter.setPen(myPen)
painter.setBrush(self.myColor)
controlPoints = []
endPt = self.endItem().getLinkPointForParameter(self.paramIndex)
startPt = self.startItem().getLinkPointForOutput(self.outputIndex)
if isinstance(self.startItem().element, GeoAlgorithm):
if self.startItem().element.outputs:
controlPoints.append(startItem.pos() + startPt)
controlPoints.append(startItem.pos() + startPt
endPt = self.endItem.getLinkPointForParameter(self.endIndex)
startPt = self.startItem.getLinkPointForOutput(self.startIndex)
if isinstance(self.startItem.element, Algorithm):
if self.startIndex != -1:
controlPoints.append(self.startItem.pos() + startPt)
controlPoints.append(self.startItem.pos() + startPt
+ QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
controlPoints.append(endItem.pos() + endPt
controlPoints.append(self.endItem.pos() + endPt
- QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
controlPoints.append(endItem.pos() + endPt)
pt = QtCore.QPointF(startItem.pos() + startPt
controlPoints.append(self.endItem.pos() + endPt)
pt = QtCore.QPointF(self.startItem.pos() + startPt
+ QtCore.QPointF(-3, -3))
painter.drawEllipse(pt.x(), pt.y(), 6, 6)
pt = QtCore.QPointF(endItem.pos() + endPt +
pt = QtCore.QPointF(self.endItem.pos() + endPt +
QtCore.QPointF(-3, -3))
painter.drawEllipse(pt.x(), pt.y(), 6, 6)
else:
# Case where there is a dependency on an algorithm not
# on an output
controlPoints.append(startItem.pos() + startPt)
controlPoints.append(startItem.pos() + startPt
controlPoints.append(self.startItem.pos() + startPt)
controlPoints.append(self.startItem.pos() + startPt
+ QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
controlPoints.append(endItem.pos() + endPt
controlPoints.append(self.endItem.pos() + endPt
- QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
controlPoints.append(endItem.pos() + endPt)
controlPoints.append(self.endItem.pos() + endPt)
else:
controlPoints.append(startItem.pos())
controlPoints.append(startItem.pos()
controlPoints.append(self.startItem.pos())
controlPoints.append(self.startItem.pos()
+ QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
controlPoints.append(endItem.pos() + endPt
controlPoints.append(self.endItem.pos() + endPt
- QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
controlPoints.append(endItem.pos() + endPt)
pt = QtCore.QPointF(endItem.pos() + endPt + QtCore.QPointF(-3, -3))
controlPoints.append(self.endItem.pos() + endPt)
pt = QtCore.QPointF(self.endItem.pos() + endPt + QtCore.QPointF(-3, -3))
painter.drawEllipse(pt.x(), pt.y(), 6, 6)
path = QtGui.QPainterPath()

View File

@ -16,7 +16,7 @@
* *
***************************************************************************
"""
import json
from processing.modeler.WrongModelException import WrongModelException
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
@ -27,21 +27,20 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
import codecs
import json
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.gui.HelpEditionDialog import HelpEditionDialog
from processing.gui.ParametersDialog import ParametersDialog
from processing.gui.AlgorithmClassification import AlgorithmDecorator
from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm, Input
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
from processing.modeler.ModelerUtils import ModelerUtils
from processing.modeler.WrongModelException import WrongModelException
from processing.modeler.ModelerScene import ModelerScene
from processing.modeler.Providers import Providers
from processing.core.ProcessingLog import ProcessingLog
from processing.tools.system import *
from processing.ui.ui_DlgModeler import Ui_DlgModeler
@ -50,11 +49,14 @@ from processing.ui.ui_DlgModeler import Ui_DlgModeler
class ModelerDialog(QDialog, Ui_DlgModeler):
USE_CATEGORIES = '/Processing/UseSimplifiedInterface'
CANVAS_SIZE = 4000
def __init__(self, alg=None):
QDialog.__init__(self)
self.setupUi(self)
self.zoom = 1
self.setWindowFlags(Qt.WindowMinimizeButtonHint |
Qt.WindowMaximizeButtonHint |
@ -62,7 +64,8 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
self.tabWidget.setCurrentIndex(0)
self.scene = ModelerScene(self)
self.scene.setSceneRect(QRectF(0, 0, 4000, 4000))
self.scene.setSceneRect(QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE))
self.view.setScene(self.scene)
self.view.setAcceptDrops(True)
self.view.ensureVisible(0, 0, 10, 10)
@ -77,11 +80,11 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
if event.mimeData().hasText():
text = event.mimeData().text()
if text in ModelerParameterDefinitionDialog.paramTypes:
self.addInputOfType(text)
self.addInputOfType(text, event.pos())
else:
alg = ModelerUtils.getAlgorithm(text);
if alg is not None:
self._addAlgorithm(alg)
self._addAlgorithm(alg.getCopy(), event.pos())
event.accept()
else:
event.ignore()
@ -92,9 +95,33 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
else:
event.ignore()
def _wheelEvent(event):
self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse);
factor = 1.05
if event.delta() > 0:
factor = 1/factor
self.view.scale(factor, factor)
self.view.centerOn(event.pos().x(), event.pos().y())
self.repaintModel()
def _enterEvent(e):
QGraphicsView.enterEvent(self.view, e)
self.view.viewport().setCursor(Qt.ArrowCursor)
def _mousePressEvent(e):
QGraphicsView.mousePressEvent(self.view, e)
self.view.viewport().setCursor(Qt.ArrowCursor)
def _mouseReleaseEvent(e):
QGraphicsView.mouseReleaseEvent(self.view, e)
self.view.viewport().setCursor(Qt.ArrowCursor)
self.view.setDragMode(QGraphicsView.ScrollHandDrag);
self.view.dragEnterEvent = _dragEnterEvent
self.view.dropEvent = _dropEvent
self.view.dragMoveEvent = _dragMoveEvent
self.view.wheelEvent = _wheelEvent
self.view.enterEvent = _enterEvent
self.view.mousePressEvent = _mousePressEvent
self.view.mouseReleaseEvent = _mouseReleaseEvent
def _mimeDataInput(items):
@ -147,7 +174,6 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
self.inputsTree.doubleClicked.connect(self.addInput)
self.searchBox.textChanged.connect(self.fillAlgorithmTree)
self.algorithmTree.doubleClicked.connect(self.addAlgorithm)
self.scene.changed.connect(self.changeModel)
self.btnOpen.clicked.connect(self.openModel)
self.btnSave.clicked.connect(self.save)
@ -164,6 +190,7 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
else:
self.alg = ModelerAlgorithm()
self.alg.modelerdialog = self
self.view.centerOn(0, 0)
self.alg.setModelerView(self)
@ -174,9 +201,6 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
self.hasChanged = False
def changeModel(self):
self.hasChanged = True
def closeEvent(self, evt):
if self.hasChanged:
ret = QMessageBox.question(self, self.tr('Message'),
@ -193,42 +217,22 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
evt.accept()
def editHelp(self):
dlg = HelpEditionDialog(self.alg)
dlg = HelpEditionDialog(self.alg.getCopy())
dlg.exec_()
# We store the description string in case there were not
# saved because there was no filename defined yet
if self.alg.descriptionFile is None and dlg.descriptions:
self.help = dlg.descriptions
def runModel(self):
# TODO: enable alg cloning without saving to file
if len(self.alg.algs) == 0:
QMessageBox.warning(self, self.tr('Empty model'),
self.tr("Model doesn't contains any algorithms and/or "
"parameters and can't be executed"))
return
if self.alg.descriptionFile is None:
self.alg.descriptionFile = getTempFilename('model')
text = self.alg.serialize()
fout = open(self.alg.descriptionFile, 'w')
fout.write(text)
fout.close()
self.alg.provider = Providers.providers['model']
alg = self.alg.getCopy()
dlg = ParametersDialog(alg)
dlg.exec_()
self.alg.descriptionFile = None
alg.descriptionFile = None
else:
self.save()
if self.alg.provider is None:
# Might happen if model is opened from modeler dialog
self.alg.provider = Providers.providers['model']
alg = self.alg.getCopy()
dlg = ParametersDialog(alg)
dlg.exec_()
if self.alg.provider is None:
# Might happen if model is opened from modeler dialog
self.alg.provider = ModelerUtils.providers['model']
alg = self.alg.getCopy()
dlg = ParametersDialog(alg)
dlg.exec_()
def save(self):
self.saveModel(False)
@ -269,9 +273,6 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
self.tr('Please enter group and model names before saving'
))
return
self.alg.setPositions(self.scene.getParameterPositions(),
self.scene.getAlgorithmPositions(),
self.scene.getOutputPositions())
self.alg.name = unicode(self.textName.text())
self.alg.group = unicode(self.textGroup.text())
if self.alg.descriptionFile is not None and not saveAs:
@ -286,7 +287,7 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
filename += '.model'
self.alg.descriptionFile = filename
if filename:
text = self.alg.serialize()
text = self.alg.toJson()
try:
fout = codecs.open(filename, 'w', encoding='utf-8')
except:
@ -303,14 +304,7 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
return
fout.write(text)
fout.close()
self.update = True
# If help strings were defined before saving the model
# for the first time, we do it here.
if self.help:
with open(self.descriptionFile + '.help', 'w') as f:
json.dump(self.help, f)
self.help = None
self.update = True
QMessageBox.information(self, self.tr('Model saved'),
self.tr('Model was correctly saved.'))
@ -322,21 +316,32 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
self.tr('Processing models (*.model)')))
if filename:
try:
alg = ModelerAlgorithm()
alg.openModel(filename)
alg = ModelerAlgorithm.fromJsonFile(filename)
self.alg = alg
self.alg.setModelerView(self)
self.textGroup.setText(alg.group)
self.textName.setText(alg.name)
self.repaintModel()
if self.scene.getLastAlgorithmItem():
self.view.ensureVisible(self.scene.getLastAlgorithmItem())
#===============================================================
# if self.scene.getLastAlgorithmItem():
# self.view.ensureVisible(self.scene.getLastAlgorithmItem())
#===============================================================
self.view.centerOn(0, 0)
self.hasChanged = False
except WrongModelException, e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
'Could not load model ' + filename + '\n'
+ e.msg)
QMessageBox.critical(self, self.tr('Could not open model'),
self.tr('The selected model could not be loaded.\n'
'Wrong line: %s') % e.msg)
'See the log for more information.'))
except Exception, e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
'Could not load model ' + filename + '\n'
+ e.args[0])
QMessageBox.critical(self, self.tr('Could not open model'),
self.tr('The selected model could not be loaded.\n'
'See the log for more information.'))
def repaintModel(self):
self.scene = ModelerScene()
@ -349,27 +354,41 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
def addInput(self):
item = self.inputsTree.currentItem()
paramType = str(item.text(0))
self.addInputOfType(paramType)
self.addInputOfType(paramType)
def addInputOfType(self, paramType):
def addInputOfType(self, paramType, pos=None):
if paramType in ModelerParameterDefinitionDialog.paramTypes:
dlg = ModelerParameterDefinitionDialog(self.alg, paramType)
dlg.exec_()
if dlg.param is not None:
self.alg.setPositions(self.scene.getParameterPositions(),
self.scene.getAlgorithmPositions(),
self.scene.getOutputPositions())
self.alg.addParameter(dlg.param)
if pos is None:
pos = self.getPositionForParameterItem()
if isinstance(pos, QPoint):
pos = QPointF(pos)
self.alg.addParameter(Input(dlg.param, pos))
self.repaintModel()
self.view.ensureVisible(self.scene.getLastParameterItem())
#self.view.ensureVisible(self.scene.getLastParameterItem())
self.hasChanged = True
def getPositionForParameterItem(self):
MARGIN = 20
BOX_WIDTH = 200
BOX_HEIGHT = 80
if self.alg.inputs:
maxX = max([i.pos.x() for i in self.alg.inputs.values()])
newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH)
else:
newX = MARGIN + BOX_WIDTH / 2
return QPointF(newX, MARGIN + BOX_HEIGHT / 2)
def fillInputsTree(self):
icon = QIcon(os.path.dirname(__file__) + '/../images/input.png')
parametersItem = QTreeWidgetItem()
parametersItem.setText(0, self.tr('Parameters'))
for paramType in ModelerParameterDefinitionDialog.paramTypes:
paramItem = QTreeWidgetItem()
paramItem.setText(0, paramType)
paramItem.setIcon(0, icon)
paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled)
parametersItem.addChild(paramItem)
self.inputsTree.addTopLevelItem(parametersItem)
@ -379,23 +398,44 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
item = self.algorithmTree.currentItem()
if isinstance(item, TreeAlgorithmItem):
alg = ModelerUtils.getAlgorithm(item.alg.commandLineName())
self._addAlgorithm(alg)
self._addAlgorithm(alg.getCopy())
def _addAlgorithm(self, alg):
alg = alg.getCopy()
def _addAlgorithm(self, alg, pos=None):
dlg = alg.getCustomModelerParametersDialog(self.alg)
if not dlg:
dlg = ModelerParametersDialog(alg, self.alg)
dlg.exec_()
if dlg.params is not None:
self.alg.setPositions(self.scene.getParameterPositions(),
self.scene.getAlgorithmPositions(),
self.scene.getOutputPositions())
self.alg.addAlgorithm(alg, dlg.params, dlg.values,
dlg.outputs, dlg.dependencies)
if dlg.alg is not None:
if pos is None:
dlg.alg.pos = self.getPositionForAlgorithmItem()
else:
dlg.alg.pos = pos
if isinstance(dlg.alg.pos, QPoint):
dlg.alg.pos = QPointF(pos)
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem
for i, out in enumerate(dlg.alg.outputs):
dlg.alg.outputs[out].pos = dlg.alg.pos + QPointF(ModelerGraphicItem.BOX_WIDTH, (i + 1.5)
* ModelerGraphicItem.BOX_HEIGHT)
self.alg.addAlgorithm(dlg.alg)
self.repaintModel()
self.view.ensureVisible(self.scene.getLastAlgorithmItem())
self.hasChanged = False
#self.view.ensureVisible(self.scene.getLastAlgorithmItem())
self.hasChanged = True
def getPositionForAlgorithmItem(self):
MARGIN = 20
BOX_WIDTH = 200
BOX_HEIGHT = 80
if self.alg.algs:
maxX = max([alg.pos.x() for alg in self.alg.algs.values()])
maxY = max([alg.pos.y() for alg in self.alg.algs.values()])
newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH)
newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE
- BOX_HEIGHT)
else:
newX = MARGIN + BOX_WIDTH / 2
newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2
return QPointF(newX, newY)
def fillAlgorithmTree(self):
settings = QSettings()
@ -416,14 +456,14 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
self.algorithmTree.clear()
text = unicode(self.searchBox.text())
groups = {}
allAlgs = ModelerUtils.getAlgorithms()
allAlgs = ModelerUtils.allAlgs
for providerName in allAlgs.keys():
provider = allAlgs[providerName]
name = 'ACTIVATE_' + providerName.upper().replace(' ', '_')
if not ProcessingConfig.getSetting(name):
continue
if providerName in providersToExclude \
or len(Providers.providers[providerName].actions) != 0:
or len(ModelerUtils.providers[providerName].actions) != 0:
continue
algs = provider.values()
@ -494,9 +534,9 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
if len(groups) > 0:
providerItem = QTreeWidgetItem()
providerItem.setText(0,
Providers.providers[providerName].getDescription())
ModelerUtils.providers[providerName].getDescription())
providerItem.setIcon(0,
Providers.providers[providerName].getIcon())
ModelerUtils.providers[providerName].getIcon())
providerItem.setToolTip(0, providerItem.text(0))
for groupItem in groups.values():
providerItem.addChild(groupItem)
@ -509,7 +549,7 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
def fillAlgorithmTreeUsingProviders(self):
self.algorithmTree.clear()
text = unicode(self.searchBox.text())
allAlgs = ModelerUtils.getAlgorithms()
allAlgs = ModelerUtils.allAlgs
for providerName in allAlgs.keys():
groups = {}
provider = allAlgs[providerName]
@ -533,11 +573,11 @@ class ModelerDialog(QDialog, Ui_DlgModeler):
if len(groups) > 0:
providerItem = QTreeWidgetItem()
providerItem.setText(0,
Providers.providers[providerName].getDescription())
ModelerUtils.providers[providerName].getDescription())
providerItem.setToolTip(0,
Providers.providers[providerName].getDescription())
ModelerUtils.providers[providerName].getDescription())
providerItem.setIcon(0,
Providers.providers[providerName].getIcon())
ModelerUtils.providers[providerName].getIcon())
for groupItem in groups.values():
providerItem.addChild(groupItem)
self.algorithmTree.addTopLevelItem(providerItem)

View File

@ -17,6 +17,7 @@
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
@ -27,8 +28,7 @@ __revision__ = '$Format:%H$'
import os
from PyQt4 import QtCore, QtGui
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.parameters.Parameter import Parameter
from processing.modeler.ModelerAlgorithm import Input, Algorithm, Output
from processing.modeler.ModelerParameterDefinitionDialog import \
ModelerParameterDefinitionDialog
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
@ -39,36 +39,31 @@ class ModelerGraphicItem(QtGui.QGraphicsItem):
BOX_HEIGHT = 30
BOX_WIDTH = 200
def __init__(self, element, elementIndex, model):
def __init__(self, element, model):
super(ModelerGraphicItem, self).__init__(None, None)
self.model = model
self.element = element
self.elementIndex = elementIndex
self.inputFolded = True
self.outputFolded = True
if isinstance(element, Parameter):
if isinstance(element, Input):
icon = QtGui.QIcon(os.path.dirname(__file__)
+ '/../images/input.png')
self.pixmap = icon.pixmap(20, 20, state=QtGui.QIcon.On)
self.text = element.description
elif isinstance(element, basestring):
self.text = element.param.description
elif isinstance(element, Output):
# Output name
icon = QtGui.QIcon(os.path.dirname(__file__)
+ '/../images/output.png')
self.pixmap = icon.pixmap(20, 20, state=QtGui.QIcon.On)
self.text = element
self.text = element.description
else:
state = QtGui.QIcon.On
if self.elementIndex in self.model.deactivated:
state = QtGui.QIcon.Off
self.text = element.name
self.pixmap = element.getIcon().pixmap(15, 15, state=state)
self.text = element.description
self.pixmap = element.algorithm.getIcon().pixmap(15, 15)
self.arrows = []
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges, True)
self.setZValue(1000)
if not isinstance(element, basestring):
if not isinstance(element, Output):
icon = QtGui.QIcon(os.path.dirname(__file__)
+ '/../images/edit.png')
pt = QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH / 2
@ -87,32 +82,30 @@ class ModelerGraphicItem(QtGui.QGraphicsItem):
self.removeElement)
self.deleteButton.setParentItem(self)
if isinstance(element, GeoAlgorithm):
if element.parameters:
pt = self.getLinkPointForParameter(-1)
x = self.getXPositionForFoldButton()
pt = QtCore.QPointF(x, pt.y() + 2)
self.inButton = FoldButtonGraphicItem(pt, self.foldInput)
if isinstance(element, Algorithm):
alg = element.algorithm
if alg.parameters:
pt = self.getLinkPointForParameter(-1)
pt = QtCore.QPointF(0, pt.y() + 2)
self.inButton = FoldButtonGraphicItem(pt, self.foldInput, self.element.paramsFolded)
self.inButton.setParentItem(self)
if element.outputs:
if alg.outputs:
pt = self.getLinkPointForOutput(-1)
x = self.getXPositionForFoldButton()
pt = QtCore.QPointF(x, pt.y() + 2)
self.outButton = FoldButtonGraphicItem(pt, self.foldOutput)
pt = QtCore.QPointF(0, pt.y() + 2)
self.outButton = FoldButtonGraphicItem(pt, self.foldOutput, self.element.outputsFolded)
self.outButton.setParentItem(self)
def foldInput(self, folded):
self.inputFolded = folded
self.element.paramsFolded = folded
self.prepareGeometryChange()
if self.element.outputs:
if self.element.algorithm.outputs:
pt = self.getLinkPointForOutput(-1)
x = self.getXPositionForFoldButton()
pt = QtCore.QPointF(x, pt.y())
pt = QtCore.QPointF(0, pt.y())
self.outButton.position = pt
self.update()
def foldOutput(self, folded):
self.outputFolded = folded
self.element.outputsFolded = folded
self.prepareGeometryChange()
self.update()
@ -122,8 +115,11 @@ class ModelerGraphicItem(QtGui.QGraphicsItem):
def boundingRect(self):
font = QtGui.QFont('Verdana', 8)
fm = QtGui.QFontMetricsF(font)
numParams = (0 if self.inputFolded else len(self.element.parameters))
numOutputs = (0 if self.outputFolded else len(self.element.outputs))
unfolded = isinstance(self.element, Algorithm) and not self.element.paramsFolded
numParams = len(self.element.algorithm.parameters) if unfolded else 0
unfolded = isinstance(self.element, Algorithm) and not self.element.outputsFolded
numOutputs = len(self.element.algorithm.outputs) if unfolded else 0
hUp = fm.height() * 1.2 * (numParams + 2)
hDown = fm.height() * 1.2 * (numOutputs + 2)
rect = QtCore.QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2,
@ -136,13 +132,15 @@ class ModelerGraphicItem(QtGui.QGraphicsItem):
self.editElement()
def contextMenuEvent(self, event):
if isinstance(self.element, Output):
return
popupmenu = QtGui.QMenu()
removeAction = popupmenu.addAction('Remove')
removeAction.triggered.connect(self.removeElement)
editAction = popupmenu.addAction('Edit')
editAction.triggered.connect(self.editElement)
if isinstance(self.element, GeoAlgorithm):
if self.elementIndex in self.model.deactivated:
editAction.triggered.connect(self.editElement)
if isinstance(self.element, Algorithm):
if not self.element.active:
removeAction = popupmenu.addAction('Activate')
removeAction.triggered.connect(self.activateAlgorithm)
else:
@ -151,56 +149,52 @@ class ModelerGraphicItem(QtGui.QGraphicsItem):
popupmenu.exec_(event.screenPos())
def deactivateAlgorithm(self):
self.model.setPositions(self.scene().getParameterPositions(),
self.scene().getAlgorithmPositions(),
self.scene().getOutputPositions())
self.model.deactivateAlgorithm(self.elementIndex, True)
self.model.deactivateAlgorithm(self.element.name)
self.model.updateModelerView()
def activateAlgorithm(self):
self.model.setPositions(self.scene().getParameterPositions(),
self.scene().getAlgorithmPositions(),
self.scene().getOutputPositions())
if not self.model.activateAlgorithm(self.elementIndex, True):
if self.model.activateAlgorithm(self.element.name):
self.model.updateModelerView()
else:
QtGui.QMessageBox.warning(None, 'Could not activate Algorithm',
'The selected algorithm depends on other currently \
non-active algorithms.\nActivate them them before trying \
to activate it.')
'The selected algorithm depends on other currently non-active algorithms.\n'
'Activate them them before trying to activate it.')
def editElement(self):
self.model.setPositions(self.scene().getParameterPositions(),
self.scene().getAlgorithmPositions(),
self.scene().getOutputPositions())
if isinstance(self.element, Parameter):
if isinstance(self.element, Input):
dlg = ModelerParameterDefinitionDialog(self.model,
param=self.element)
param=self.element.param)
dlg.exec_()
if dlg.param is not None:
self.model.updateParameter(self.elementIndex, dlg.param)
self.element = dlg.param
self.text = self.element.description
self.model.updateParameter(dlg.param)
self.element.param = dlg.param
self.text = dlg.param.description
self.update()
elif isinstance(self.element, GeoAlgorithm):
dlg = self.element.getCustomModelerParametersDialog(self.model,
self.elementIndex)
elif isinstance(self.element, Algorithm):
dlg = self.element.algorithm.getCustomModelerParametersDialog(self.model, self.element.name)
if not dlg:
dlg = ModelerParametersDialog(self.element, self.model,
self.elementIndex)
dlg = ModelerParametersDialog(self.element.algorithm, self.model, self.element.name)
dlg.exec_()
if dlg.params is not None:
self.model.updateAlgorithm(self.elementIndex, dlg.params,
dlg.values, dlg.outputs, dlg.dependencies)
if dlg.alg is not None:
dlg.alg.name = self.element.name
self.model.updateAlgorithm(dlg.alg)
self.model.updateModelerView()
def removeElement(self):
if isinstance(self.element, Parameter):
if not self.model.removeParameter(self.elementIndex):
if isinstance(self.element, Input):
if not self.model.removeParameter(self.element.param.name):
QtGui.QMessageBox.warning(None, 'Could not remove element',
'Other elements depend on the selected one.\nRemove \
them before trying to remove it.')
elif isinstance(self.element, GeoAlgorithm):
if not self.model.removeAlgorithm(self.elementIndex):
'Other elements depend on the selected one.\n'
'Remove them before trying to remove it.')
else:
self.model.updateModelerView()
elif isinstance(self.element, Algorithm):
if not self.model.removeAlgorithm(self.element.name):
QtGui.QMessageBox.warning(None, 'Could not remove element',
'Other elements depend on the selected one.\nRemove \
them before trying to remove it.')
'Other elements depend on the selected one.\n'
'Remove them before trying to remove it.')
else:
self.model.updateModelerView()
def getAdjustedText(self, text):
font = QtGui.QFont('Verdana', 8)
@ -223,34 +217,35 @@ class ModelerGraphicItem(QtGui.QGraphicsItem):
ModelerGraphicItem.BOX_HEIGHT + 2)
painter.setPen(QtGui.QPen(QtCore.Qt.gray, 1))
color = QtGui.QColor(125, 232, 232)
if isinstance(self.element, Parameter):
if isinstance(self.element, Input):
color = QtGui.QColor(179, 179, 255)
elif isinstance(self.element, GeoAlgorithm):
elif isinstance(self.element, Algorithm):
color = QtCore.Qt.white
painter.setBrush(QtGui.QBrush(color, QtCore.Qt.SolidPattern))
painter.drawRect(rect)
font = QtGui.QFont('Verdana', 8)
painter.setFont(font)
painter.setPen(QtGui.QPen(QtCore.Qt.black))
if self.isSelected():
text = self.getAdjustedText(self.text)
if isinstance(self.element, Algorithm) and not self.element.active:
painter.setPen(QtGui.QPen(QtCore.Qt.gray))
text = text + "\n(deactivated)"
elif self.isSelected():
painter.setPen(QtGui.QPen(QtCore.Qt.blue))
if isinstance(self.element, GeoAlgorithm):
if self.elementIndex in self.model.deactivated:
painter.setPen(QtGui.QPen(QtCore.Qt.lightGray))
fm = QtGui.QFontMetricsF(font)
text = self.getAdjustedText(self.text)
h = fm.height()
pt = QtCore.QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h / 2.0)
painter.drawText(pt, text)
painter.setPen(QtGui.QPen(QtCore.Qt.black))
if isinstance(self.element, GeoAlgorithm):
if isinstance(self.element, Algorithm):
h = -(fm.height() * 1.2)
h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5
pt = QtCore.QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h)
painter.drawText(pt, 'In')
i = 1
if not self.inputFolded:
for param in self.element.parameters:
if not self.element.paramsFolded:
for param in self.element.algorithm.parameters:
if not param.hidden:
text = self.getAdjustedText(param.description)
h = -(fm.height() * 1.2) * (i + 1)
@ -258,63 +253,59 @@ class ModelerGraphicItem(QtGui.QGraphicsItem):
pt = QtCore.QPointF(-ModelerGraphicItem.BOX_WIDTH / 2
+ 33, h)
painter.drawText(pt, text)
i += 1
i = 1
i += 1
h = fm.height() * 1.2
h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0
pt = QtCore.QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h)
painter.drawText(pt, 'Out')
if not self.outputFolded:
for out in self.element.outputs:
if not out.hidden:
if not self.element.outputsFolded:
for i, out in enumerate(self.element.algorithm.outputs):
text = self.getAdjustedText(out.description)
h = fm.height() * 1.2 * (i + 1)
h = fm.height() * 1.2 * (i + 2)
h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0
pt = QtCore.QPointF(-ModelerGraphicItem.BOX_WIDTH / 2
+ 33, h)
painter.drawText(pt, text)
i += 1
if self.pixmap:
painter.drawPixmap(-(ModelerGraphicItem.BOX_WIDTH / 2.0) + 3, -8,
self.pixmap)
def getLinkPointForParameter(self, paramIndex):
offsetX = 25
if self.inputFolded:
if isinstance(self.element, Algorithm) and self.element.paramsFolded:
paramIndex = -1
offsetX = 17
font = QtGui.QFont('Verdana', 8)
fm = QtGui.QFontMetricsF(font)
if isinstance(self.element, GeoAlgorithm):
if isinstance(self.element, Algorithm):
h = -(fm.height() * 1.2) * (paramIndex + 2) - fm.height() / 2.0 + 8
h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0
else:
h = 0
return QtCore.QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + offsetX, h)
def getXPositionForFoldButton(self):
return 0
def getLinkPointForOutput(self, outputIndex):
if isinstance(self.element, GeoAlgorithm):
outputIndex = (outputIndex if not self.outputFolded else -1)
if isinstance(self.element, Algorithm):
outputIndex = (outputIndex if not self.element.outputsFolded else -1)
text = self.getAdjustedText(
self.element.outputs[outputIndex].description)
self.element.algorithm.outputs[outputIndex].description)
font = QtGui.QFont('Verdana', 8)
fm = QtGui.QFontMetricsF(font)
w = fm.width(text)
h = fm.height() * 1.2 * (outputIndex + 1) + fm.height() / 2.0
y = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5
x = (-ModelerGraphicItem.BOX_WIDTH / 2 + 33 + w
+ 5 if not self.outputFolded else 10)
+ 5 if not self.element.outputsFolded else 10)
return QtCore.QPointF(x, y)
else:
return QtCore.QPointF(0, 0)
def itemChange(self, change, value):
if change == QtGui.QGraphicsItem.ItemPositionChange:
if change == QtGui.QGraphicsItem.ItemPositionHasChanged:
for arrow in self.arrows:
arrow.updatePosition()
arrow.updatePosition()
self.element.pos = self.pos()
return value
@ -399,9 +390,9 @@ class FoldButtonGraphicItem(FlatButtonGraphicItem):
False: QtGui.QIcon(os.path.dirname(__file__)
+ '/../images/minus.png')}
def __init__(self, position, action):
self.folded = True
icon = self.icons[True]
def __init__(self, position, action, folded):
self.folded = folded
icon = self.icons[self.folded]
super(FoldButtonGraphicItem, self).__init__(icon, position, action)
def mousePressEvent(self, event):

View File

@ -26,8 +26,6 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from processing.parameters.Parameter import Parameter
from processing.parameters.ParameterBoolean import ParameterBoolean
from processing.parameters.ParameterRaster import ParameterRaster
@ -120,11 +118,11 @@ class ModelerParameterDefinitionDialog(QtGui.QDialog):
self.horizontalLayout2.addWidget(QtGui.QLabel('Parent layer'))
self.parentCombo = QtGui.QComboBox()
idx = 0
for param in self.alg.parameters:
if isinstance(param, (ParameterVector, ParameterTable)):
self.parentCombo.addItem(param.description, param.name)
for param in self.alg.inputs.values():
if isinstance(param.param, (ParameterVector, ParameterTable)):
self.parentCombo.addItem(param.param.description, param.param.name)
if self.param is not None:
if self.param.parent == param.name:
if self.param.parent == param.param.name:
self.parentCombo.setCurrentIndex(idx)
idx += 1
self.horizontalLayout2.addWidget(self.parentCombo)
@ -241,9 +239,9 @@ class ModelerParameterDefinitionDialog(QtGui.QDialog):
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel
| QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName('buttonBox')
QObject.connect(self.buttonBox, QtCore.SIGNAL('accepted()'),
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL('accepted()'),
self.okPressed)
QObject.connect(self.buttonBox, QtCore.SIGNAL('rejected()'),
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL('rejected()'),
self.cancelPressed)
self.verticalLayout.addWidget(self.buttonBox)
@ -253,7 +251,7 @@ class ModelerParameterDefinitionDialog(QtGui.QDialog):
def okPressed(self):
description = unicode(self.nameTextBox.text())
if description.strip() == '':
QMessageBox.critical(self, 'Unable to define parameter',
QtGui.QMessageBox.warning(self, 'Unable to define parameter',
'Invalid parameter name')
return
if self.param is None:
@ -273,7 +271,7 @@ class ModelerParameterDefinitionDialog(QtGui.QDialog):
== ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD \
or isinstance(self.param, ParameterTableField):
if self.parentCombo.currentIndex() < 0:
QMessageBox.critical(self, 'Unable to define parameter',
QtGui.QMessageBox.warning(self, 'Unable to define parameter',
'Wrong or missing parameter values')
return
parent = self.parentCombo.itemData(self.parentCombo.currentIndex())
@ -317,7 +315,7 @@ class ModelerParameterDefinitionDialog(QtGui.QDialog):
self.param = ParameterNumber(name, description, vmin, vmax,
float(str(self.defaultTextBox.text())))
except:
QMessageBox.critical(self, 'Unable to define parameter',
QtGui.QMessageBox.warning(self, 'Unable to define parameter',
'Wrong or missing parameter values')
return
elif self.paramType \

View File

@ -28,13 +28,13 @@ __revision__ = '$Format:%H$'
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore, QtGui, QtWebKit
from processing.modeler.ModelerAlgorithm import ValueFromInput,\
ValueFromOutput, Algorithm, Output
from processing.core.WrongHelpFileException import WrongHelpFileException
from processing.gui.CrsSelectionPanel import CrsSelectionPanel
from processing.gui.MultipleInputPanel import MultipleInputPanel
from processing.gui.FixedTablePanel import FixedTablePanel
from processing.gui.RangePanel import RangePanel
from processing.modeler.ModelerAlgorithm import AlgorithmAndParameter
from processing.modeler.MultilineTextPanel import MultilineTextPanel
from processing.parameters.ParameterCrs import ParameterCrs
from processing.parameters.ParameterRaster import ParameterRaster
@ -67,12 +67,17 @@ class ModelerParametersDialog(QtGui.QDialog):
NOT_SELECTED = '[Not selected]'
USE_MIN_COVERING_EXTENT = '[Use min covering extent]'
def __init__(self, alg, model, algIndex=None):
def __init__(self, alg, model, algName=None):
QtGui.QDialog.__init__(self)
self.setModal(True)
self.alg = alg
#The algorithm to define in this dialog. It is an instance of GeoAlgorithm
self._alg = alg
#The resulting algorithm after the user clicks on OK. it is an instance of the container Algorithm class
self.alg = None
#The model this algorithm is going to be added to
self.model = model
self.algIndex = algIndex
#The name of the algorithm in the model, in case we are editing it and not defining it for the first time
self._algName = algName
self.setupUi()
self.params = None
@ -88,13 +93,28 @@ class ModelerParametersDialog(QtGui.QDialog):
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel
| QtGui.QDialogButtonBox.Ok)
tooltips = self.alg.getParameterDescriptions()
tooltips = self._alg.getParameterDescriptions()
self.setSizePolicy(QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setSpacing(5)
self.verticalLayout.setMargin(20)
for param in self.alg.parameters:
hLayout = QtGui.QHBoxLayout()
hLayout.setSpacing(5)
hLayout.setMargin(0)
descriptionLabel = QtGui.QLabel("Description")
self.descriptionBox = QtGui.QLineEdit()
self.descriptionBox.setText(self._alg.name)
hLayout.addWidget(descriptionLabel)
hLayout.addWidget(self.descriptionBox)
self.verticalLayout.addLayout(hLayout)
line = QtGui.QFrame()
line.setFrameShape(QtGui.QFrame.HLine)
line.setFrameShadow(QtGui.QFrame.Sunken)
self.verticalLayout.addWidget(line)
for param in self._alg.parameters:
if param.isAdvanced:
self.advancedButton = QtGui.QPushButton()
self.advancedButton.setText('Show advanced parameters')
@ -104,7 +124,7 @@ class ModelerParametersDialog(QtGui.QDialog):
self.showAdvancedParametersClicked)
self.verticalLayout.addWidget(self.advancedButton)
break
for param in self.alg.parameters:
for param in self._alg.parameters:
if param.hidden:
continue
desc = param.description
@ -127,7 +147,7 @@ class ModelerParametersDialog(QtGui.QDialog):
self.verticalLayout.addWidget(label)
self.verticalLayout.addWidget(widget)
for output in self.alg.outputs:
for output in self._alg.outputs:
if output.hidden:
continue
if isinstance(output, (OutputRaster, OutputVector, OutputTable,
@ -152,7 +172,7 @@ class ModelerParametersDialog(QtGui.QDialog):
self.setLayout(self.verticalLayout)
self.setPreviousValues()
self.setWindowTitle(self.alg.name)
self.setWindowTitle(self._alg.name)
self.verticalLayout2 = QtGui.QVBoxLayout()
self.verticalLayout2.setSpacing(2)
self.verticalLayout2.setMargin(0)
@ -169,7 +189,7 @@ class ModelerParametersDialog(QtGui.QDialog):
html = None
url = None
try:
isText, help = self.alg.help()
isText, help = self._alg.help()
if help is not None:
if isText:
html = help;
@ -198,16 +218,14 @@ class ModelerParametersDialog(QtGui.QDialog):
QtCore.QMetaObject.connectSlotsByName(self)
def getAvailableDependencies(self):
if self.algIndex is None:
if self._algName is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
dependent = self.model.getDependentAlgorithms(self._algName)
opts = []
i = 0
for alg in self.model.algs:
if i not in dependent:
opts.append(str(i + 1) + ':' + alg.name)
i += 1
for alg in self.model.algs.values():
if alg.name not in dependent:
opts.append(alg.algorithm.name)
return opts
def getDependenciesPanel(self):
@ -219,235 +237,70 @@ class ModelerParametersDialog(QtGui.QDialog):
self.advancedButton.setText('Hide advanced parameters')
else:
self.advancedButton.setText('Show advanced parameters')
for param in self.alg.parameters:
for param in self._alg.parameters:
if param.isAdvanced:
self.labels[param.name].setVisible(self.showAdvanced)
self.widgets[param.name].setVisible(self.showAdvanced)
def getRasterLayers(self):
layers = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterRaster):
layers.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
def getAvailableValuesOfType(self, paramType, outType = None):
values = []
inputs = self.model.inputs
for i in inputs.values():
param = i.param
if isinstance(param, paramType):
values.append(ValueFromInput(param.name))
if outType is None:
return values
if self._algName is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
dependent = self.model.getDependentAlgorithms(self._algName)
for alg in self.model.algs.values():
if alg.name not in dependent:
for out in alg.algorithm.outputs:
if isinstance(out, outType):
values.append(ValueFromOutput(alg.name, out.name))
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputRaster):
layers.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return layers
def getVectorLayers(self):
layers = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterVector):
layers.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
dependent = []
return values
def resolveValueDescription(self, value):
if isinstance(value, ValueFromInput):
return self.model.inputs[value.name].param.description
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
alg = self.model.algs[value.alg]
return "'%s' from algorithm '%s'" % (alg.algorithm.getOutputFromName(value.output).description, alg.description)
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputVector):
layers.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return layers
def getTables(self):
tables = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterTable):
tables.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputTable):
tables.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return tables
def getExtents(self):
extents = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterExtent):
extents.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputExtent):
extents.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return extents
def getNumbers(self):
numbers = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterNumber):
numbers.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputNumber):
numbers.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return numbers
def getFiles(self):
files = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterFile):
files.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputFile):
files.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return files
def getBooleans(self):
booleans = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterBoolean):
booleans.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
return booleans
def getStrings(self):
strings = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterString):
strings.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
if self.algIndex is None:
dependent = []
else:
dependent = self.model.getDependentAlgorithms(self.algIndex)
i = 0
for alg in self.model.algs:
if i not in dependent:
for out in alg.outputs:
if isinstance(out, OutputString):
strings.append(AlgorithmAndParameter(i, out.name,
alg.name, out.description))
i += 1
return strings
def getTableFields(self):
strings = []
params = self.model.parameters
for param in params:
if isinstance(param, ParameterTableField):
strings.append(AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM,
param.name, '', param.description))
return strings
def getWidgetFromParameter(self, param):
if isinstance(param, ParameterRaster):
item = QtGui.QComboBox()
layers = self.getRasterLayers()
layers = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
if param.optional:
item.addItem(self.NOT_SELECTED, None)
for layer in layers:
item.addItem(layer.name(), layer)
item.addItem(self.resolveValueDescription(layer), layer)
elif isinstance(param, ParameterVector):
item = QtGui.QComboBox()
layers = self.getVectorLayers()
layers = self.getAvailableValuesOfType(ParameterVector, OutputVector)
if param.optional:
item.addItem(self.NOT_SELECTED, None)
for layer in layers:
item.addItem(layer.name(), layer)
item.addItem(self.resolveValueDescription(layer), layer)
elif isinstance(param, ParameterTable):
item = QtGui.QComboBox()
item.setEditable(True)
layers = self.getTables()
layers = self.getAvailableValuesOfType(ParameterTable, OutputTable)
if param.optional:
item.addItem(self.NOT_SELECTED, None)
for layer in layers:
item.addItem(layer.name(), layer)
item.addItem(self.resolveValueDescription(layer), layer)
elif isinstance(param, ParameterBoolean):
item = QtGui.QComboBox()
item.addItem('Yes')
item.addItem('No')
bools = self.getBooleans()
bools = self.getAvailableValuesOfType(ParameterBoolean, None)
for b in bools:
item.addItem(b.name(), b)
item.addItem(self.resolveValueDescription(b), b)
elif isinstance(param, ParameterSelection):
item = QtGui.QComboBox()
item.addItems(param.options)
@ -457,15 +310,15 @@ class ModelerParametersDialog(QtGui.QDialog):
item = RangePanel(param)
elif isinstance(param, ParameterMultipleInput):
if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
options = self.getVectorLayers()
options = self.getAvailableValuesOfType(ParameterVector, OutputVector)
else:
options = self.getRasterLayers()
options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
opts = []
for opt in options:
opts.append(opt.name())
opts.append(self.resolveValueDescription(opt))
item = MultipleInputPanel(opts)
elif isinstance(param, ParameterString):
strings = self.getStrings()
strings = self.getAvailableValuesOfType(ParameterString, OutputString)
if param.multiline:
item = MultilineTextPanel(strings, self.model)
item.setText(str(param.default))
@ -473,31 +326,31 @@ class ModelerParametersDialog(QtGui.QDialog):
item = QtGui.QComboBox()
item.setEditable(True)
for s in strings:
item.addItem(s.name(), s)
item.addItem(self.resolveValueDescription(s), s)
item.setEditText(str(param.default))
elif isinstance(param, ParameterTableField):
item = QtGui.QComboBox()
item.setEditable(True)
fields = self.getTableFields()
fields = self.getAvailableValuesOfType(ParameterTableField, None)
for f in fields:
item.addItem(f.name(), f)
item.addItem(self.resolveValueDescription(f), f)
elif isinstance(param, ParameterNumber):
item = QtGui.QComboBox()
item.setEditable(True)
numbers = self.getNumbers()
numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
for n in numbers:
item.addItem(n.name(), n)
item.addItem(self.resolveValueDescription(n), n)
item.setEditText(str(param.default))
elif isinstance(param, ParameterCrs):
item = CrsSelectionPanel(param.default)
elif isinstance(param, ParameterExtent):
item = QtGui.QComboBox()
item.setEditable(True)
extents = self.getExtents()
extents = self.getAvailableValuesOfType(ParameterExtent, OutputExtent)
if self.canUseAutoExtent():
item.addItem(self.USE_MIN_COVERING_EXTENT, None)
for ex in extents:
item.addItem(ex.name(), ex)
item.addItem(self.resolveValueDescription(ex), ex)
if not self.canUseAutoExtent():
item.setEditText(str(param.default))
elif isinstance(param, ParameterFile):
@ -505,7 +358,7 @@ class ModelerParametersDialog(QtGui.QDialog):
item.setEditable(True)
files = self.getFiles()
for f in files:
item.addItem(f.name(), f)
item.addItem(self.resolveValueDescription(f), f)
else:
item = QtGui.QLineEdit()
try:
@ -515,81 +368,72 @@ class ModelerParametersDialog(QtGui.QDialog):
return item
def canUseAutoExtent(self):
for param in self.alg.parameters:
if isinstance(param, (ParameterRaster, ParameterVector)):
return True
if isinstance(param, ParameterMultipleInput):
for param in self._alg.parameters:
if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)):
return True
return False
def setTableContent(self):
params = self.alg.parameters
outputs = self.alg.outputs
numParams = 0
for param in params:
if not param.hidden:
numParams += 1
numOutputs = 0
for output in outputs:
if not output.hidden:
numOutputs += 1
self.tableWidget.setRowCount(numParams + numOutputs)
params = self._alg.parameters
outputs = self._alg.outputs
visibleParams = [p for p in params if not p.hidden]
visibleOutputs = [p for o in outputs if not o.hidden]
self.tableWidget.setRowCount(len(visibleParams) + len(visibleOutputs))
for i, param in visibleParams:
item = QtGui.QTableWidgetItem(param.description)
item.setFlags(QtCore.Qt.ItemIsEnabled)
self.tableWidget.setItem(i, 0, item)
item = self.getWidgetFromParameter(param)
self.valueItems[param.name] = item
self.tableWidget.setCellWidget(i, 1, item)
self.tableWidget.setRowHeight(i, 22)
i = 0
for param in params:
if not param.hidden:
item = QtGui.QTableWidgetItem(param.description)
item.setFlags(QtCore.Qt.ItemIsEnabled)
self.tableWidget.setItem(i, 0, item)
item = self.getWidgetFromParameter(param)
self.valueItems[param.name] = item
self.tableWidget.setCellWidget(i, 1, item)
self.tableWidget.setRowHeight(i, 22)
i += 1
for output in outputs:
if not output.hidden:
item = QtGui.QTableWidgetItem(output.description + '<'
+ output.__module__.split('.')[-1] + '>')
item.setFlags(QtCore.Qt.ItemIsEnabled)
self.tableWidget.setItem(i, 0, item)
item = QLineEdit()
if hasattr(item, 'setPlaceholderText'):
item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME)
self.valueItems[output.name] = item
self.tableWidget.setCellWidget(i, 1, item)
self.tableWidget.setRowHeight(i, 22)
i += 1
for i, output in visibleOutputs:
item = QtGui.QTableWidgetItem(output.description + '<'
+ output.__module__.split('.')[-1] + '>')
item.setFlags(QtCore.Qt.ItemIsEnabled)
self.tableWidget.setItem(i, 0, item)
item = QLineEdit()
if hasattr(item, 'setPlaceholderText'):
item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME)
self.valueItems[output.name] = item
self.tableWidget.setCellWidget(i, 1, item)
self.tableWidget.setRowHeight(i, 22)
def setComboBoxValue(self, combo, value, param):
if isinstance(value, list):
value = value[0]
print param.name
print value
items = [combo.itemData(i) for i in range(combo.count())]
idx = 0
for item in items:
if item and value:
if item.alg == value.alg and item.param == value.param:
combo.setCurrentIndex(idx)
return
idx += 1
if combo.isEditable():
value = self.model.getValueFromAlgorithmAndParameter(value)
if value:
combo.setEditText(str(value))
elif isinstance(param, ParameterSelection):
value = self.model.getValueFromAlgorithmAndParameter(value)
print items
try:
idx = items.index(value)
combo.setCurrentIndex(idx)
return
except ValueError:
pass
if combo.isEditable():
if value is not None:
combo.setEditText(unicode(value))
elif isinstance(param, ParameterSelection):
combo.setCurrentIndex(int(value))
elif isinstance(param, ParameterBoolean):
value = self.model.getValueFromAlgorithmAndParameter(value) \
== str(True)
elif isinstance(param, ParameterBoolean):
if value:
combo.setCurrentIndex(0)
else:
combo.setCurrentIndex(1)
def setPreviousValues(self):
if self.algIndex is not None:
for (name, value) in \
self.model.algParameters[self.algIndex].items():
widget = self.valueItems[name]
param = self.alg.getParameterFromName(name)
def setPreviousValues(self):
if self._algName is not None:
alg = self.model.algs[self._algName]
self.descriptionBox.setText(alg.description)
for param in alg.algorithm.parameters:
if param.hidden:
continue
widget = self.valueItems[param.name]
value = alg.params[param.name]
if isinstance(param, (
ParameterRaster,
ParameterVector,
@ -607,210 +451,140 @@ class ModelerParametersDialog(QtGui.QDialog):
else:
self.setComboBoxValue(widget, value, param)
elif isinstance(param, ParameterCrs):
value = self.model.getValueFromAlgorithmAndParameter(value)
widget.setAuthid(value)
elif isinstance(param, ParameterFixedTable):
pass
pass #TODO!
elif isinstance(param, ParameterMultipleInput):
value = self.model.getValueFromAlgorithmAndParameter(value)
values = value.split(';')
selectedoptions = []
if param.datatype \
== ParameterMultipleInput.TYPE_VECTOR_ANY:
options = self.getVectorLayers()
if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
options = self.getAvailableValuesOfType(ParameterVector, OutputVector)
else:
options = self.getRasterLayers()
for i in range(len(options)):
option = options[i]
for aap in values:
if str(option) == aap:
selectedoptions.append(i)
widget.setSelectedItems(selectedoptions)
else:
pass
options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
selected = []
for i, opt in enumerate(options):
if opt in value:
selected.append(i)
widget.setSelectedItems(selected)
for out in self.alg.outputs:
if not out.hidden:
value = self.model.algOutputs[self.algIndex][out.name]
if value is not None:
widget = \
self.valueItems[out.name].setText(unicode(value))
for name, out in alg.outputs.iteritems():
widget = self.valueItems[name].setText(out.description)
selected = []
dependencies = self.getAvailableDependencies()
index = -1
for dependency in dependencies:
index += 1
n = int(dependency[:dependency.find(':')]) - 1
if n in self.model.dependencies[self.algIndex]:
selected.append(index)
for idx, dependency in enumerate(dependencies):
if dependency in alg.dependencies:
selected.append(idx)
self.dependenciesPanel.setSelectedItems(selected)
def setParamValues(self):
self.params = {}
self.values = {}
self.outputs = {}
params = self.alg.parameters
outputs = self.alg.outputs
def createAlgorithm(self):
alg = Algorithm(self._alg.commandLineName())
alg.setName(self.model)
alg.description = self.descriptionBox.text()
params = self._alg.parameters
outputs = self._alg.outputs
for param in params:
if param.hidden:
continue
if not self.setParamValue(param, self.valueItems[param.name]):
return False
if not self.setParamValue(alg, param, self.valueItems[param.name]):
return None
for output in outputs:
if output.hidden:
self.outputs[output.name] = None
else:
if not output.hidden:
name = unicode(self.valueItems[output.name].text())
if name.strip() != '' and name \
!= ModelerParametersDialog.ENTER_NAME:
self.outputs[output.name] = name
else:
self.outputs[output.name] = None
if name.strip() != '' and name != ModelerParametersDialog.ENTER_NAME:
alg.outputs[output.name] = Output(name)
selectedOptions = self.dependenciesPanel.selectedoptions
# This index are based on the list of available dependencies.
# we translate them into indices based on the whole set of
# algorithm in the model. We just take the values in the
# beginning of the string representing the algorithm.
availableDependencies = self.getAvailableDependencies()
self.dependencies = []
for selected in selectedOptions:
s = availableDependencies[selected]
n = int(s[:s.find(':')]) - 1
self.dependencies.append(n)
alg.dependencies.append(s)
return True
return alg
def setParamValueLayerOrTable(self, param, widget):
def setParamValueLayerOrTable(self, alg, param, widget):
idx = widget.currentIndex()
if idx < 0:
return False
else:
value = widget.itemData(widget.currentIndex())
self.params[param.name] = value
alg.params[param.name] = value
return True
def setParamBooleanValue(self, param, widget):
if widget.currentIndex() < 2:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = str(widget.currentIndex() == 0)
else:
value = widget.itemData(widget.currentIndex())
self.params[param.name] = value
return True
def setParamTableFieldValue(self, param, widget):
def setParamTableFieldValue(self, alg, param, widget):
idx = widget.findText(widget.currentText())
if idx < 0:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
if idx < 0:
s = str(widget.currentText()).strip()
if s == '':
if param.optional:
self.params[param.name] = None
alg.params[param.name] = None
return True
else:
return False
else:
self.params[param.name] = value
self.values[name] = str(widget.currentText())
else:
alg.values[param.name] = s
return True
else:
value = widget.itemData(widget.currentIndex())
self.params[param.name] = value
alg.params[param.name] = widget.itemData(widget.currentIndex())
return True
def setParamStringValue(self, param, widget):
if param.multiline:
name = self.getSafeNameForHarcodedParameter(param)
paramValue = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
def setParamStringValue(self, alg, param, widget):
if param.multiline:
value = widget.getValue()
option = widget.getOption()
if option == MultilineTextPanel.USE_TEXT:
if value == '':
if param.optional:
self.params[param.name] = None
alg.params[param.name] = None
return True
else:
return False
else:
self.values[name] = value
self.params[param.name] = paramValue
alg.params[param.name] = value
else:
self.params[param.name] = value
else:
#if widget.currentText() == '':
# return False
alg.params[param.name] = value
else:
idx = widget.findText(widget.currentText())
if idx < 0:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
value = str(widget.currentText()).strip()
if idx < 0:
value = widget.currentText().strip()
if value == '':
if param.optional:
self.values[name] = None
alg.params[param.name] = None
return True
else:
return False
else:
self.values[name] = str(widget.currentText())
alg.params[param.name] = value
else:
value = widget.itemData(widget.currentIndex())
self.params[param.name] = value
alg.params[param.name] = widget.itemData(widget.currentIndex())
return True
def setParamFileValue(self, param, widget):
def setParamFileValue(self, alg, param, widget):
idx = widget.findText(widget.currentText())
if idx < 0:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
s = str(widget.currentText())
self.values[name] = s
if idx < 0:
value = widget.currentText()
else:
value = widget.itemData(widget.currentIndex())
self.params[param.name] = value
alg.params[param.name] = value
return True
def setParamNumberValue(self, param, widget):
def setParamNumberValue(self, alg, param, widget):
idx = widget.findText(widget.currentText())
if idx < 0:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
s = str(widget.currentText())
if idx < 0:
s = widget.currentText()
try:
float(s)
self.values[name] = s
value = float(s)
except:
return False
else:
value = widget.itemData(widget.currentIndex())
self.params[param.name] = value
alg.params[param.name] = value
return True
def setParamExtentValue(self, param, widget):
def setParamExtentValue(self, alg, param, widget):
idx = widget.findText(widget.currentText())
if idx < 0:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
if idx < 0:
s = str(widget.currentText())
try:
tokens = s.split(',')
@ -819,101 +593,72 @@ class ModelerParametersDialog(QtGui.QDialog):
for token in tokens:
float(token)
except:
return False
self.values[name] = s
return False
alg.params[param.name] = [s]
else:
value = widget.itemData(widget.currentIndex())
self.params[param.name] = value
alg.params[param.name] = value
return True
def setParamValue(self, param, widget):
def setParamValue(self, alg, param, widget):
if isinstance(param, (ParameterRaster, ParameterVector,
ParameterTable)):
return self.setParamValueLayerOrTable(param, widget)
return self.setParamValueLayerOrTable(alg, param, widget)
elif isinstance(param, ParameterBoolean):
return self.setParamBooleanValue(param, widget)
if widget.currentIndex() < 2:
value = widget.currentIndex() == 0
else:
value = widget.itemData(widget.currentIndex())
alg.params[param.name] = value
return True
elif isinstance(param, ParameterString):
return self.setParamStringValue(param, widget)
return self.setParamStringValue(alg, param, widget)
elif isinstance(param, ParameterNumber):
return self.setParamNumberValue(param, widget)
return self.setParamNumberValue(alg, param, widget)
elif isinstance(param, ParameterExtent):
return self.setParamExtentValue(param, widget)
return self.setParamExtentValue(alg, param, widget)
elif isinstance(param, ParameterFile):
return self.setParamFileValue(param, widget)
return self.setParamFileValue(alg, param, widget)
elif isinstance(param, ParameterSelection):
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = str(widget.currentIndex())
return True
alg.params[param.name] = widget.currentIndex()
return True
elif isinstance(param, ParameterRange):
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = str(widget.getValue())
return True
alg.params[param.name] = widget.getValue()
return True
elif isinstance(param, ParameterCrs):
authid = widget.getValue()
if authid is None:
self.params[param.name] = None
alg.params[param.name] = None
else:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = authid
alg.params[param.name] = authid
return True
elif isinstance(param, ParameterFixedTable):
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = ParameterFixedTable.tableToString(widget.table)
return True
alg.params[param.name] = ParameterFixedTable.tableToString(widget.table)
return True
elif isinstance(param, ParameterTableField):
return self.setParamTableFieldValue(param, widget)
return self.setParamTableFieldValue(alg, param, widget)
elif isinstance(param, ParameterMultipleInput):
if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
options = self.getVectorLayers()
options = self.getAvailableValuesOfType(ParameterVector, OutputVector)
else:
options = self.getRasterLayers()
values = []
for index in widget.selectedoptions:
values.append(options[index].serialize())
options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
values = [options[i] for i in widget.selectedoptions]
if len(values) == 0 and not param.optional:
return False
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = ';'.join(values)
return False
alg.params[param.name] = values
return True
else:
name = self.getSafeNameForHarcodedParameter(param)
value = AlgorithmAndParameter(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM, name)
self.params[param.name] = value
self.values[name] = unicode(widget.text())
alg.params[param.name] = unicode(widget.text())
return True
def getSafeNameForHarcodedParameter(self, param):
if self.algIndex is None:
return 'HARDCODEDPARAMVALUE_' + param.name + '_' \
+ str(len(self.model.algs))
else:
return 'HARDCODEDPARAMVALUE_' + param.name + '_' \
+ str(self.algIndex)
def okPressed(self):
if self.setParamValues():
self.alg = self.createAlgorithm()
if self.alg is not None:
self.close()
else:
QMessageBox.critical(self, 'Unable to add algorithm',
'Wrong or missing parameter values')
self.params = None
QMessageBox.warning(self, 'Unable to add algorithm',
'Wrong or missing parameter values')
def cancelPressed(self):
self.params = None
self.alg = None
self.close()

View File

@ -17,6 +17,7 @@
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
@ -26,160 +27,118 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from processing.modeler.ModelerAlgorithm import AlgorithmAndParameter
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem
from processing.modeler.ModelerArrowItem import ModelerArrowItem
from processing.parameters.ParameterMultipleInput import ParameterMultipleInput
from processing.modeler.ModelerAlgorithm import ValueFromInput, ValueFromOutput
class ModelerScene(QtGui.QGraphicsScene):
def __init__(self, parent=None):
super(ModelerScene, self).__init__(parent)
self.paramItems = []
self.algItems = []
self.outputItems = []
self.paramItems = {}
self.algItems = {}
self.outputItems = {}
self.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
def getParameterPositions(self):
pos = []
for item in self.paramItems:
pos.append(item.pos())
return pos
return {key : item.pos() for key,item in self.paramItems.iteritems()}
def getAlgorithmPositions(self):
pos = []
for item in self.algItems:
pos.append(item.pos())
return pos
return {key : item.pos() for key,item in self.algItems.iteritems()}
def getOutputPositions(self):
pos = []
for alg in self.outputItems:
pos = {}
for algName, outputs in self.outputItems.iteritems():
outputPos = {}
for (key, value) in alg.iteritems():
for (key, value) in outputs.iteritems():
if value is not None:
outputPos[key] = value.pos()
else:
outputPos[key] = None
pos.append(outputPos)
pos[algName] = outputPos
return pos
def getLastParameterItem(self):
return self.paramItems[-1]
def getLastAlgorithmItem(self):
if self.algItems:
return self.algItems[-1]
else:
return None
def getItemsFromAAP(self, aap, isMultiple):
def getItemsFromParamValue(self, value):
items = []
start = int(aap.alg)
if aap.alg == AlgorithmAndParameter.PARENT_MODEL_ALGORITHM:
if isMultiple:
multi = self.model.paramValues[aap.param]
tokens = multi.split(';')
for token in tokens:
aap = AlgorithmAndParameter(float(token.split('|')[0]),
token.split('|')[1])
ret = self.getItemsFromAAP(aap, False)
if ret:
for item in ret:
items.append(item)
else:
iModelParam = 0
for modelparam in self.model.parameters:
if modelparam.name == aap.param:
items.append((self.paramItems[iModelParam], -1))
break
iModelParam += 1
else:
idx = 0
for output in self.model.algs[start].outputs:
if output.name == aap.param:
items.append((self.algItems[start], idx))
break
idx += 1
return items
if isinstance(value, list):
for v in value:
items.extend(self.getItemsFromParamValue(v))
elif isinstance(value, ValueFromInput):
items.append((self.paramItems[value.name], 0))
elif isinstance(value, ValueFromOutput):
outputs = self.model.algs[value.alg].algorithm.outputs
for i, out in enumerate(outputs):
if out.name == value.output:
break
items.append((self.algItems[value.alg], i))
return items
def paintModel(self, model):
self.model = model
i = 0
# Inputs
for param in model.parameters:
item = ModelerGraphicItem(param, i, model)
for inp in model.inputs.values():
item = ModelerGraphicItem(inp, model)
item.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
item.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.addItem(item)
item.setPos(model.paramPos[i])
self.paramItems.append(item)
i += 1
item.setPos(inp.pos.x(), inp.pos.y())
self.paramItems[inp.param.name] = item
# We add the algs
iAlg = 0
for alg in model.algs:
item = ModelerGraphicItem(alg, iAlg, model)
# We add the algs
for alg in model.algs.values():
item = ModelerGraphicItem(alg, model)
item.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
item.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.addItem(item)
item.setPos(model.algPos[iAlg])
self.algItems.append(item)
iAlg += 1
item.setPos(alg.pos.x(), alg.pos.y())
self.algItems[alg.name] = item
# And then the arrows
iAlg = 0
for alg in model.algs:
params = model.algParameters[iAlg]
for alg in model.algs.values():
idx = 0
for parameter in alg.parameters:
for parameter in alg.algorithm.parameters:
if not parameter.hidden:
param = params[parameter.name]
if param:
sourceItems = self.getItemsFromAAP(param,
isinstance(alg.getParameterFromName(parameter.name), ParameterMultipleInput))
for sourceItem in sourceItems:
arrow = ModelerArrowItem(sourceItem[0], sourceItem[1], self.algItems[iAlg], idx)
self.addItem(arrow)
value = alg.params[parameter.name]
sourceItems = self.getItemsFromParamValue(value)
for sourceItem, sourceIdx in sourceItems:
arrow = ModelerArrowItem(sourceItem, sourceIdx, self.algItems[alg.name], idx)
self.addItem(arrow)
idx += 1
for depend in model.dependencies[iAlg]:
for depend in alg.dependencies:
arrow = ModelerArrowItem(self.algItems[depend], -1,
self.algItems[iAlg], -1)
self.algItems[alg.name], -1)
self.addItem(arrow)
iAlg += 1
# And finally the outputs
for (iAlg, alg) in enumerate(model.algs):
outputs = model.algOutputs[iAlg]
for alg in model.algs.values():
outputs = alg.outputs
outputItems = {}
for (idx, key) in enumerate(outputs.keys()):
idx = 0
for key in outputs:
out = outputs[key]
if out is not None:
item = ModelerGraphicItem(out, idx, model)
item = ModelerGraphicItem(out, model)
item.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
item.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.addItem(item)
pos = model.outputPos[iAlg][key]
pos = alg.outputs[key].pos
if pos is None:
pos = self.algItems[iAlg].pos() \
+ QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH, 0) \
+ self.algItems[iAlg].getLinkPointForOutput(idx)
pos = (alg.pos() + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH, 0)
+ self.algItems[alg.name].getLinkPointForOutput(idx))
item.setPos(pos)
outputItems[key] = item
arrow = ModelerArrowItem(self.algItems[iAlg], idx, item,
arrow = ModelerArrowItem(self.algItems[alg.name], idx, item,
-1)
self.addItem(arrow)
idx += 1
else:
outputItems[key] = None
self.outputItems.append(outputItems)
self.outputItems[alg.name] = outputItems
def mousePressEvent(self, mouseEvent):
if mouseEvent.button() != QtCore.Qt.LeftButton:
return
super(ModelerScene, self).mousePressEvent(mouseEvent)

View File

@ -31,6 +31,9 @@ from processing.core.ProcessingConfig import ProcessingConfig
class ModelerUtils:
allAlgs = {}
providers = {}
MODELS_FOLDER = 'MODELS_FOLDER'
ACTIVATE_MODELS = 'ACTIVATE_MODELS'
@ -51,6 +54,3 @@ class ModelerUtils:
return provider[name]
return None
@staticmethod
def getAlgorithms():
return ModelerUtils.allAlgs

View File

@ -63,15 +63,11 @@ class MultilineTextPanel(QtGui.QWidget):
return self.combo.itemData(self.combo.currentIndex())
def setValue(self, value):
items = [self.combo.itemData(i) for i in range(1, self.combo.count())]
idx = 0
for item in items:
idx += 1
if item and value:
if item.alg == value.alg and item.param == value.param:
self.combo.setCurrentIndex(idx)
return
self.combo.setCurrentIndex(0)
value = self.model.getValueFromAlgorithmAndParameter(value)
items = [self.combo.itemData(i) for i in range(1, self.combo.count())]
for idx, item in enumerate(items):
if item == value:
self.combo.setCurrentIndex(idx)
return
self.combo.setCurrentIndex(0)
if value:
self.textBox.setPlainText(str(value))
self.textBox.setPlainText(value)

View File

@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
Providers.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
class Providers:
providers = {}

View File

@ -1,126 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
SaveAsPythonScriptAction.py
---------------------
Date : April 2013
Copyright : (C) 2013 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'April 2013'
__copyright__ = '(C) 2013, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from processing.gui.ContextAction import ContextAction
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm, \
AlgorithmAndParameter
from processing.script.ScriptUtils import ScriptUtils
from processing.parameters.ParameterMultipleInput import ParameterMultipleInput
class SaveAsPythonScriptAction(ContextAction):
def __init__(self):
self.name = 'Save as Python script'
def isEnabled(self):
return isinstance(self.alg, ModelerAlgorithm)
def execute(self):
filename = str(QFileDialog.getSaveFileName(None, 'Save Script',
ScriptUtils.scriptsFolder(), 'Python scripts (*.py)'))
if filename:
if not filename.endswith('.py'):
filename += '.py'
text = self.translateToPythonCode(self.alg)
try:
fout = open(filename, 'w')
fout.write(text)
fout.close()
if filename.replace('\\', '/').startswith(
ScriptUtils.scriptsFolder().replace('\\', '/')):
self.toolbox.updateProvider('script')
except:
QMessageBox.warning(self, self.tr('I/O error'),
self.tr('Unable to save edits. Reason:\n %s')
% unicode(sys.exc_info()[1]))
def translateToPythonCode(self, model):
s = ['##' + model.name + '=name']
for param in model.parameters:
s.append(str(param.getAsScriptCode().lower()))
i = 0
for outs in model.algOutputs:
for out in outs.keys():
if outs[out]:
s.append('##' + out.lower() + '_alg' + str(i) + '='
+ model.getOutputType(i, out))
i += 1
i = 0
iMultiple = 0
for alg in model.algs:
multiple = []
runline = 'outputs_' + str(i) + '=processing.runalg("' \
+ alg.commandLineName() + '"'
for param in alg.parameters:
aap = model.algParameters[i][param.name]
if aap is None:
runline += ', None'
elif isinstance(param, ParameterMultipleInput):
value = model.paramValues[aap.param]
tokens = value.split(';')
layerslist = []
for token in tokens:
(iAlg, paramname) = token.split('|')
if float(iAlg) == float(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM):
if model.ismodelparam(paramname):
value = paramname.lower()
else:
value = model.paramValues[paramname]
else:
value = 'outputs_' + str(iAlg) + "['" + paramname \
+ "']"
layerslist.append(str(value))
multiple.append('multiple_' + str(iMultiple) + '=['
+ ','.join(layerslist) + ']')
runline += ', ";".join(multiple_' + str(iMultiple) + ') '
else:
if float(aap.alg) == float(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM):
if model.ismodelparam(aap.param):
runline += ', ' + aap.param.lower()
else:
runline += ', ' + str(model.paramValues[aap.param])
else:
runline += ', outputs_' + str(aap.alg) + "['" \
+ aap.param + "']"
for out in alg.outputs:
value = model.algOutputs[i][out.name]
if value:
name = out.name.lower() + '_alg' + str(i)
else:
name = str(None)
runline += ', ' + name
i += 1
s += multiple
s.append(str(runline + ')'))
return '\n'.join(s)

View File

@ -1,21 +0,0 @@
NAME:Extract raster values (CSV)
GROUP:[Example models]
PARAMETER:ParameterVector|VECTORLAYER_INPUTVECTOR|Input vector|-1|False
114.0,29.0
PARAMETER:ParameterRaster|RASTERLAYER_INPUTRASTER|Input raster|False
333.0,30.0
PARAMETER:ParameterBoolean|BOOLEAN_REPROJECTVECTORTORASTERCRS|Reproject vector to raster CRS|False
552.0,31.0
ALGORITHM:script:pointsfromvector
123.0,146.0
None
-1|RASTERLAYER_INPUTRASTER
-1|VECTORLAYER_INPUTVECTOR
None
ALGORITHM:script:extractrastervaluestocsv
398.0,201.0
None
-1|RASTERLAYER_INPUTRASTER
0|Output_layer
-1|BOOLEAN_REPROJECTVECTORTORASTERCRS
Output CSV file|555.0,284.0

View File

@ -1,21 +0,0 @@
NAME:Extract raster values (shapefile)
GROUP:[Example models]
PARAMETER:ParameterVector|VECTORLAYER_INPUTVECTOR|Input vector|-1|False
114.0,29.0
PARAMETER:ParameterRaster|RASTERLAYER_INPUTRASTER|Input raster|False
333.0,30.0
PARAMETER:ParameterBoolean|BOOLEAN_REPROJECTVECTORTORASTERCRS|Reproject vector to raster CRS|False
552.0,31.0
ALGORITHM:script:pointsfromvector
123.0,146.0
None
-1|RASTERLAYER_INPUTRASTER
-1|VECTORLAYER_INPUTVECTOR
None
ALGORITHM:script:extractrastervaluestoshapefile
343.0,246.0
None
-1|RASTERLAYER_INPUTRASTER
0|Output_layer
-1|BOOLEAN_REPROJECTVECTORTORASTERCRS
Output layer|533.0,321.0

View File

@ -1,43 +0,0 @@
NAME:Contour lines from points
GROUP:[Example models]
PARAMETER:ParameterVector|VECTORLAYER_SHAPES|Shapes|-1|False
120.0,60.0
PARAMETER:ParameterNumber|NUMBER_INTERVAL|Interval|0.0|None|10.0
633.0,163.0
PARAMETER:ParameterNumber|NUMBER_CELLSIZEFORINTERMEDIATELAYER|Cellsize for intermediate layer|0.0|None|10.0
411.0,84.0
PARAMETER:ParameterTableField|TABLEFIELD_FIELD|Field|VECTORLAYER_SHAPES|-1|False
104.0,202.0
VALUE:HARDCODEDPARAMVALUE_LINE_TYPE_0===0
VALUE:HARDCODEDPARAMVALUE_ZMAX_2===10000.0
VALUE:HARDCODEDPARAMVALUE_USER_SIZE_0===1.0
VALUE:HARDCODEDPARAMVALUE_ZMIN_2===0.0
VALUE:HARDCODEDPARAMVALUE_THRESHOLD_1===0.1
VALUE:HARDCODEDPARAMVALUE_MULTIPLE_0===0
VALUE:HARDCODEDPARAMVALUE_GRID_TYPE_0===3
ALGORITHM:saga:shapestogrid
348.0,211.0
None
-1|VECTORLAYER_SHAPES
-1|TABLEFIELD_FIELD
-1|HARDCODEDPARAMVALUE_MULTIPLE_0
-1|HARDCODEDPARAMVALUE_LINE_TYPE_0
-1|HARDCODEDPARAMVALUE_GRID_TYPE_0
None
-1|NUMBER_CELLSIZEFORINTERMEDIATELAYER
None
ALGORITHM:saga:closegaps
450.0,379.0
None
0|USER_GRID
None
-1|HARDCODEDPARAMVALUE_THRESHOLD_1
None
ALGORITHM:saga:contourlinesfromgrid
630.0,279.0
None
1|RESULT
-1|HARDCODEDPARAMVALUE_ZMIN_2
-1|HARDCODEDPARAMVALUE_ZMAX_2
-1|NUMBER_INTERVAL
Contour lines

View File

@ -1,20 +0,0 @@
NAME:A model with an empty string
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_V|v|-1|False
120.0,60.0
VALUE:HARDCODEDPARAMVALUE_FORMULA_0===value = 10
VALUE:HARDCODEDPARAMVALUE_FIELD_PRECISION_0===0
VALUE:HARDCODEDPARAMVALUE_FIELD_TYPE_0===0
VALUE:HARDCODEDPARAMVALUE_FIELD_LENGTH_0===10
VALUE:HARDCODEDPARAMVALUE_FIELD_NAME_0===NewField
ALGORITHM:qgis:advancedpythonfieldcalculator
120.0,160.0
None
-1|VECTORLAYER_V
-1|HARDCODEDPARAMVALUE_FIELD_NAME_0
-1|HARDCODEDPARAMVALUE_FIELD_TYPE_0
-1|HARDCODEDPARAMVALUE_FIELD_LENGTH_0
-1|HARDCODEDPARAMVALUE_FIELD_PRECISION_0
None
-1|HARDCODEDPARAMVALUE_FORMULA_0
out

View File

@ -1,21 +0,0 @@
NAME:Model using field input and autoextent
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_VECTOR|vector|2|False
120.0,60.0
PARAMETER:ParameterTableField|TABLEFIELD_FIELD|field|VECTORLAYER_VECTOR|-1|False
340.0,60.0
VALUE:HARDCODEDPARAMVALUE_LINE_TYPE_0===0
VALUE:HARDCODEDPARAMVALUE_GRID_TYPE_0===3
VALUE:HARDCODEDPARAMVALUE_MULTIPLE_0===0
VALUE:HARDCODEDPARAMVALUE_USER_SIZE_0===10
ALGORITHM:saga:shapestogrid
207.0,202.0
None
-1|VECTORLAYER_VECTOR
-1|TABLEFIELD_FIELD
-1|HARDCODEDPARAMVALUE_MULTIPLE_0
-1|HARDCODEDPARAMVALUE_LINE_TYPE_0
-1|HARDCODEDPARAMVALUE_GRID_TYPE_0
None
-1|HARDCODEDPARAMVALUE_USER_SIZE_0
grid

View File

@ -1,23 +0,0 @@
NAME:Model using field input and extent input
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_LAYER|layer|-1|False
120.0,60.0
PARAMETER:ParameterExtent|EXTENT_EXTENT|extent|0,1,0,1
340.0,60.0
PARAMETER:ParameterTableField|TABLEFIELD_FIELD|field|VECTORLAYER_LAYER|-1|False
560.0,60.0
VALUE:HARDCODEDPARAMVALUE_LINE_TYPE_0===0
VALUE:HARDCODEDPARAMVALUE_GRID_TYPE_0===3
VALUE:HARDCODEDPARAMVALUE_MULTIPLE_0===0
VALUE:HARDCODEDPARAMVALUE_USER_SIZE_0===25
ALGORITHM:saga:shapestogrid
338.0,247.0
None
-1|VECTORLAYER_LAYER
-1|TABLEFIELD_FIELD
-1|HARDCODEDPARAMVALUE_MULTIPLE_0
-1|HARDCODEDPARAMVALUE_LINE_TYPE_0
-1|HARDCODEDPARAMVALUE_GRID_TYPE_0
-1|EXTENT_EXTENT
-1|HARDCODEDPARAMVALUE_USER_SIZE_0
rasterized

View File

@ -1,26 +0,0 @@
NAME:A model with a script
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_VECTOR|vector|-1|False
238.0,94.0
VALUE:HARDCODEDPARAMVALUE_DY_1===0.0
VALUE:HARDCODEDPARAMVALUE_ANGLE_1===0.0
VALUE:HARDCODEDPARAMVALUE_SCALEX_1===1.0
VALUE:HARDCODEDPARAMVALUE_ANCHORX_1===0.0
VALUE:HARDCODEDPARAMVALUE_ANCHORY_1===0.0
VALUE:HARDCODEDPARAMVALUE_SCALEY_1===1.0
ALGORITHM:script:ascriptthatreturnsanumber
546.0,150.0
None
None
ALGORITHM:saga:transformshapes
310.0,304.0
None
-1|VECTORLAYER_VECTOR
0|number
-1|HARDCODEDPARAMVALUE_DY_1
-1|HARDCODEDPARAMVALUE_ANGLE_1
-1|HARDCODEDPARAMVALUE_SCALEX_1
-1|HARDCODEDPARAMVALUE_SCALEY_1
-1|HARDCODEDPARAMVALUE_ANCHORX_1
-1|HARDCODEDPARAMVALUE_ANCHORY_1
displaced

View File

@ -1,27 +0,0 @@
NAME:A model without inputs
GROUP:[Test models]
VALUE:HARDCODEDPARAMVALUE_HSPACING_0===10.0
VALUE:HARDCODEDPARAMVALUE_CENTERY_0===0.0
VALUE:HARDCODEDPARAMVALUE_CRS_0===EPSG:4326
VALUE:HARDCODEDPARAMVALUE_HEIGHT_0===180.0
VALUE:HARDCODEDPARAMVALUE_GRIDTYPE_0===0
VALUE:HARDCODEDPARAMVALUE_CENTERX_0===0.0
VALUE:HARDCODEDPARAMVALUE_WIDTH_0===360.0
VALUE:HARDCODEDPARAMVALUE_VSPACING_0===10.0
ALGORITHM:qgis:creategrid
113.0,48.0
None
-1|HARDCODEDPARAMVALUE_HSPACING_0
-1|HARDCODEDPARAMVALUE_VSPACING_0
-1|HARDCODEDPARAMVALUE_WIDTH_0
-1|HARDCODEDPARAMVALUE_HEIGHT_0
-1|HARDCODEDPARAMVALUE_CENTERX_0
-1|HARDCODEDPARAMVALUE_CENTERY_0
-1|HARDCODEDPARAMVALUE_GRIDTYPE_0
-1|HARDCODEDPARAMVALUE_CRS_0
None
ALGORITHM:qgis:polygoncentroids
333.0,148.0
None
0|SAVENAME
centroids|531.0,259.0

View File

@ -1,39 +0,0 @@
NAME:Model with algorithms not in running order
GROUP:[Test models]
PARAMETER:ParameterRaster|RASTERLAYER_RASTER|raster|False
120.0,60.0
VALUE:HARDCODEDPARAMVALUE_MINSLOPE_1===0.01
VALUE:HARDCODEDPARAMVALUE_Method_0===0
VALUE:HARDCODEDPARAMVALUE_STEP_0===1
VALUE:HARDCODEDPARAMVALUE_DOLINEAR _0===True
VALUE:HARDCODEDPARAMVALUE_LINEARTHRS_0===500.0
VALUE:HARDCODEDPARAMVALUE_CONVERGENCE_0===1.0
ALGORITHM:saga:catchmentareaparallel
154.0,415.0
None
1|RESULT
None
None
None
None
-1|HARDCODEDPARAMVALUE_STEP_0
-1|HARDCODEDPARAMVALUE_Method_0
-1|HARDCODEDPARAMVALUE_DOLINEAR _0
-1|HARDCODEDPARAMVALUE_LINEARTHRS_0
None
None
-1|HARDCODEDPARAMVALUE_CONVERGENCE_0
catchment area
None
None
None
None
None
None
None
ALGORITHM:saga:fillsinks
340.0,260.0
None
-1|RASTERLAYER_RASTER
-1|HARDCODEDPARAMVALUE_MINSLOPE_1
None

View File

@ -1,32 +0,0 @@
NAME:Model using numerical output
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_LAYER|layer|-1|False
120.0,60.0
PARAMETER:ParameterTableField|TABLEFIELD_FIELD|field|VECTORLAYER_LAYER|-1|False
340.0,60.0
VALUE:HARDCODEDPARAMVALUE_SEGMENTS_1===5
VALUE:HARDCODEDPARAMVALUE_DISSOLVE_1===True
ALGORITHM:qgis:basicstatisticsfornumericfields
343.0,220.0
None
-1|VECTORLAYER_LAYER
-1|TABLEFIELD_FIELD
None
None
None
None
None
None
None
None
None
None
None
ALGORITHM:qgis:fixeddistancebuffer
120.0,327.0
None
-1|VECTORLAYER_LAYER
0|MEAN
-1|HARDCODEDPARAMVALUE_SEGMENTS_1
-1|HARDCODEDPARAMVALUE_DISSOLVE_1
buffer

View File

@ -1,12 +0,0 @@
NAME:A model with an optional field
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_V|v|-1|False
120.0,60.0
VALUE:HARDCODEDPARAMVALUE_METHOD_0===0
ALGORITHM:qgis:convexhull
135.0,186.0
None
-1|VECTORLAYER_V
None
-1|HARDCODEDPARAMVALUE_METHOD_0
result

View File

@ -1,29 +0,0 @@
NAME:A SAGA and GRASS model
GROUP:[Test models]
PARAMETER:ParameterVector|VECTORLAYER_VECTOR|vector|-1|False
120.0,60.0
VALUE:HARDCODEDPARAMVALUE_GRASS_MIN_AREA_PARAMETER_0===0.0001
VALUE:HARDCODEDPARAMVALUE_GRASS_SNAP_TOLERANCE_PARAMETER_0===-1.0
VALUE:HARDCODEDPARAMVALUE_METHOD _1===False
VALUE:HARDCODEDPARAMVALUE_-c_0===True
VALUE:HARDCODEDPARAMVALUE_tolerance_0===0.01
VALUE:HARDCODEDPARAMVALUE_-s_0===True
VALUE:HARDCODEDPARAMVALUE_distance_0===2
ALGORITHM:grass:v.buffer.distance
120.0,160.0
None
-1|VECTORLAYER_VECTOR
-1|HARDCODEDPARAMVALUE_distance_0
-1|HARDCODEDPARAMVALUE_tolerance_0
-1|HARDCODEDPARAMVALUE_-s_0
-1|HARDCODEDPARAMVALUE_-c_0
None
-1|HARDCODEDPARAMVALUE_GRASS_SNAP_TOLERANCE_PARAMETER_0
-1|HARDCODEDPARAMVALUE_GRASS_MIN_AREA_PARAMETER_0
None
ALGORITHM:saga:polygoncentroids
340.0,260.0
None
0|output
-1|HARDCODEDPARAMVALUE_METHOD _1
output

View File

@ -1,15 +0,0 @@
NAME:A basic model
GROUP:[Test models]
PARAMETER:ParameterRaster|RASTERLAYER_RASTER|raster|False
120.0,60.0
VALUE:HARDCODEDPARAMVALUE_METHOD_0===5
ALGORITHM:saga:slopeaspectcurvature
120.0,160.0
None
-1|RASTERLAYER_RASTER
-1|HARDCODEDPARAMVALUE_METHOD_0
slope
None
None
None
None

View File

@ -1,79 +0,0 @@
NAME:Watershed from DEM and threshold
GROUP:[Example models]
PARAMETER:ParameterRaster|RASTERLAYER_DEM|DEM|False
233.0,49.0
PARAMETER:ParameterNumber|NUMBER_THRESHOLDFORCHANNELDEFINITION|Threshold for channel definition|0.0|None|1000000.0
330.0,411.0
VALUE:HARDCODEDPARAMVALUE_Method_1===0
VALUE:HARDCODEDPARAMVALUE_MINSLOPE_0===0.01
VALUE:HARDCODEDPARAMVALUE_SPLIT_4===1
VALUE:HARDCODEDPARAMVALUE_CLASS_ID_4===0
VALUE:HARDCODEDPARAMVALUE_INIT_METHOD_2===2
VALUE:HARDCODEDPARAMVALUE_STEP_1===1
VALUE:HARDCODEDPARAMVALUE_DOLINEAR _1===True
VALUE:HARDCODEDPARAMVALUE_MINSIZE_3===0
VALUE:HARDCODEDPARAMVALUE_CLASS_ALL_4===1
VALUE:HARDCODEDPARAMVALUE_LINEARTHRS_1===500.0
VALUE:HARDCODEDPARAMVALUE_DIV_CELLS_2===10
VALUE:HARDCODEDPARAMVALUE_CONVERGENCE_1===1.0
VALUE:HARDCODEDPARAMVALUE_MINLEN_2===10
ALGORITHM:saga:fillsinks
120.0,160.0
None
-1|RASTERLAYER_DEM
-1|HARDCODEDPARAMVALUE_MINSLOPE_0
None
ALGORITHM:saga:catchmentareaparallel
119.0,285.0
None
0|RESULT
None
None
None
None
-1|HARDCODEDPARAMVALUE_STEP_1
-1|HARDCODEDPARAMVALUE_Method_1
-1|HARDCODEDPARAMVALUE_DOLINEAR _1
-1|HARDCODEDPARAMVALUE_LINEARTHRS_1
None
None
-1|HARDCODEDPARAMVALUE_CONVERGENCE_1
None
None
None
None
None
None
None
None
ALGORITHM:saga:channelnetwork
398.0,283.0
None
-1|RASTERLAYER_DEM
None
1|CAREA
-1|HARDCODEDPARAMVALUE_INIT_METHOD_2
-1|NUMBER_THRESHOLDFORCHANNELDEFINITION
None
-1|HARDCODEDPARAMVALUE_DIV_CELLS_2
None
-1|HARDCODEDPARAMVALUE_MINLEN_2
None
None
None
ALGORITHM:saga:watershedbasins
528.0,48.0
None
-1|RASTERLAYER_DEM
2|CHNLNTWRK
None
-1|HARDCODEDPARAMVALUE_MINSIZE_3
None
ALGORITHM:saga:vectorisinggridclasses
649.0,285.0
None
3|BASINS
-1|HARDCODEDPARAMVALUE_CLASS_ALL_4
-1|HARDCODEDPARAMVALUE_CLASS_ID_4
-1|HARDCODEDPARAMVALUE_SPLIT_4
Watersheds

View File

@ -68,3 +68,8 @@ class Parameter:
def parameterName(self):
return self.__module__.split('.')[-1]
def todict(self):
return self.__dict__