mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
186 lines
8.5 KiB
Python
186 lines
8.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
***************************************************************************
|
|
ModelerScene.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 qgis.PyQt.QtCore import QPointF, Qt
|
|
from qgis.PyQt.QtWidgets import QGraphicsItem, QGraphicsScene
|
|
from qgis.core import (QgsProcessingParameterDefinition,
|
|
QgsProcessingModelChildParameterSource,
|
|
QgsExpression)
|
|
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem
|
|
from processing.modeler.ModelerArrowItem import ModelerArrowItem
|
|
from processing.tools.dataobjects import createContext
|
|
|
|
|
|
class ModelerScene(QGraphicsScene):
|
|
|
|
def __init__(self, parent=None, dialog=None):
|
|
super(ModelerScene, self).__init__(parent)
|
|
self.paramItems = {}
|
|
self.algItems = {}
|
|
self.outputItems = {}
|
|
self.setItemIndexMethod(QGraphicsScene.NoIndex)
|
|
self.dialog = dialog
|
|
|
|
def getParameterPositions(self):
|
|
return {key: item.pos() for key, item in list(self.paramItems.items())}
|
|
|
|
def getAlgorithmPositions(self):
|
|
return {key: item.pos() for key, item in list(self.algItems.items())}
|
|
|
|
def getOutputPositions(self):
|
|
pos = {}
|
|
for algName, outputs in list(self.outputItems.items()):
|
|
outputPos = {}
|
|
for (key, value) in list(outputs.items()):
|
|
if value is not None:
|
|
outputPos[key] = value.pos()
|
|
else:
|
|
outputPos[key] = None
|
|
pos[algName] = outputPos
|
|
return pos
|
|
|
|
def getItemsFromParamValue(self, value, child_id, context):
|
|
items = []
|
|
if isinstance(value, list):
|
|
for v in value:
|
|
items.extend(self.getItemsFromParamValue(v, child_id, context))
|
|
elif isinstance(value, QgsProcessingModelChildParameterSource):
|
|
if value.source() == QgsProcessingModelChildParameterSource.ModelParameter:
|
|
items.append((self.paramItems[value.parameterName()], 0))
|
|
elif value.source() == QgsProcessingModelChildParameterSource.ChildOutput:
|
|
outputs = self.model.childAlgorithm(value.outputChildId()).algorithm().outputDefinitions()
|
|
for i, out in enumerate(outputs):
|
|
if out.name() == value.outputName():
|
|
break
|
|
if value.outputChildId() in self.algItems:
|
|
items.append((self.algItems[value.outputChildId()], i))
|
|
elif value.source() == QgsProcessingModelChildParameterSource.Expression:
|
|
variables = self.model.variablesForChildAlgorithm(child_id, context)
|
|
exp = QgsExpression(value.expression())
|
|
for v in exp.referencedVariables():
|
|
if v in variables:
|
|
items.extend(self.getItemsFromParamValue(variables[v].source, child_id, context))
|
|
return items
|
|
|
|
def paintModel(self, model, controls=True):
|
|
self.model = model
|
|
context = createContext()
|
|
# Inputs
|
|
for inp in list(model.parameterComponents().values()):
|
|
item = ModelerGraphicItem(inp, model, controls, scene=self)
|
|
item.setFlag(QGraphicsItem.ItemIsMovable, True)
|
|
item.setFlag(QGraphicsItem.ItemIsSelectable, True)
|
|
self.addItem(item)
|
|
item.setPos(inp.position().x(), inp.position().y())
|
|
self.paramItems[inp.parameterName()] = item
|
|
|
|
# Input dependency arrows
|
|
for input_name in list(model.parameterComponents().keys()):
|
|
idx = 0
|
|
parameter_def = model.parameterDefinition(input_name)
|
|
if hasattr(parameter_def, 'parentLayerParameterName') and parameter_def.parentLayerParameterName():
|
|
parent_name = parameter_def.parentLayerParameterName()
|
|
if input_name in self.paramItems and parent_name in self.paramItems:
|
|
input_item = self.paramItems[input_name]
|
|
parent_item = self.paramItems[parent_name]
|
|
arrow = ModelerArrowItem(parent_item, -1, input_item, -1)
|
|
input_item.addArrow(arrow)
|
|
parent_item.addArrow(arrow)
|
|
arrow.setPenStyle(Qt.DotLine)
|
|
arrow.updatePath()
|
|
self.addItem(arrow)
|
|
|
|
# We add the algs
|
|
for alg in list(model.childAlgorithms().values()):
|
|
item = ModelerGraphicItem(alg, model, controls, scene=self)
|
|
item.setFlag(QGraphicsItem.ItemIsMovable, True)
|
|
item.setFlag(QGraphicsItem.ItemIsSelectable, True)
|
|
self.addItem(item)
|
|
item.setPos(alg.position().x(), alg.position().y())
|
|
self.algItems[alg.childId()] = item
|
|
|
|
# And then the arrows
|
|
|
|
for alg in list(model.childAlgorithms().values()):
|
|
idx = 0
|
|
for parameter in alg.algorithm().parameterDefinitions():
|
|
if not parameter.isDestination() and not parameter.flags() & QgsProcessingParameterDefinition.FlagHidden:
|
|
if parameter.name() in alg.parameterSources():
|
|
sources = alg.parameterSources()[parameter.name()]
|
|
else:
|
|
sources = []
|
|
for source in sources:
|
|
sourceItems = self.getItemsFromParamValue(source, alg.childId(), context)
|
|
for sourceItem, sourceIdx in sourceItems:
|
|
arrow = ModelerArrowItem(sourceItem, sourceIdx, self.algItems[alg.childId()], idx)
|
|
sourceItem.addArrow(arrow)
|
|
self.algItems[alg.childId()].addArrow(arrow)
|
|
arrow.updatePath()
|
|
self.addItem(arrow)
|
|
idx += 1
|
|
for depend in alg.dependencies():
|
|
arrow = ModelerArrowItem(self.algItems[depend], -1,
|
|
self.algItems[alg.childId()], -1)
|
|
self.algItems[depend].addArrow(arrow)
|
|
self.algItems[alg.childId()].addArrow(arrow)
|
|
arrow.updatePath()
|
|
self.addItem(arrow)
|
|
|
|
# And finally the outputs
|
|
for alg in list(model.childAlgorithms().values()):
|
|
outputs = alg.modelOutputs()
|
|
outputItems = {}
|
|
idx = 0
|
|
for key, out in outputs.items():
|
|
if out is not None:
|
|
item = ModelerGraphicItem(out, model, controls, scene=self)
|
|
item.setFlag(QGraphicsItem.ItemIsMovable, True)
|
|
item.setFlag(QGraphicsItem.ItemIsSelectable, True)
|
|
self.addItem(item)
|
|
pos = out.position()
|
|
if pos is None:
|
|
pos = (alg.position() + QPointF(ModelerGraphicItem.BOX_WIDTH, 0) +
|
|
self.algItems[alg.childId()].getLinkPointForOutput(idx))
|
|
item.setPos(pos)
|
|
outputItems[key] = item
|
|
arrow = ModelerArrowItem(self.algItems[alg.childId()], idx, item,
|
|
-1)
|
|
self.algItems[alg.childId()].addArrow(arrow)
|
|
item.addArrow(arrow)
|
|
arrow.updatePath()
|
|
self.addItem(arrow)
|
|
idx += 1
|
|
else:
|
|
outputItems[key] = None
|
|
self.outputItems[alg.childId()] = outputItems
|
|
|
|
def mousePressEvent(self, mouseEvent):
|
|
if mouseEvent.button() != Qt.LeftButton:
|
|
return
|
|
super(ModelerScene, self).mousePressEvent(mouseEvent)
|