Skip to content
Permalink
Browse files

Move almost all the remaining Python code for model graphic items to c++

Only minimal shells of objects are left in Python now, the bare minimum
required because they call objects which depend on Python compatibility
for deprecated API calls...
  • Loading branch information
nyalldawson committed Mar 3, 2020
1 parent d80bdd3 commit 7d0b476fa7d3a6dd0b8af760bab00d0fe536ccbe
@@ -819,6 +819,8 @@
<file>themes/default/mIconModelerExpand.svg</file>
<file>themes/default/mActionDeleteModelComponent.svg</file>
<file>themes/default/mActionEditModelComponent.svg</file>
<file>themes/default/mIconModelOutput.svg</file>
<file>themes/default/mIconModelInput.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><g stroke="#5a8c5a" stroke-width=".265"><path d="M5.5 1.5v4h-4v5h4v4h5v-4h4v-5h-4v-4z" fill="#fff" stroke-width="1.00157545"/><path d="M3.5 8.5v-1h9v1z" fill="#5a8c5a" stroke-width="1.00157545"/><path d="M7.5 3.5h1v9h-1z" fill="#5a8c5a" stroke-width="1.00157545"/></g></svg>
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M0 5h8V0l8 8-8 8v-5H0z" fill="#5a8c5a"/><path d="M1 10V6h8V2.5L14.5 8 9 13.5V10z" fill="#fff"/><path d="M2 7v2h8v2l3.3-3L10 5v2z" fill="#5a8c5a"/></svg>
@@ -53,6 +53,7 @@ Ownership of ``component`` is transferred to the item.
Returns the model component associated with this item.
%End


QgsProcessingModelAlgorithm *model();
%Docstring
Returns the model associated with this item.
@@ -250,6 +251,25 @@ it must exist for the lifetime of this object.
Ownership of ``parameter`` is transferred to the item.
%End

virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent *event );


protected:

virtual QColor fillColor( State state ) const;

virtual QColor strokeColor( State state ) const;

virtual QColor textColor( State state ) const;

virtual QPicture iconPicture() const;


protected slots:

virtual void deleteComponent();


};

class QgsModelChildAlgorithmGraphicItem : QgsModelComponentGraphicItem
@@ -280,6 +300,31 @@ it must exist for the lifetime of this object.

Ownership of ``child`` is transferred to the item.
%End
virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent *event );


protected:

virtual QColor fillColor( State state ) const;

virtual QColor strokeColor( State state ) const;

virtual QColor textColor( State state ) const;

virtual QPixmap iconPixmap() const;

virtual QPicture iconPicture() const;


virtual int linkPointCount( Qt::Edge edge ) const;

virtual QString linkPointText( Qt::Edge edge, int index ) const;


protected slots:

virtual void deleteComponent();


};

@@ -313,6 +358,22 @@ it must exist for the lifetime of this object.
Ownership of ``output`` is transferred to the item.
%End

protected:

virtual QColor fillColor( State state ) const;

virtual QColor strokeColor( State state ) const;

virtual QColor textColor( State state ) const;

virtual QPicture iconPicture() const;


protected slots:

virtual void deleteComponent();


};

