31#include <QSvgRenderer>
34#include <QGraphicsSceneHoverEvent>
35#include <QApplication>
42QgsModelComponentGraphicItem::QgsModelComponentGraphicItem( QgsProcessingModelComponent *component, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
43 : QGraphicsObject( parent )
44 , mComponent( component )
47 setAcceptHoverEvents(
true );
48 setFlag( QGraphicsItem::ItemIsSelectable,
true );
49 setFlag( QGraphicsItem::ItemSendsGeometryChanges,
true );
50 setZValue( QgsModelGraphicsScene::ZValues::ModelComponent );
52 mFont.setPixelSize( 12 );
56 QPainter painter( &editPicture );
57 svg.render( &painter );
59 mEditButton =
new QgsModelDesignerFlatButtonGraphicItem(
this, editPicture, QPointF( 0, 0 ) );
60 connect( mEditButton, &QgsModelDesignerFlatButtonGraphicItem::clicked,
this, &QgsModelComponentGraphicItem::editComponent );
63 QPicture deletePicture;
64 painter.begin( &deletePicture );
65 svg2.render( &painter );
67 mDeleteButton =
new QgsModelDesignerFlatButtonGraphicItem(
this, deletePicture, QPointF( 0, 0 ) );
68 connect( mDeleteButton, &QgsModelDesignerFlatButtonGraphicItem::clicked,
this, &QgsModelComponentGraphicItem::deleteComponent );
70 updateButtonPositions();
73QgsModelComponentGraphicItem::Flags QgsModelComponentGraphicItem::flags()
const
75 return QgsModelComponentGraphicItem::Flags();
78QgsModelComponentGraphicItem::~QgsModelComponentGraphicItem() =
default;
80QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
82 return mComponent.get();
85const QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
const
87 return mComponent.get();
90QgsProcessingModelAlgorithm *QgsModelComponentGraphicItem::model()
95QgsModelGraphicsView *QgsModelComponentGraphicItem::view()
97 if ( scene()->views().isEmpty() )
100 return qobject_cast< QgsModelGraphicsView * >( scene()->views().first() );
103QFont QgsModelComponentGraphicItem::font()
const
108void QgsModelComponentGraphicItem::setFont(
const QFont &font )
114void QgsModelComponentGraphicItem::moveComponentBy( qreal dx, qreal dy )
116 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
117 mComponent->setPosition( pos() );
119 emit aboutToChange( tr(
"Move %1" ).arg( mComponent->description() ) );
120 updateStoredComponentPosition( pos(), mComponent->size() );
123 emit sizePositionChanged();
124 emit updateArrowPaths();
127void QgsModelComponentGraphicItem::previewItemMove( qreal dx, qreal dy )
129 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
130 emit updateArrowPaths();
133void QgsModelComponentGraphicItem::setItemRect( QRectF rect )
135 rect = rect.normalized();
137 if ( rect.width() < MIN_COMPONENT_WIDTH )
138 rect.setWidth( MIN_COMPONENT_WIDTH );
139 if ( rect.height() < MIN_COMPONENT_HEIGHT )
140 rect.setHeight( MIN_COMPONENT_HEIGHT );
142 setPos( rect.center() );
143 prepareGeometryChange();
145 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
147 mComponent->setPosition( pos() );
148 mComponent->setSize( rect.size() );
149 updateStoredComponentPosition( pos(), mComponent->size() );
151 updateButtonPositions();
154 emit updateArrowPaths();
155 emit sizePositionChanged();
158QRectF QgsModelComponentGraphicItem::previewItemRectChange( QRectF rect )
160 rect = rect.normalized();
162 if ( rect.width() < MIN_COMPONENT_WIDTH )
163 rect.setWidth( MIN_COMPONENT_WIDTH );
164 if ( rect.height() < MIN_COMPONENT_HEIGHT )
165 rect.setHeight( MIN_COMPONENT_HEIGHT );
167 setPos( rect.center() );
168 prepareGeometryChange();
170 mTempSize = rect.size();
172 updateButtonPositions();
173 emit updateArrowPaths();
178void QgsModelComponentGraphicItem::finalizePreviewedItemRectChange( QRectF )
180 mComponent->setPosition( pos() );
181 prepareGeometryChange();
182 mComponent->setSize( mTempSize );
183 mTempSize = QSizeF();
185 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
186 updateStoredComponentPosition( pos(), mComponent->size() );
188 updateButtonPositions();
192 emit sizePositionChanged();
193 emit updateArrowPaths();
198 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
199 updateToolTip( mapFromScene( event->
modelPoint() ) );
204 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
205 updateToolTip( mapFromScene( event->
modelPoint() ) );
210 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
212 setToolTip( QString() );
217 emit repaintArrows();
224 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
228void QgsModelComponentGraphicItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * )
230 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
234void QgsModelComponentGraphicItem::hoverEnterEvent( QGraphicsSceneHoverEvent *event )
236 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
237 updateToolTip( event->pos() );
240void QgsModelComponentGraphicItem::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
242 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
243 updateToolTip( event->pos() );
246void QgsModelComponentGraphicItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * )
248 modelHoverLeaveEvent(
nullptr );
251QVariant QgsModelComponentGraphicItem::itemChange( QGraphicsItem::GraphicsItemChange change,
const QVariant &value )
255 case QGraphicsItem::ItemSelectedChange:
257 emit repaintArrows();
261 case QGraphicsItem::ItemSceneChange:
266 if ( linkPointCount( Qt::TopEdge ) )
268 mExpandTopButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::TopEdge ), QPointF( 0, 0 ) );
269 connect( mExpandTopButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [ = ](
bool folded ) { fold( Qt::TopEdge, folded ); } );
271 if ( linkPointCount( Qt::BottomEdge ) )
273 mExpandBottomButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::BottomEdge ), QPointF( 0, 0 ) );
274 connect( mExpandBottomButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [ = ](
bool folded ) { fold( Qt::BottomEdge, folded ); } );
277 updateButtonPositions();
286 return QGraphicsObject::itemChange( change, value );
289QRectF QgsModelComponentGraphicItem::boundingRect()
const
291 const QFontMetricsF fm( mFont );
292 const int linksAbove = linkPointCount( Qt::TopEdge );
293 const int linksBelow = linkPointCount( Qt::BottomEdge );
295 const double hUp = linksAbove == 0 ? 0 :
296 fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::TopEdge ) ? 0 : linksAbove ) + 2 );
297 const double hDown = linksBelow == 0 ? 0 :
298 fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::BottomEdge ) ? 0 : linksBelow ) + 2 );
299 return QRectF( -( itemSize().width() ) / 2 - RECT_PEN_SIZE,
300 -( itemSize().height() ) / 2 - hUp - RECT_PEN_SIZE,
301 itemSize().width() + 2 * RECT_PEN_SIZE,
302 itemSize().height() + hDown + hUp + 2 * RECT_PEN_SIZE );
305bool QgsModelComponentGraphicItem::contains(
const QPointF &point )
const
307 const QRectF paintingBounds = boundingRect();
308 if ( point.x() < paintingBounds.left() + RECT_PEN_SIZE )
310 if ( point.x() > paintingBounds.right() - RECT_PEN_SIZE )
312 if ( point.y() < paintingBounds.top() + RECT_PEN_SIZE )
314 if ( point.y() > paintingBounds.bottom() - RECT_PEN_SIZE )
320void QgsModelComponentGraphicItem::paint( QPainter *painter,
const QStyleOptionGraphicsItem *, QWidget * )
322 const QRectF rect = itemRect();
326 if ( mComponent->color().isValid() )
328 color = mComponent->color();
332 color = color.darker( 110 );
335 color = color.darker( 105 );
341 stroke = color.darker( 110 );
342 foreColor = color.lightness() > 150 ? QColor( 0, 0, 0 ) : QColor( 255, 255, 255 );
346 color = fillColor( state() );
347 stroke = strokeColor( state() );
348 foreColor = textColor( state() );
351 QPen strokePen = QPen( stroke, 0 ) ;
352 strokePen.setStyle( strokeStyle( state() ) );
353 painter->setPen( strokePen );
354 painter->setBrush( QBrush( color, Qt::SolidPattern ) );
355 painter->drawRect( rect );
356 painter->setFont( font() );
357 painter->setPen( QPen( foreColor ) );
361 const QSizeF componentSize = itemSize();
363 const QFontMetricsF fm( font() );
364 double h = fm.ascent();
365 QPointF pt( -componentSize.width() / 2 + 25, componentSize.height() / 2.0 - h + 1 );
367 if ( iconPicture().isNull() && iconPixmap().isNull() )
369 const QRectF labelRect = QRectF( rect.left() + TEXT_MARGIN, rect.top() + TEXT_MARGIN, rect.width() - 2 * TEXT_MARGIN - mButtonSize.width() - BUTTON_MARGIN, rect.height() - 2 * TEXT_MARGIN );
371 painter->drawText( labelRect, Qt::TextWordWrap | titleAlignment(), text );
375 const QRectF labelRect = QRectF( rect.left() + 21 + TEXT_MARGIN, rect.top() + TEXT_MARGIN,
376 rect.width() - 2 * TEXT_MARGIN - mButtonSize.width() - BUTTON_MARGIN - 21, rect.height() - 2 * TEXT_MARGIN );
378 painter->drawText( labelRect, Qt::TextWordWrap | Qt::AlignVCenter, text );
381 painter->setPen( QPen( QApplication::palette().color( QPalette::WindowText ) ) );
383 if ( linkPointCount( Qt::TopEdge ) || linkPointCount( Qt::BottomEdge ) )
385 h = -( fm.height() * 1.2 );
386 h = h - componentSize.height() / 2.0 + 5;
387 pt = QPointF( -componentSize.width() / 2 + 25, h );
388 painter->drawText( pt, QObject::tr(
"In" ) );
390 if ( !mComponent->linksCollapsed( Qt::TopEdge ) )
392 for (
int idx = 0; idx < linkPointCount( Qt::TopEdge ); ++idx )
394 text = linkPointText( Qt::TopEdge, idx );
395 h = -( fm.height() * 1.2 ) * ( i + 1 );
396 h = h - componentSize.height() / 2.0 + 5;
397 pt = QPointF( -componentSize.width() / 2 + 33, h );
398 painter->drawText( pt, text );
403 h = fm.height() * 1.1;
404 h = h + componentSize.height() / 2.0;
405 pt = QPointF( -componentSize.width() / 2 + 25, h );
406 painter->drawText( pt, QObject::tr(
"Out" ) );
407 if ( !mComponent->linksCollapsed( Qt::BottomEdge ) )
409 for (
int idx = 0; idx < linkPointCount( Qt::BottomEdge ); ++idx )
411 text = linkPointText( Qt::BottomEdge, idx );
412 h = fm.height() * 1.2 * ( idx + 2 );
413 h = h + componentSize.height() / 2.0;
414 pt = QPointF( -componentSize.width() / 2 + 33, h );
415 painter->drawText( pt, text );
420 const QPixmap px = iconPixmap();
423 painter->drawPixmap( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), px );
427 const QPicture pic = iconPicture();
430 painter->drawPicture( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), pic );
435QRectF QgsModelComponentGraphicItem::itemRect(
bool storedRect )
const
439 return QRectF( mComponent->position().x() - ( mComponent->size().width() ) / 2.0,
440 mComponent->position().y() - ( mComponent->size().height() ) / 2.0,
441 mComponent->size().width(),
442 mComponent->size().height() );
445 return QRectF( -( itemSize().width() ) / 2.0,
446 -( itemSize().height() ) / 2.0,
448 itemSize().height() );
451QString QgsModelComponentGraphicItem::truncatedTextForItem(
const QString &text )
const
453 const QFontMetricsF fm( mFont );
454 double width = fm.boundingRect( text ).width();
455 if ( width < itemSize().width() - 25 - mButtonSize.width() )
459 t = t.left( t.length() - 3 ) + QChar( 0x2026 );
460 width = fm.boundingRect( t ).width();
461 while ( width > itemSize().width() - 25 - mButtonSize.width() )
463 if ( t.length() < 5 )
466 t = t.left( t.length() - 4 ) + QChar( 0x2026 );
467 width = fm.boundingRect( t ).width();
472Qt::PenStyle QgsModelComponentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
474 return Qt::SolidLine;
477Qt::Alignment QgsModelComponentGraphicItem::titleAlignment()
const
479 return Qt::AlignLeft;
482QPicture QgsModelComponentGraphicItem::iconPicture()
const
487QPixmap QgsModelComponentGraphicItem::iconPixmap()
const
492void QgsModelComponentGraphicItem::updateButtonPositions()
494 mEditButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN,
495 itemSize().height() / 2.0 - mButtonSize.height() / 2.0 - BUTTON_MARGIN ) );
496 mDeleteButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN,
497 mButtonSize.height() / 2.0 - itemSize().height() / 2.0 + BUTTON_MARGIN ) );
499 if ( mExpandTopButton )
501 const QPointF pt = linkPoint( Qt::TopEdge, -1,
true );
502 mExpandTopButton->setPosition( QPointF( 0, pt.y() ) );
504 if ( mExpandBottomButton )
506 const QPointF pt = linkPoint( Qt::BottomEdge, -1,
false );
507 mExpandBottomButton->setPosition( QPointF( 0, pt.y() ) );
511QSizeF QgsModelComponentGraphicItem::itemSize()
const
513 return !mTempSize.isValid() ? mComponent->size() : mTempSize;
516void QgsModelComponentGraphicItem::updateToolTip(
const QPointF &pos )
518 const bool prevHoverStatus = mIsHovering;
519 if ( itemRect().contains( pos ) )
521 setToolTip( mLabel );
526 setToolTip( QString() );
529 if ( mIsHovering != prevHoverStatus )
532 emit repaintArrows();
536void QgsModelComponentGraphicItem::fold( Qt::Edge edge,
bool folded )
538 emit aboutToChange( !folded ? tr(
"Expand Item" ) : tr(
"Collapse Item" ) );
539 mComponent->setLinksCollapsed( edge, folded );
543 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast< QgsProcessingModelChildAlgorithm *
>( mComponent.get() ) )
544 mModel->childAlgorithm( child->childId() ).setLinksCollapsed( edge, folded );
545 else if ( QgsProcessingModelParameter *param =
dynamic_cast< QgsProcessingModelParameter *
>( mComponent.get() ) )
546 mModel->parameterComponent( param->parameterName() ).setLinksCollapsed( edge, folded );
547 else if ( QgsProcessingModelOutput *output =
dynamic_cast< QgsProcessingModelOutput *
>( mComponent.get() ) )
548 mModel->childAlgorithm( output->childId() ).modelOutput( output->name() ).setLinksCollapsed( edge, folded );
550 prepareGeometryChange();
551 emit updateArrowPaths();
556QString QgsModelComponentGraphicItem::label()
const
561void QgsModelComponentGraphicItem::setLabel(
const QString &label )
567QgsModelComponentGraphicItem::State QgsModelComponentGraphicItem::state()
const
571 else if ( mIsHovering )
577int QgsModelComponentGraphicItem::linkPointCount( Qt::Edge )
const
582QString QgsModelComponentGraphicItem::linkPointText( Qt::Edge,
int )
const
587QPointF QgsModelComponentGraphicItem::linkPoint( Qt::Edge edge,
int index,
bool incoming )
const
593 if ( linkPointCount( Qt::BottomEdge ) )
596 if ( mComponent->linksCollapsed( Qt::BottomEdge ) )
600 const int pointIndex = !mComponent->linksCollapsed( Qt::BottomEdge ) ? index : -1;
601 const QString text = truncatedTextForItem( linkPointText( Qt::BottomEdge, index ) );
602 const QFontMetricsF fm( mFont );
603 const double w = fm.boundingRect( text ).width();
604 const double h = fm.height() * 1.2 * ( pointIndex + 1 ) + fm.height() / 2.0;
605 const double y = h + itemSize().height() / 2.0 + 5;
606 const double x = !mComponent->linksCollapsed( Qt::BottomEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10;
607 return QPointF( incoming ? -itemSize().width() / 2 + offsetX
616 if ( linkPointCount( Qt::TopEdge ) )
619 int paramIndex = index;
620 if ( mComponent->linksCollapsed( Qt::TopEdge ) )
625 const QFontMetricsF fm( mFont );
626 const QString text = truncatedTextForItem( linkPointText( Qt::TopEdge, index ) );
627 const double w = fm.boundingRect( text ).width();
628 double h = -( fm.height() * 1.2 ) * ( paramIndex + 2 ) - fm.height() / 2.0 + 8;
629 h = h - itemSize().height() / 2.0;
630 return QPointF( incoming ? -itemSize().width() / 2 + offsetX
631 : ( !mComponent->linksCollapsed( Qt::TopEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10 ),
644QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint( QgsModelComponentGraphicItem *other, Qt::Edge &edge )
const
647 const QgsRectangle otherRect( other->itemRect().translated( other->pos() ) );
649 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
650 const double distLeft = otherRect.distance(
QgsPointXY( leftPoint ) );
652 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
653 const double distRight = otherRect.distance(
QgsPointXY( rightPoint ) );
655 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
656 const double distTop = otherRect.distance(
QgsPointXY( topPoint ) );
658 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
659 const double distBottom = otherRect.distance(
QgsPointXY( bottomPoint ) );
661 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
666 else if ( distRight <= distTop && distRight <= distBottom )
668 edge = Qt::RightEdge;
671 else if ( distBottom <= distTop )
673 edge = Qt::BottomEdge;
683QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint(
const QPointF &point, Qt::Edge &edge )
const
687 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
688 const double distLeft = otherPt.distance(
QgsPointXY( leftPoint ) );
690 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
691 const double distRight = otherPt.distance(
QgsPointXY( rightPoint ) );
693 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
694 const double distTop = otherPt.distance(
QgsPointXY( topPoint ) );
696 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
697 const double distBottom = otherPt.distance(
QgsPointXY( bottomPoint ) );
699 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
704 else if ( distRight <= distTop && distRight <= distBottom )
706 edge = Qt::RightEdge;
709 else if ( distBottom <= distTop )
711 edge = Qt::BottomEdge;
721QgsModelParameterGraphicItem::QgsModelParameterGraphicItem( QgsProcessingModelParameter *parameter, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
722 : QgsModelComponentGraphicItem( parameter, model, parent )
725 QPainter painter( &mPicture );
726 svg.render( &painter );
730 setLabel( paramDef->description() );
732 setLabel( QObject::tr(
"Error (%1)" ).arg( parameter->parameterName() ) );
735void QgsModelParameterGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
737 QMenu *popupmenu =
new QMenu( event->widget() );
738 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
739 connect( removeAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::deleteComponent );
740 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
741 connect( editAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComponent );
742 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
743 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
745 popupmenu->exec( event->screenPos() );
748QColor QgsModelParameterGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
750 QColor
c( 238, 242, 131 );
766QColor QgsModelParameterGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
771 return QColor( 116, 113, 68 );
774 return QColor( 234, 226, 118 );
779QColor QgsModelParameterGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
784QPicture QgsModelParameterGraphicItem::iconPicture()
const
789void QgsModelParameterGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
791 if ( QgsProcessingModelParameter *param =
dynamic_cast< QgsProcessingModelParameter *
>( component() ) )
793 model()->parameterComponent( param->parameterName() ).setPosition( pos );
794 model()->parameterComponent( param->parameterName() ).setSize( size );
798bool QgsModelParameterGraphicItem::canDeleteComponent()
800 if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( component() ) )
802 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
806 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
818void QgsModelParameterGraphicItem::deleteComponent()
820 if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( component() ) )
822 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
824 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ),
825 QObject::tr(
"Algorithms depend on the selected input.\n"
826 "Remove them before trying to remove it." ) );
828 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
830 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ),
831 QObject::tr(
"Other inputs depend on the selected input.\n"
832 "Remove them before trying to remove it." ) );
836 emit aboutToChange( tr(
"Delete Input %1" ).arg( param->description() ) );
837 model()->removeModelParameter( param->parameterName() );
839 emit requestModelRepaint();
846QgsModelChildAlgorithmGraphicItem::QgsModelChildAlgorithmGraphicItem( QgsProcessingModelChildAlgorithm *child, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
847 : QgsModelComponentGraphicItem( child, model, parent )
849 if ( child->algorithm() && !child->algorithm()->svgIconPath().isEmpty() )
851 QSvgRenderer svg( child->algorithm()->svgIconPath() );
852 const QSizeF size = svg.defaultSize();
853 QPainter painter( &mPicture );
854 painter.scale( 16.0 / size.width(), 16.0 / size.width() );
855 svg.render( &painter );
858 else if ( child->algorithm() )
860 mPixmap = child->algorithm()->icon().pixmap( 15, 15 );
863 setLabel( child->description() );
866 mIsValid = model->validateChildAlgorithm( child->childId(), issues );
869void QgsModelChildAlgorithmGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
871 QMenu *popupmenu =
new QMenu( event->widget() );
872 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
873 connect( removeAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deleteComponent );
874 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
875 connect( editAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::editComponent );
876 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
877 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
878 popupmenu->addSeparator();
880 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
882 if ( !child->isActive() )
884 QAction *activateAction = popupmenu->addAction( QObject::tr(
"Activate" ) );
885 connect( activateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::activateAlgorithm );
889 QAction *deactivateAction = popupmenu->addAction( QObject::tr(
"Deactivate" ) );
890 connect( deactivateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm );
894 popupmenu->exec( event->screenPos() );
897QColor QgsModelChildAlgorithmGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
902 c = QColor( 255, 255, 255 );
904 c = QColor( 208, 0, 0 );
921QColor QgsModelChildAlgorithmGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
926 return mIsValid ? QColor( 50, 50, 50 ) : QColor( 80, 0, 0 );
929 return mIsValid ? Qt::gray : QColor( 134, 0, 0 );
934QColor QgsModelChildAlgorithmGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
936 return mIsValid ? ( qgis::down_cast< const QgsProcessingModelChildAlgorithm * >( component() )->isActive() ? Qt::black : Qt::gray ) : QColor( 255, 255, 255 );
939QPixmap QgsModelChildAlgorithmGraphicItem::iconPixmap()
const
944QPicture QgsModelChildAlgorithmGraphicItem::iconPicture()
const
949int QgsModelChildAlgorithmGraphicItem::linkPointCount( Qt::Edge edge )
const
951 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
953 if ( !child->algorithm() )
959 return child->algorithm()->outputDefinitions().size();
965 return param->flags() & QgsProcessingParameterDefinition::FlagHidden || param->isDestination();
967 return params.size();
978QString QgsModelChildAlgorithmGraphicItem::linkPointText( Qt::Edge edge,
int index )
const
983 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
985 if ( !child->algorithm() )
992 if ( index >= child->algorithm()->outputDefinitions().length() )
996 tr(
"Cannot link output for child: %1" ).arg( child->algorithm()->name() ),
997 "QgsModelChildAlgorithmGraphicItem", Qgis::MessageLevel::Warning,
true );
1003 if ( mResults.contains( output->
name() ) )
1005 title += QStringLiteral(
": %1" ).arg( mResults.value( output->
name() ).toString() );
1007 return truncatedTextForItem( title );
1015 return param->flags() & QgsProcessingParameterDefinition::FlagHidden || param->isDestination();
1016 } ), params.end() );
1018 if ( index >= params.length() )
1022 tr(
"Cannot link source for child: %1" ).arg( child->algorithm()->name() ),
1023 "QgsModelChildAlgorithmGraphicItem", Qgis::MessageLevel::Warning,
true );
1027 QString title = params.at( index )->description();
1028 if ( !mInputs.value( params.at( index )->name() ).toString().isEmpty() )
1029 title += QStringLiteral(
": %1" ).arg( mInputs.value( params.at( index )->name() ).toString() );
1030 return truncatedTextForItem( title );
1041void QgsModelChildAlgorithmGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1043 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast< QgsProcessingModelChildAlgorithm *
>( component() ) )
1045 model()->childAlgorithm( child->childId() ).setPosition( pos );
1046 model()->childAlgorithm( child->childId() ).setSize( size );
1050bool QgsModelChildAlgorithmGraphicItem::canDeleteComponent()
1052 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1054 return model()->dependentChildAlgorithms( child->childId() ).empty();
1059void QgsModelChildAlgorithmGraphicItem::setResults(
const QVariantMap &results )
1061 if ( mResults == results )
1066 emit updateArrowPaths();
1069void QgsModelChildAlgorithmGraphicItem::setInputs(
const QVariantMap &inputs )
1071 if ( mInputs == inputs )
1076 emit updateArrowPaths();
1079void QgsModelChildAlgorithmGraphicItem::deleteComponent()
1081 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1083 emit aboutToChange( tr(
"Remove %1" ).arg( child->algorithm() ? child->algorithm()->displayName() : tr(
"Algorithm" ) ) );
1084 if ( !model()->removeChildAlgorithm( child->childId() ) )
1086 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove algorithm" ),
1087 QObject::tr(
"Other algorithms depend on the selected one.\n"
1088 "Remove them before trying to remove it." ) );
1093 emit requestModelRepaint();
1098void QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm()
1100 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1102 model()->deactivateChildAlgorithm( child->childId() );
1103 emit requestModelRepaint();
1107void QgsModelChildAlgorithmGraphicItem::activateAlgorithm()
1109 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1111 if ( model()->activateChildAlgorithm( child->childId() ) )
1113 emit requestModelRepaint();
1117 QMessageBox::warning(
nullptr, QObject::tr(
"Could not activate algorithm" ),
1118 QObject::tr(
"The selected algorithm depends on other currently non-active algorithms.\n"
1119 "Activate them them before trying to activate it.." ) );
1125QgsModelOutputGraphicItem::QgsModelOutputGraphicItem( QgsProcessingModelOutput *output, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1126 : QgsModelComponentGraphicItem( output, model, parent )
1129 QPainter painter( &mPicture );
1130 svg.render( &painter );
1132 setLabel( output->description() );
1135QColor QgsModelOutputGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1137 QColor
c( 172, 196, 114 );
1141 c =
c.darker( 110 );
1144 c =
c.darker( 105 );
1153QColor QgsModelOutputGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1158 return QColor( 42, 65, 42 );
1161 return QColor( 90, 140, 90 );
1166QColor QgsModelOutputGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1171QPicture QgsModelOutputGraphicItem::iconPicture()
const
1176void QgsModelOutputGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1178 if ( QgsProcessingModelOutput *output =
dynamic_cast< QgsProcessingModelOutput *
>( component() ) )
1180 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setPosition( pos );
1181 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setSize( size );
1185bool QgsModelOutputGraphicItem::canDeleteComponent()
1187 if (
dynamic_cast< const QgsProcessingModelOutput *
>( component() ) )
1194void QgsModelOutputGraphicItem::deleteComponent()
1196 if (
const QgsProcessingModelOutput *output =
dynamic_cast< const QgsProcessingModelOutput *
>( component() ) )
1198 emit aboutToChange( tr(
"Delete Output %1" ).arg( output->description() ) );
1199 model()->childAlgorithm( output->childId() ).removeModelOutput( output->name() );
1200 model()->updateDestinationParameters();
1202 emit requestModelRepaint();
1211QgsModelGroupBoxGraphicItem::QgsModelGroupBoxGraphicItem( QgsProcessingModelGroupBox *box, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1212 : QgsModelComponentGraphicItem( box, model, parent )
1214 setZValue( QgsModelGraphicsScene::ZValues::GroupBox );
1215 setLabel( box->description() );
1219 f.setPixelSize( 14 );
1223void QgsModelGroupBoxGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1225 QMenu *popupmenu =
new QMenu( event->widget() );
1226 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1227 connect( removeAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::deleteComponent );
1228 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1229 connect( editAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::editComponent );
1230 popupmenu->exec( event->screenPos() );
1233QgsModelGroupBoxGraphicItem::~QgsModelGroupBoxGraphicItem() =
default;
1235QColor QgsModelGroupBoxGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1237 QColor
c( 230, 230, 230 );
1241 c =
c.darker( 110 );
1244 c =
c.darker( 105 );
1253QColor QgsModelGroupBoxGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1258 return QColor( 50, 50, 50 );
1261 return QColor( 150, 150, 150 );
1266QColor QgsModelGroupBoxGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1268 return QColor( 100, 100, 100 );
1271Qt::PenStyle QgsModelGroupBoxGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1276Qt::Alignment QgsModelGroupBoxGraphicItem::titleAlignment()
const
1278 return Qt::AlignHCenter;
1281void QgsModelGroupBoxGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1283 if ( QgsProcessingModelGroupBox *box =
dynamic_cast< QgsProcessingModelGroupBox *
>( component() ) )
1285 box->setPosition( pos );
1286 box->setSize( size );
1287 model()->addGroupBox( *box );
1291bool QgsModelGroupBoxGraphicItem::canDeleteComponent()
1293 if (
dynamic_cast< QgsProcessingModelGroupBox *
>( component() ) )
1300void QgsModelGroupBoxGraphicItem::deleteComponent()
1302 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast< const QgsProcessingModelGroupBox *
>( component() ) )
1304 emit aboutToChange( tr(
"Delete Group Box" ) );
1305 model()->removeGroupBox( box->uuid() );
1307 emit requestModelRepaint();
1311void QgsModelGroupBoxGraphicItem::editComponent()
1313 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast< const QgsProcessingModelGroupBox *
>( component() ) )
1319 emit aboutToChange( tr(
"Edit Group Box" ) );
1320 model()->addGroupBox( dlg.groupBox() );
1322 emit requestModelRepaint();
1331QgsModelCommentGraphicItem::QgsModelCommentGraphicItem( QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1332 : QgsModelComponentGraphicItem( comment, model, parent )
1333 , mParentComponent( parentItem->component()->clone() )
1334 , mParentItem( parentItem )
1336 setLabel( comment->description() );
1339 f.setPixelSize( 9 );
1343void QgsModelCommentGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1345 QMenu *popupmenu =
new QMenu( event->widget() );
1346 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1347 connect( removeAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::deleteComponent );
1348 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1349 connect( editAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::editComponent );
1350 popupmenu->exec( event->screenPos() );
1353QgsModelCommentGraphicItem::~QgsModelCommentGraphicItem() =
default;
1355QColor QgsModelCommentGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1357 QColor
c( 230, 230, 230 );
1361 c =
c.darker( 110 );
1364 c =
c.darker( 105 );
1373QColor QgsModelCommentGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1378 return QColor( 50, 50, 50 );
1381 return QColor( 150, 150, 150 );
1386QColor QgsModelCommentGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1388 return QColor( 100, 100, 100 );
1391Qt::PenStyle QgsModelCommentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1396void QgsModelCommentGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1398 if ( QgsProcessingModelComment *comment = modelComponent() )
1400 comment->setPosition( pos );
1401 comment->setSize( size );
1405bool QgsModelCommentGraphicItem::canDeleteComponent()
1407 if ( modelComponent() )
1414void QgsModelCommentGraphicItem::deleteComponent()
1416 if ( QgsProcessingModelComment *comment = modelComponent() )
1418 emit aboutToChange( tr(
"Delete Comment" ) );
1419 comment->setDescription( QString() );
1421 emit requestModelRepaint();
1425void QgsModelCommentGraphicItem::editComponent()
1429 mParentItem->editComment();
1433QgsProcessingModelComment *QgsModelCommentGraphicItem::modelComponent()
1435 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( mParentComponent.get() ) )
1437 return model()->childAlgorithm( child->childId() ).comment();
1439 else if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( mParentComponent.get() ) )
1441 return model()->parameterComponent( param->parameterName() ).comment();
1443 else if (
const QgsProcessingModelOutput *output =
dynamic_cast< const QgsProcessingModelOutput *
>( mParentComponent.get() ) )
1445 return model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).comment();
1450QgsModelComponentGraphicItem *QgsModelCommentGraphicItem::parentComponentItem()
const
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A widget which allow users to specify the properties of a model group box.
A QgsModelViewMouseEvent is the result of a user interaction with the mouse on a QgsModelGraphicsView...
QPointF modelPoint() const
Returns the event point location in model coordinates.
A class to represent a 2D point.
Base class for the definition of processing outputs.
QString name() const
Returns the name of the output.
QString description() const
Returns the description for the output.
Base class for the definition of processing parameters.
A rectangle specified with double values.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.