Skip to content
Permalink
Browse files

Move responsibility for painting model components to c++

  • Loading branch information
nyalldawson committed Mar 3, 2020
1 parent a082bde commit b9edcbd1623afbffce627d9a4962b8d107a0cb20
@@ -84,6 +84,8 @@ Sets the ``font`` used to render text in the item.

virtual QRectF boundingRect() const;

virtual void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0 );


QRectF itemRect() const;
%Docstring
@@ -190,6 +192,31 @@ The default implementation does nothing.
%Docstring
Truncates a ``text`` string so that it fits nicely within the item's width,
accounting for margins and interactive buttons.
%End

virtual QColor fillColor( State state ) const = 0;
%Docstring
Returns the fill color for the item for the specified ``state``.
%End

virtual QColor strokeColor( State state ) const = 0;
%Docstring
Returns the stroke color for the item for the specified ``state``.
%End

virtual QColor textColor( State state ) const = 0;
%Docstring
Returns the label text color for the item for the specified ``state``.
%End

virtual QPicture iconPicture() const;
%Docstring
Returns a QPicture version of the item's icon, if available.
%End

virtual QPixmap iconPixmap() const;
%Docstring
Returns a QPixmap version of the item's icon, if available.
%End

};
@@ -24,8 +24,8 @@
import os

from qgis.PyQt.QtCore import Qt, QPointF
from qgis.PyQt.QtGui import QFontMetricsF, QPen, QBrush, QColor, QPicture, QPainter, QPalette
from qgis.PyQt.QtWidgets import QApplication, QMessageBox, QMenu
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,
@@ -49,78 +49,6 @@ class ModelerGraphicItem(QgsModelComponentGraphicItem):

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

def paint(self, painter, option, widget=None):
rect = self.itemRect()

if isinstance(self.component(), QgsProcessingModelParameter):
color = QColor(238, 242, 131)
stroke = QColor(234, 226, 118)
selected = QColor(116, 113, 68)
elif isinstance(self.component(), QgsProcessingModelChildAlgorithm):
color = QColor(255, 255, 255)
stroke = Qt.gray
selected = QColor(50, 50, 50)
else:
color = QColor(172, 196, 114)
stroke = QColor(90, 140, 90)
selected = QColor(42, 65, 42)
if self.state() == QgsModelComponentGraphicItem.Selected:
stroke = selected
color = color.darker(110)
if self.state() == QgsModelComponentGraphicItem.Hover:
color = color.darker(105)
painter.setPen(QPen(stroke, 0)) # 0 width "cosmetic" pen
painter.setBrush(QBrush(color, Qt.SolidPattern))
painter.drawRect(rect)
painter.setFont(self.font())
painter.setPen(QPen(Qt.black))
text = self.truncatedTextForItem(self.label())
if isinstance(self.component(), QgsProcessingModelChildAlgorithm) and not self.component().isActive():
painter.setPen(QPen(Qt.gray))
text = text + "\n(deactivated)"
fm = QFontMetricsF(self.font())
text = self.truncatedTextForItem(self.label())
h = fm.ascent()
pt = QPointF(-self.component().size().width() / 2 + 25, self.component().size().height() / 2.0 - h + 1)
painter.drawText(pt, text)
painter.setPen(QPen(QApplication.palette().color(QPalette.WindowText)))

if self.linkPointCount(Qt.TopEdge) or self.linkPointCount(Qt.BottomEdge):
h = -(fm.height() * 1.2)
h = h - self.component().size().height() / 2.0 + 5
pt = QPointF(-self.component().size().width() / 2 + 25, h)
painter.drawText(pt, 'In')
i = 1
if not self.component().linksCollapsed(Qt.TopEdge):
for idx in range(self.linkPointCount(Qt.TopEdge)):
text = self.linkPointText(Qt.TopEdge, idx)
h = -(fm.height() * 1.2) * (i + 1)
h = h - self.component().size().height() / 2.0 + 5
pt = QPointF(-self.component().size().width() / 2 + 33, h)
painter.drawText(pt, text)
i += 1

h = fm.height() * 1.1
h = h + self.component().size().height() / 2.0
pt = QPointF(-self.component().size().width() / 2 + 25, h)
painter.drawText(pt, 'Out')
if not self.component().linksCollapsed(Qt.BottomEdge):
for idx in range(self.linkPointCount(Qt.BottomEdge)):
text = self.linkPointText(Qt.BottomEdge, idx)
h = fm.height() * 1.2 * (idx + 2)
h = h + self.component().size().height() / 2.0
pt = QPointF(-self.component().size().width() / 2 + 33, h)
painter.drawText(pt, text)

if self.pixmap:
painter.drawPixmap(-(self.component().size().width() / 2.0) + 3, -8,
self.pixmap)
elif self.picture:
painter.drawPicture(-(self.component().size().width() / 2.0) + 3, -8,
self.picture)

def getLinkPointForParameter(self, paramIndex):
offsetX = 25
@@ -156,6 +84,26 @@ def __init__(self, element, model):
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
@@ -250,6 +198,30 @@ def __init__(self, element, model):
pt)
self.outButton.folded.connect(self.foldOutput)

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())
@@ -305,8 +277,8 @@ 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)
@@ -362,6 +334,27 @@ def __init__(self, element, model):
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