/************************************************************************
@@ -894,7 +894,6 @@ def _addAlgorithm(self, alg, pos=None):
alg.setPosition(self.getPositionForAlgorithmItem())
else:
alg.setPosition(pos)
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem

output_offset_x = alg.size().width()
output_offset_y = 1.5 * alg.size().height()
@@ -21,72 +21,33 @@
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'

import os

from qgis.PyQt.QtCore import Qt, QPointF
from qgis.PyQt.QtGui import QFontMetricsF, QColor, QPicture, QPainter, QPixmap
from qgis.PyQt.QtWidgets import QMessageBox, QMenu
from qgis.PyQt.QtSvg import QSvgRenderer
from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingModelParameter,
QgsProcessingModelChildAlgorithm,
QgsProject)
from qgis.gui import (
QgsProcessingParameterDefinitionDialog,
QgsProcessingParameterWidgetContext,
QgsModelDesignerFoldButtonGraphicItem,
QgsModelComponentGraphicItem
QgsModelParameterGraphicItem,
QgsModelChildAlgorithmGraphicItem,
QgsModelOutputGraphicItem
)
from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
from processing.tools.dataobjects import createContext
from qgis.utils import iface

pluginPath = os.path.split(os.path.dirname(__file__))[0]

class ModelerInputGraphicItem(QgsModelParameterGraphicItem):
"""
IMPORTANT! This is intentionally a MINIMAL class, only containing code which HAS TO BE HERE
because it contains Python code for compatibility with deprecated methods ONLY.
class ModelerGraphicItem(QgsModelComponentGraphicItem):
Don't add anything here -- edit the c++ base class instead!
"""

def __init__(self, element, model):
super().__init__(element, model, None)


class ModelerInputGraphicItem(ModelerGraphicItem):

def __init__(self, element, model):
super().__init__(element, model)

svg = QSvgRenderer(os.path.join(pluginPath, 'images', 'input.svg'))
self.picture = QPicture()
painter = QPainter(self.picture)
svg.render(painter)
painter.end()
paramDef = self.model().parameterDefinition(element.parameterName())
if paramDef:
self.setLabel(paramDef.description())
else:
self.setLabel('Error ({})'.format(element.parameterName()))

def fillColor(self, state):
c = QColor(238, 242, 131)
if state == QgsModelComponentGraphicItem.Selected:
c = c.darker(110)
elif state == QgsModelComponentGraphicItem.Hover:
c = c.darker(105)
return c

def strokeColor(self, state):
if state == QgsModelComponentGraphicItem.Selected:
return QColor(116, 113, 68)
else:
return QColor(234, 226, 118)

def textColor(self, state):
return Qt.black

def iconPicture(self):
return self.picture

def create_widget_context(self):
"""
Returns a new widget context for use in the model editor
@@ -127,88 +88,17 @@ def editComponent(self):
self.setLabel(new_param.description())
self.requestModelRepaint.emit()

def deleteComponent(self):
if self.model().childAlgorithmsDependOnParameter(self.component().parameterName()):
QMessageBox.warning(None, 'Could not remove input',
'Algorithms depend on the selected input.\n'
'Remove them before trying to remove it.')
elif self.model().otherParametersDependOnParameter(self.component().parameterName()):
QMessageBox.warning(None, 'Could not remove input',
'Other inputs depend on the selected input.\n'
'Remove them before trying to remove it.')
else:
self.model().removeModelParameter(self.component().parameterName())
self.changed.emit()
self.requestModelRepaint.emit()

def contextMenuEvent(self, event):
popupmenu = QMenu()
removeAction = popupmenu.addAction('Remove')
removeAction.triggered.connect(self.deleteComponent)
editAction = popupmenu.addAction('Edit')
editAction.triggered.connect(self.editComponent)
popupmenu.exec_(event.screenPos())

class ModelerChildAlgorithmGraphicItem(QgsModelChildAlgorithmGraphicItem):
"""
IMPORTANT! This is intentionally a MINIMAL class, only containing code which HAS TO BE HERE
because it contains Python code for compatibility with deprecated methods ONLY.
class ModelerChildAlgorithmGraphicItem(ModelerGraphicItem):
Don't add anything here -- edit the c++ base class instead!
"""

def __init__(self, element, model):
super().__init__(element, model)

if element.algorithm().svgIconPath():
svg = QSvgRenderer(element.algorithm().svgIconPath())
size = svg.defaultSize()
self.picture = QPicture()
painter = QPainter(self.picture)
painter.scale(16 / size.width(), 16 / size.width())
svg.render(painter)
painter.end()
self.pixmap = None
else:
self.pixmap = element.algorithm().icon().pixmap(15, 15)
self.setLabel(element.description())

def iconPicture(self):
return self.picture if self.picture is not None else QPicture()

def iconPixmap(self):
return self.pixmap if self.pixmap is not None else QPixmap()

def fillColor(self, state):
c = QColor(255, 255, 255)
if state == QgsModelComponentGraphicItem.Selected:
c = c.darker(110)
elif state == QgsModelComponentGraphicItem.Hover:
c = c.darker(105)

return c

def strokeColor(self, state):
if state == QgsModelComponentGraphicItem.Selected:
return QColor(50, 50, 50)
else:
return Qt.gray

def textColor(self, state):
return Qt.black if self.component().isActive() else Qt.gray

def linkPointCount(self, edge):
if edge == Qt.BottomEdge:
return len(self.component().algorithm().outputDefinitions())
elif edge == Qt.TopEdge:
return len([p for p in self.component().algorithm().parameterDefinitions() if
not p.isDestination() and not p.flags() & QgsProcessingParameterDefinition.FlagHidden])

return 0

def linkPointText(self, edge, index):
if edge == Qt.TopEdge:
param = [p for p in self.component().algorithm().parameterDefinitions() if
not p.isDestination() and not p.flags() & QgsProcessingParameterDefinition.FlagHidden][index]
return self.truncatedTextForItem(param.description())
elif edge == Qt.BottomEdge:
out = self.component().algorithm().outputDefinitions()[index]
return self.truncatedTextForItem(out.description())
super().__init__(element, model, None)

def editComponent(self):
elemAlg = self.component().algorithm()
@@ -226,83 +116,23 @@ def updateAlgorithm(self, alg):
alg.setLinksCollapsed(Qt.TopEdge, existing_child.linksCollapsed(Qt.TopEdge))
alg.setLinksCollapsed(Qt.BottomEdge, existing_child.linksCollapsed(Qt.BottomEdge))
for i, out in enumerate(alg.modelOutputs().keys()):
alg.modelOutput(out).setPosition(alg.modelOutput(out).position() or
alg.position() + QPointF(
alg.modelOutput(out).setPosition(alg.modelOutput(out).position()
or alg.position() + QPointF(
self.component().size().width(),
(i + 1.5) * self.component().size().height()))
self.model().setChildAlgorithm(alg)

def deleteComponent(self):
if not self.model().removeChildAlgorithm(self.component().childId()):
QMessageBox.warning(None, 'Could not remove element',
'Other elements depend on the selected one.\n'
'Remove them before trying to remove it.')
else:
self.changed.emit()
self.requestModelRepaint.emit()

def contextMenuEvent(self, event):
popupmenu = QMenu()
removeAction = popupmenu.addAction('Remove')
removeAction.triggered.connect(self.deleteComponent)
editAction = popupmenu.addAction('Edit')
editAction.triggered.connect(self.editComponent)

if not self.component().isActive():
removeAction = popupmenu.addAction('Activate')
removeAction.triggered.connect(self.activateAlgorithm)
else:
deactivateAction = popupmenu.addAction('Deactivate')
deactivateAction.triggered.connect(self.deactivateAlgorithm)

popupmenu.exec_(event.screenPos())

def deactivateAlgorithm(self):
self.model().deactivateChildAlgorithm(self.component().childId())
self.requestModelRepaint.emit()

def activateAlgorithm(self):
if self.model().activateChildAlgorithm(self.component().childId()):
self.requestModelRepaint.emit()
else:
QMessageBox.warning(None, 'Could not activate Algorithm',
'The selected algorithm depends on other currently non-active algorithms.\n'
'Activate them them before trying to activate it.')

class ModelerOutputGraphicItem(QgsModelOutputGraphicItem):
"""
IMPORTANT! This is intentionally a MINIMAL class, only containing code which HAS TO BE HERE
because it contains Python code for compatibility with deprecated methods ONLY.
class ModelerOutputGraphicItem(ModelerGraphicItem):
Don't add anything here -- edit the c++ base class instead!
"""

def __init__(self, element, model):
super().__init__(element, model)

# Output name
svg = QSvgRenderer(os.path.join(pluginPath, 'images', 'output.svg'))
self.picture = QPicture()
painter = QPainter(self.picture)
svg.render(painter)
painter.end()
self.setLabel(element.name())

def iconPicture(self):
return self.picture

def fillColor(self, state):
c = QColor(172, 196, 114)
if state == QgsModelComponentGraphicItem.Selected:
c = c.darker(110)
elif state == QgsModelComponentGraphicItem.Hover:
c = c.darker(105)

return c

def strokeColor(self, state):
if state == QgsModelComponentGraphicItem.Selected:
return QColor(42, 65, 42)
else:
return QColor(90, 140, 90)

def textColor(self, state):
return Qt.black
super().__init__(element, model, None)

def editComponent(self):
child_alg = self.model().childAlgorithm(self.component().childId())
@@ -315,12 +145,3 @@ def editComponent(self):
model_output.setDefaultValue(dlg.param.defaultValue())
model_output.setMandatory(not (dlg.param.flags() & QgsProcessingParameterDefinition.FlagOptional))
self.model().updateDestinationParameters()

def deleteComponent(self):
self.model().childAlgorithm(self.component().childId()).removeModelOutput(self.component().name())
self.model().updateDestinationParameters()
self.changed.emit()
self.requestModelRepaint.emit()

def contextMenuEvent(self, event):
return

0 comments on commit 7d0b476

Please sign in to comment.
You can’t perform that action at this time.