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

View File

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

View File

@ -16,6 +16,7 @@
* * * *
*************************************************************************** ***************************************************************************
""" """
from processing.modeler.ModelerUtils import ModelerUtils
__author__ = 'Victor Olaya' __author__ = 'Victor Olaya'
__date__ = 'August 2012' __date__ = 'August 2012'
@ -41,7 +42,6 @@ from processing.gui.RenderingStyles import RenderingStyles
from processing.gui.Postprocessing import handleAlgorithmResults from processing.gui.Postprocessing import handleAlgorithmResults
from processing.gui.UnthreadedAlgorithmExecutor import \ from processing.gui.UnthreadedAlgorithmExecutor import \
UnthreadedAlgorithmExecutor UnthreadedAlgorithmExecutor
from processing.modeler.Providers import Providers
from processing.modeler.ModelerAlgorithmProvider import \ from processing.modeler.ModelerAlgorithmProvider import \
ModelerAlgorithmProvider ModelerAlgorithmProvider
from processing.modeler.ModelerOnlyAlgorithmProvider import \ from processing.modeler.ModelerOnlyAlgorithmProvider import \
@ -119,8 +119,7 @@ class Processing:
@staticmethod @staticmethod
def getProviderFromName(name): def getProviderFromName(name):
"""Returns the provider with the given name. """Returns the provider with the given name."""
"""
for provider in Processing.providers: for provider in Processing.providers:
if provider.getName() == name: if provider.getName() == name:
return provider return provider
@ -139,8 +138,9 @@ class Processing:
Processing.addProvider(SagaAlgorithmProvider()) Processing.addProvider(SagaAlgorithmProvider())
Processing.addProvider(GrassAlgorithmProvider()) Processing.addProvider(GrassAlgorithmProvider())
Processing.addProvider(Grass7AlgorithmProvider()) Processing.addProvider(Grass7AlgorithmProvider())
Processing.addProvider(ScriptAlgorithmProvider()) Processing.addProvider(ScriptAlgorithmProvider())
Processing.addProvider(TauDEMAlgorithmProvider()) Processing.addProvider(TauDEMAlgorithmProvider())
Processing.addProvider(ModelerAlgorithmProvider())
Processing.modeler.initializeSettings() Processing.modeler.initializeSettings()
# And initialize # And initialize
@ -173,7 +173,8 @@ class Processing:
@staticmethod @staticmethod
def addAlgListListener(listener): 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 Whenever the list of algorithms changes, that method will be
called for all registered listeners. called for all registered listeners.
@ -196,33 +197,11 @@ class Processing:
algs[alg.commandLineName()] = alg algs[alg.commandLineName()] = alg
Processing.algs[provider.getName()] = algs 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 = {} provs = {}
for provider in Processing.providers: for provider in Processing.providers:
provs[provider.getName()] = provider provs[provider.getName()] = provider
provs[Processing.modeler.getName()] = Processing.modeler ModelerUtils.allAlgs = Processing.algs
Providers.providers = provs ModelerUtils.providers = provs
@staticmethod @staticmethod
def loadActions(): def loadActions():
@ -232,11 +211,7 @@ class Processing:
for action in providerActions: for action in providerActions:
actions.append(action) actions.append(action)
Processing.actions[provider.getName()] = actions Processing.actions[provider.getName()] = actions
provider = Processing.modeler
actions = list()
for action in provider.actions:
actions.append(action)
Processing.actions[provider.getName()] = actions Processing.actions[provider.getName()] = actions
@staticmethod @staticmethod
@ -247,11 +222,6 @@ class Processing:
for action in providerActions: for action in providerActions:
Processing.contextMenuActions.append(action) Processing.contextMenuActions.append(action)
provider = Processing.modeler
providerActions = provider.contextMenuActions
for action in providerActions:
Processing.contextMenuActions.append(action)
@staticmethod @staticmethod
def getAlgorithm(name): def getAlgorithm(name):
for provider in Processing.algs.values(): for provider in Processing.algs.values():
@ -269,8 +239,7 @@ class Processing:
@staticmethod @staticmethod
def getObject(uri): 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) return dataobjects.getObjectFromUri(uri)
@staticmethod @staticmethod

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,45 +25,114 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$' __revision__ = '$Format:%H$'
from PyQt4 import QtCore, QtGui
from processing.core.GeoAlgorithm import GeoAlgorithm from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import \ from processing.core.GeoAlgorithmExecutionException import \
GeoAlgorithmExecutionException GeoAlgorithmExecutionException
from processing.modeler.CalculatorModelerParametersDialog import \
CalculatorModelerParametersDialog
from processing.parameters.ParameterString import ParameterString from processing.parameters.ParameterString import ParameterString
from processing.parameters.ParameterNumber import ParameterNumber from processing.parameters.ParameterNumber import ParameterNumber
from processing.outputs.OutputNumber import OutputNumber 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): class CalculatorModelerAlgorithm(GeoAlgorithm):
FORMULA = 'FORMULA'
NUMBER = 'NUMBER'
RESULT = 'RESULT'
AVAILABLE_VARIABLES = 10
def defineCharacteristics(self): def defineCharacteristics(self):
self.showInModeler = True self.showInModeler = True
self.showInToolbox = False self.showInToolbox = False
self.name = 'Calculator' self.name = 'Calculator'
self.group = 'Modeler-only tools' self.group = 'Modeler-only tools'
self.addParameter(ParameterString(self.FORMULA, 'Formula', '')) self.addParameter(ParameterString(FORMULA, 'Formula', ''))
for i in range(self.AVAILABLE_VARIABLES): for i in range(AVAILABLE_VARIABLES):
self.addParameter(ParameterNumber(CalculatorModelerAlgorithm.NUMBER self.addParameter(ParameterNumber(NUMBER
+ str(i), 'dummy')) + str(i), 'dummy'))
self.addOutput(OutputNumber(self.RESULT, 'Result')) self.addOutput(OutputNumber(RESULT, 'Result'))
def processAlgorithm(self, progress): def processAlgorithm(self, progress):
formula = self.getParameterValue(self.FORMULA) formula = self.getParameterValue(FORMULA)
for i in range(self.AVAILABLE_VARIABLES): for i in range(AVAILABLE_VARIABLES):
name = CalculatorModelerAlgorithm.NUMBER + str(i) name = NUMBER + str(i)
num = self.getParameterValue(name) num = self.getParameterValue(name)
formula = formula.replace(chr(97 + i), str(num)) formula = formula.replace(chr(97 + i), str(num))
try: try:
result = eval(formula) result = eval(formula)
self.setOutputValue(self.RESULT, result) self.setOutputValue(RESULT, result)
except: except:
raise GeoAlgorithmExecutionException('Wrong formula: ' + formula) raise GeoAlgorithmExecutionException('Wrong formula: ' + formula)
def getCustomModelerParametersDialog(self, modelAlg, algIndex=None): def getCustomModelerParametersDialog(self, modelAlg, algIndex=None):
return CalculatorModelerParametersDialog(self, modelAlg, algIndex) 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.AlgorithmProvider import AlgorithmProvider
from processing.core.ProcessingConfig import ProcessingConfig, Setting from processing.core.ProcessingConfig import ProcessingConfig, Setting
from processing.core.ProcessingLog import ProcessingLog from processing.core.ProcessingLog import ProcessingLog
from processing.modeler.SaveAsPythonScriptAction import \
SaveAsPythonScriptAction
from processing.modeler.ModelerUtils import ModelerUtils from processing.modeler.ModelerUtils import ModelerUtils
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
from processing.modeler.WrongModelException import WrongModelException from processing.modeler.WrongModelException import WrongModelException
@ -48,8 +46,7 @@ class ModelerAlgorithmProvider(AlgorithmProvider):
def __init__(self): def __init__(self):
AlgorithmProvider.__init__(self) AlgorithmProvider.__init__(self)
self.actions = [CreateNewModelAction(), AddModelFromFileAction(), GetModelsAction()] self.actions = [CreateNewModelAction(), AddModelFromFileAction(), GetModelsAction()]
self.contextMenuActions = [EditModelAction(), DeleteModelAction(), self.contextMenuActions = [EditModelAction(), DeleteModelAction()]
SaveAsPythonScriptAction()]
def initializeSettings(self): def initializeSettings(self):
AlgorithmProvider.initializeSettings(self) AlgorithmProvider.initializeSettings(self)
@ -75,8 +72,6 @@ class ModelerAlgorithmProvider(AlgorithmProvider):
def _loadAlgorithms(self): def _loadAlgorithms(self):
folder = ModelerUtils.modelsFolder() folder = ModelerUtils.modelsFolder()
self.loadFromFolder(folder) self.loadFromFolder(folder)
folder = os.path.join(os.path.dirname(__file__), 'models')
self.loadFromFolder(folder)
def loadFromFolder(self, folder): def loadFromFolder(self, folder):
if not os.path.exists(folder): if not os.path.exists(folder):
@ -84,14 +79,13 @@ class ModelerAlgorithmProvider(AlgorithmProvider):
for path, subdirs, files in os.walk(folder): for path, subdirs, files in os.walk(folder):
for descriptionFile in files: for descriptionFile in files:
if descriptionFile.endswith('model'): if descriptionFile.endswith('model'):
try: try:
alg = ModelerAlgorithm()
fullpath = os.path.join(path, descriptionFile) fullpath = os.path.join(path, descriptionFile)
alg.openModel(fullpath) alg = ModelerAlgorithm.fromJsonFile(fullpath)
if alg.name.strip() != '': if alg:
alg.provider = self alg.provider = self
self.algs.append(alg) self.algs.append(alg)
except WrongModelException, e: except WrongModelException, e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
'Could not load model ' + descriptionFile + '\n' 'Could not load model ' + descriptionFile + '\n'
+ e.msg) + e.msg)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,6 +31,9 @@ from processing.core.ProcessingConfig import ProcessingConfig
class ModelerUtils: class ModelerUtils:
allAlgs = {}
providers = {}
MODELS_FOLDER = 'MODELS_FOLDER' MODELS_FOLDER = 'MODELS_FOLDER'
ACTIVATE_MODELS = 'ACTIVATE_MODELS' ACTIVATE_MODELS = 'ACTIVATE_MODELS'
@ -51,6 +54,3 @@ class ModelerUtils:
return provider[name] return provider[name]
return None 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()) return self.combo.itemData(self.combo.currentIndex())
def setValue(self, value): def setValue(self, value):
items = [self.combo.itemData(i) for i in range(1, self.combo.count())] items = [self.combo.itemData(i) for i in range(1, self.combo.count())]
idx = 0 for idx, item in enumerate(items):
for item in items: if item == value:
idx += 1 self.combo.setCurrentIndex(idx)
if item and value: return
if item.alg == value.alg and item.param == value.param: self.combo.setCurrentIndex(0)
self.combo.setCurrentIndex(idx)
return
self.combo.setCurrentIndex(0)
value = self.model.getValueFromAlgorithmAndParameter(value)
if value: 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): def parameterName(self):
return self.__module__.split('.')[-1] return self.__module__.split('.')[-1]
def todict(self):
return self.__dict__