def editComponent(self):
child_alg = self.model().childAlgorithm(self.component().childId())
param_name = '{}:{}'.format(self.component().childId(), self.component().name())
@@ -26,6 +26,8 @@
#include <QPicture>
#include <QPainter>
#include <QGraphicsSceneHoverEvent>
#include <QApplication>
#include <QPalette>

///@cond NOT_STABLE

@@ -159,6 +161,80 @@ QRectF QgsModelComponentGraphicItem::boundingRect() const
mComponent->size().height() + hDown + hUp );
}

void QgsModelComponentGraphicItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * )
{
const QRectF rect = itemRect();
QColor color = fillColor( state() );
QColor stroke = strokeColor( state() );

painter->setPen( QPen( stroke, 0 ) ); // 0 width "cosmetic" pen
painter->setBrush( QBrush( color, Qt::SolidPattern ) );
painter->drawRect( rect );
painter->setFont( font() );
painter->setPen( QPen( textColor( state() ) ) );

QString text = truncatedTextForItem( label() );

const QSizeF componentSize = mComponent->size();

QFontMetricsF fm( font() );
double h = fm.ascent();
QPointF pt( -componentSize.width() / 2 + 25, componentSize.height() / 2.0 - h + 1 );
painter->drawText( pt, text );
painter->setPen( QPen( QApplication::palette().color( QPalette::WindowText ) ) );

if ( linkPointCount( Qt::TopEdge ) || linkPointCount( Qt::BottomEdge ) )
{
h = -( fm.height() * 1.2 );
h = h - componentSize.height() / 2.0 + 5;
pt = QPointF( -componentSize.width() / 2 + 25, h );
painter->drawText( pt, QObject::tr( "In" ) );
int i = 1;
if ( !mComponent->linksCollapsed( Qt::TopEdge ) )
{
for ( int idx = 0; idx < linkPointCount( Qt::TopEdge ); ++idx )
{
text = linkPointText( Qt::TopEdge, idx );
h = -( fm.height() * 1.2 ) * ( i + 1 );
h = h - componentSize.height() / 2.0 + 5;
pt = QPointF( -componentSize.width() / 2 + 33, h );
painter->drawText( pt, text );
i += 1;
}
}

h = fm.height() * 1.1;
h = h + componentSize.height() / 2.0;
pt = QPointF( -componentSize.width() / 2 + 25, h );
painter->drawText( pt, QObject::tr( "Out" ) );
if ( !mComponent->linksCollapsed( Qt::BottomEdge ) )
{
for ( int idx = 0; idx < linkPointCount( Qt::BottomEdge ); ++idx )
{
text = linkPointText( Qt::BottomEdge, idx );
h = fm.height() * 1.2 * ( idx + 2 );
h = h + componentSize.height() / 2.0;
pt = QPointF( -componentSize.width() / 2 + 33, h );
painter->drawText( pt, text );
}
}
}

const QPixmap px = iconPixmap();
if ( !px.isNull() )
{
painter->drawPixmap( -( componentSize.width() / 2.0 ) + 3, -8, px );
}
else
{
const QPicture pic = iconPicture();
if ( !pic.isNull() )
{
painter->drawPicture( -( componentSize.width() / 2.0 ) + 3, -8, pic );
}
}
}

QRectF QgsModelComponentGraphicItem::itemRect() const
{
return QRectF( -( mComponent->size().width() + 2 ) / 2.0,
@@ -185,6 +261,16 @@ QString QgsModelComponentGraphicItem::truncatedTextForItem( const QString &text
return t;
}

QPicture QgsModelComponentGraphicItem::iconPicture() const
{
return QPicture();
}

QPixmap QgsModelComponentGraphicItem::iconPixmap() const
{
return QPixmap();
}

void QgsModelComponentGraphicItem::updateToolTip( const QPointF &pos )
{
const bool prevHoverStatus = mIsHovering;
@@ -92,6 +92,7 @@ class GUI_EXPORT QgsModelComponentGraphicItem : public QGraphicsObject
void hoverLeaveEvent( QGraphicsSceneHoverEvent *event ) override;
QVariant itemChange( GraphicsItemChange change, const QVariant &value ) override;
QRectF boundingRect() const override;
void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr ) override;

/**
* Returns the rectangle representing the body of the item.
@@ -199,6 +200,31 @@ class GUI_EXPORT QgsModelComponentGraphicItem : public QGraphicsObject
*/
QString truncatedTextForItem( const QString &text ) const;

/**
* Returns the fill color for the item for the specified \a state.
*/
virtual QColor fillColor( State state ) const = 0;

/**
* Returns the stroke color for the item for the specified \a state.
*/
virtual QColor strokeColor( State state ) const = 0;

/**
* Returns the label text color for the item for the specified \a state.
*/
virtual QColor textColor( State state ) const = 0;

/**
* Returns a QPicture version of the item's icon, if available.
*/
virtual QPicture iconPicture() const;

/**
* Returns a QPixmap version of the item's icon, if available.
*/
virtual QPixmap iconPixmap() const;

private:

void updateToolTip( const QPointF &pos );

0 comments on commit b9edcbd

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