QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsmodelgraphicitem.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmodelgraphicitem.cpp
3 ----------------------------------
4 Date : February 2020
5 Copyright : (C) 2020 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsmodelgraphicitem.h"
17
18#include "qgsapplication.h"
23#include "qgsmodelviewtool.h"
29
30#include <QGraphicsSceneMouseEvent>
31#include <QPainter>
32#include <QString>
33#include <QSvgRenderer>
34
35#include "moc_qgsmodelgraphicitem.cpp"
36
37using namespace Qt::StringLiterals;
38
40
41QgsModelDesignerFlatButtonGraphicItem::QgsModelDesignerFlatButtonGraphicItem( QGraphicsItem *parent, const QPicture &picture, const QPointF &position, const QSizeF &size )
42 : QGraphicsObject( parent )
43 , mPicture( picture )
44 , mPosition( position )
45 , mSize( size )
46{
47 setAcceptHoverEvents( true );
48 setFlag( QGraphicsItem::ItemIsMovable, false );
49 setCacheMode( QGraphicsItem::DeviceCoordinateCache );
50}
51
52void QgsModelDesignerFlatButtonGraphicItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * )
53{
54 if ( QgsModelGraphicsScene *modelScene = qobject_cast<QgsModelGraphicsScene *>( scene() ) )
55 {
56 if ( modelScene->flags() & QgsModelGraphicsScene::FlagHideControls )
57 return;
58 }
59
60 if ( mHoverState )
61 {
62 painter->setPen( QPen( Qt::transparent, 1.0 ) );
63 painter->setBrush( QBrush( QColor( 55, 55, 55, 33 ), Qt::SolidPattern ) );
64 }
65 else
66 {
67 painter->setPen( QPen( Qt::transparent, 1.0 ) );
68 painter->setBrush( QBrush( Qt::transparent, Qt::SolidPattern ) );
69 }
70 const QPointF topLeft = mPosition - QPointF( std::floor( mSize.width() / 2 ), std::floor( mSize.height() / 2 ) );
71 const QRectF rect = QRectF( topLeft.x(), topLeft.y(), mSize.width(), mSize.height() );
72 painter->drawRect( rect );
73 painter->drawPicture( topLeft.x(), topLeft.y(), mPicture );
74}
75
76QRectF QgsModelDesignerFlatButtonGraphicItem::boundingRect() const
77{
78 return QRectF( mPosition.x() - std::floor( mSize.width() / 2 ), mPosition.y() - std::floor( mSize.height() / 2 ), mSize.width(), mSize.height() );
79}
80
81void QgsModelDesignerFlatButtonGraphicItem::hoverEnterEvent( QGraphicsSceneHoverEvent * )
82{
83 if ( view()->tool() && !view()->tool()->allowItemInteraction() )
84 mHoverState = false;
85 else
86 mHoverState = true;
87 update();
88}
89
90void QgsModelDesignerFlatButtonGraphicItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * )
91{
92 mHoverState = false;
93 update();
94}
95
96void QgsModelDesignerFlatButtonGraphicItem::mousePressEvent( QGraphicsSceneMouseEvent * )
97{
98 if ( view()->tool() && view()->tool()->allowItemInteraction() )
99 emit clicked();
100}
101
102void QgsModelDesignerFlatButtonGraphicItem::modelHoverEnterEvent( QgsModelViewMouseEvent * )
103{
104 if ( view()->tool() && !view()->tool()->allowItemInteraction() )
105 mHoverState = false;
106 else
107 mHoverState = true;
108 update();
109}
110
111void QgsModelDesignerFlatButtonGraphicItem::modelHoverLeaveEvent( QgsModelViewMouseEvent * )
112{
113 mHoverState = false;
114 update();
115}
116
117void QgsModelDesignerFlatButtonGraphicItem::modelPressEvent( QgsModelViewMouseEvent *event )
118{
119 if ( view()->tool() && view()->tool()->allowItemInteraction() && event->button() == Qt::LeftButton )
120 {
121 QMetaObject::invokeMethod( this, "clicked", Qt::QueuedConnection );
122 mHoverState = false;
123 update();
124 }
125}
126
127void QgsModelDesignerFlatButtonGraphicItem::setPosition( const QPointF &position )
128{
129 mPosition = position;
130 prepareGeometryChange();
131 update();
132}
133
134QgsModelGraphicsView *QgsModelDesignerFlatButtonGraphicItem::view()
135{
136 return qobject_cast<QgsModelGraphicsView *>( scene()->views().first() );
137}
138
139void QgsModelDesignerFlatButtonGraphicItem::setPicture( const QPicture &picture )
140{
141 mPicture = picture;
142 update();
143}
144
145//
146// QgsModelDesignerFoldButtonGraphicItem
147//
148
149QgsModelDesignerFoldButtonGraphicItem::QgsModelDesignerFoldButtonGraphicItem( QGraphicsItem *parent, bool folded, const QPointF &position, const QSizeF &size )
150 : QgsModelDesignerFlatButtonGraphicItem( parent, QPicture(), position, size )
151 , mFolded( folded )
152{
153 QSvgRenderer svg( QgsApplication::iconPath( u"mIconModelerExpand.svg"_s ) );
154 QPainter painter( &mPlusPicture );
155 svg.render( &painter );
156 painter.end();
157
158 QSvgRenderer svg2( QgsApplication::iconPath( u"mIconModelerCollapse.svg"_s ) );
159 painter.begin( &mMinusPicture );
160 svg2.render( &painter );
161 painter.end();
162
163 setPicture( mFolded ? mPlusPicture : mMinusPicture );
164}
165
166void QgsModelDesignerFoldButtonGraphicItem::mousePressEvent( QGraphicsSceneMouseEvent *event )
167{
168 mFolded = !mFolded;
169 setPicture( mFolded ? mPlusPicture : mMinusPicture );
170 emit folded( mFolded );
171 QgsModelDesignerFlatButtonGraphicItem::mousePressEvent( event );
172}
173
174void QgsModelDesignerFoldButtonGraphicItem::modelPressEvent( QgsModelViewMouseEvent *event )
175{
176 mFolded = !mFolded;
177 setPicture( mFolded ? mPlusPicture : mMinusPicture );
178 emit folded( mFolded );
179 QgsModelDesignerFlatButtonGraphicItem::modelPressEvent( event );
180}
181
182
183QgsModelDesignerSocketGraphicItem::QgsModelDesignerSocketGraphicItem(
184 QgsModelComponentGraphicItem *parent, QgsProcessingModelComponent *component, int index, const QPointF &position, Qt::Edge edge, const QSizeF &size
185)
186 : QgsModelDesignerFlatButtonGraphicItem( parent, QPicture(), position, size )
187 , mComponentItem( parent )
188 , mComponent( component )
189 , mIndex( index )
190 , mEdge( edge )
191{}
192
193void QgsModelDesignerSocketGraphicItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * )
194{
195 QColor outlineColor = socketColor();
196 QColor fillColor = QColor( outlineColor );
197
198 if ( isInput() )
199 {
200 fillColor.setAlpha( isDefaultParameterValue() ? 30 : 255 );
201 }
202 else
203 {
204 // outputs are always filled sockets
205 fillColor.setAlpha( 255 );
206 }
207
208 // Outline style
209 painter->setPen( QPen( outlineColor, mHoverState ? mSocketOutlineWidth * 2 : mSocketOutlineWidth ) );
210
211 // Fill style
212 painter->setBrush( QBrush( fillColor, Qt::SolidPattern ) );
213
214 painter->setRenderHint( QPainter::Antialiasing );
215
216 // Radius of the socket circle
217 constexpr float DISPLAY_SIZE = 4;
218
219 // Offset of the socket to separate from the label
220 constexpr float ELLIPSE_OFFSET = 0.4;
221 QPointF ellipsePosition = QPointF( position().x() + ELLIPSE_OFFSET, position().y() + ELLIPSE_OFFSET );
222 painter->drawEllipse( ellipsePosition, DISPLAY_SIZE, DISPLAY_SIZE );
223
224 /* Uncomment to display bounding box */
225#if 0
226 painter->save();
227 painter->setPen( QPen() );
228 painter->setBrush( QBrush() );
229 painter->drawRect( boundingRect() );
230 painter->restore();
231#endif
232}
233
234
235QColor QgsModelDesignerSocketGraphicItem::socketColor() const
236{
237 return mComponentItem->linkColor( mEdge, mIndex );
238}
239
240
241bool QgsModelDesignerSocketGraphicItem::isDefaultParameterValue() const
242{
243 if ( !mComponent )
244 {
245 return false;
246 }
247
248 const QgsProcessingModelChildAlgorithm *child = dynamic_cast<const QgsProcessingModelChildAlgorithm *>( mComponent );
249
250 if ( !child )
251 {
252 return false;
253 }
254
255 bool isDefaultValue = true;
256
257 // We can only know if the socket should be filled if the algorithm is non null
258 if ( child->algorithm() )
259 {
260 switch ( mEdge )
261 {
262 // Input params
263 case Qt::TopEdge:
264 {
265 const QgsProcessingParameterDefinitions params = child->algorithm()->parameterDefinitions();
266 const QgsProcessingParameterDefinition *param = params.value( mIndex );
267 if ( !param )
268 break;
269
270 const QString name = param->name();
271
272 QgsProcessingModelChildParameterSources paramSources = child->parameterSources().value( name );
273 if ( paramSources.empty() )
274 {
275 break;
276 }
277
278 // The default value can only happen in the case of the parameter uses a static value
279 if ( paramSources[0].source() != Qgis::ProcessingModelChildParameterSource::StaticValue )
280 {
281 isDefaultValue = false;
282 break;
283 }
284
285 isDefaultValue = paramSources[0].staticValue() == param->defaultValue();
286 break;
287 }
288
289 // Outputs
290 case Qt::BottomEdge:
291 case Qt::LeftEdge:
292 case Qt::RightEdge:
293 break;
294 }
295 }
296
297 return isDefaultValue;
298}
299
300
301QgsModelDesignerFeatureCountGraphicItem::QgsModelDesignerFeatureCountGraphicItem( QgsModelArrowItem *link, const QString &text )
302 : QGraphicsTextItem( text )
303 , mLink( link )
304{
305 connect( link, &QgsModelArrowItem::painterPathUpdated, this, &QgsModelDesignerFeatureCountGraphicItem::setPosition );
306
307 QFont font = this->font();
308 font.setPointSize( FONT_SIZE );
309 setFont( font );
310
311 setZValue( QgsModelGraphicsScene::ZValues::ArrowDecoration );
312 setPosition();
313}
314
315void QgsModelDesignerFeatureCountGraphicItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *widget )
316{
317 const bool isDarkTheme = QApplication::palette().color( QPalette::Window ).lightness() < 128;
318 QPalette::ColorRole bgPalette = isDarkTheme ? QPalette::Dark : QPalette::Light;
319
320 // First draw a rounded rectangle as background
321 QColor backgroundColor = QApplication::palette().color( bgPalette );
322 backgroundColor.setAlpha( 220 ); // Add some transparency so we still see the arrow underneath
323 painter->setBrush( QBrush( backgroundColor ) );
324 painter->setPen( Qt::PenStyle::NoPen );
325 constexpr double RADIUS = 5;
326 painter->drawRoundedRect( boundingRect(), RADIUS, RADIUS );
327
328 // And finally draw the text on top
329 setDefaultTextColor( QApplication::palette().color( QPalette::Text ) );
330 QGraphicsTextItem::paint( painter, itemStyle, widget );
331}
332
333void QgsModelDesignerFeatureCountGraphicItem::setPosition()
334{
335 QPointF middlePos = mLink->path().pointAtPercent( 0.5 );
336 QRectF rect = boundingRect();
337 QPointF offset = rect.center();
338 setPos( middlePos - offset );
339 update();
340}
341
@ StaticValue
Parameter value is a static value.
Definition qgis.h:3967
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
A mouse event which is the result of a user interaction with a QgsModelGraphicsView.
Base class for the definition of processing parameters.
QVariant defaultValue() const
Returns the default value for the parameter.
QString name() const
Returns the name of the parameter.
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.