31 #include <QSvgRenderer>
34 #include <QGraphicsSceneHoverEvent>
35 #include <QApplication>
37 #include <QMessageBox>
42 QgsModelComponentGraphicItem::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();
73 QgsModelComponentGraphicItem::Flags QgsModelComponentGraphicItem::flags()
const
75 return QgsModelComponentGraphicItem::Flags();
78 QgsModelComponentGraphicItem::~QgsModelComponentGraphicItem() =
default;
80 QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
82 return mComponent.get();
85 const QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
const
87 return mComponent.get();
90 QgsProcessingModelAlgorithm *QgsModelComponentGraphicItem::model()
95 QgsModelGraphicsView *QgsModelComponentGraphicItem::view()
97 if ( scene()->views().isEmpty() )
100 return qobject_cast< QgsModelGraphicsView * >( scene()->views().first() );
103 QFont QgsModelComponentGraphicItem::font()
const
108 void QgsModelComponentGraphicItem::setFont(
const QFont &font )
114 void 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();
127 void QgsModelComponentGraphicItem::previewItemMove( qreal dx, qreal dy )
129 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
130 emit updateArrowPaths();
133 void 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();
158 QRectF 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();
178 void 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() )
228 void QgsModelComponentGraphicItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * )
230 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
234 void QgsModelComponentGraphicItem::hoverEnterEvent( QGraphicsSceneHoverEvent *event )
236 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
237 updateToolTip( event->pos() );
240 void QgsModelComponentGraphicItem::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
242 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
243 updateToolTip( event->pos() );
246 void QgsModelComponentGraphicItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * )
248 modelHoverLeaveEvent(
nullptr );
251 QVariant 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 );
289 QRectF 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 );
305 bool 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 )
320 void 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 );
435 QRectF 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() );
451 QString 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();
472 Qt::PenStyle QgsModelComponentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
474 return Qt::SolidLine;
477 Qt::Alignment QgsModelComponentGraphicItem::titleAlignment()
const
479 return Qt::AlignLeft;
482 QPicture QgsModelComponentGraphicItem::iconPicture()
const
487 QPixmap QgsModelComponentGraphicItem::iconPixmap()
const
492 void 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() ) );
511 QSizeF QgsModelComponentGraphicItem::itemSize()
const
513 return !mTempSize.isValid() ? mComponent->size() : mTempSize;
516 void 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();
536 void 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();
556 QString QgsModelComponentGraphicItem::label()
const
561 void QgsModelComponentGraphicItem::setLabel(
const QString &label )
567 QgsModelComponentGraphicItem::State QgsModelComponentGraphicItem::state()
const
571 else if ( mIsHovering )
577 int QgsModelComponentGraphicItem::linkPointCount( Qt::Edge )
const
582 QString QgsModelComponentGraphicItem::linkPointText( Qt::Edge,
int )
const
587 QPointF 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 ),
644 QPointF 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;
683 QPointF 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;
721 QgsModelParameterGraphicItem::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() ) );
735 void 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() );
748 QColor QgsModelParameterGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
750 QColor
c( 238, 242, 131 );
766 QColor QgsModelParameterGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
771 return QColor( 116, 113, 68 );
774 return QColor( 234, 226, 118 );
779 QColor QgsModelParameterGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
784 QPicture QgsModelParameterGraphicItem::iconPicture()
const
789 void 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 );
798 bool 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() ) )
818 void 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();
846 QgsModelChildAlgorithmGraphicItem::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 );
869 void 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() );
897 QColor QgsModelChildAlgorithmGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
902 c = QColor( 255, 255, 255 );
904 c = QColor( 208, 0, 0 );
921 QColor 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 );
934 QColor QgsModelChildAlgorithmGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
936 return mIsValid ? ( qgis::down_cast< const QgsProcessingModelChildAlgorithm * >( component() )->isActive() ? Qt::black : Qt::gray ) : QColor( 255, 255, 255 );
939 QPixmap QgsModelChildAlgorithmGraphicItem::iconPixmap()
const
944 QPicture QgsModelChildAlgorithmGraphicItem::iconPicture()
const
949 int 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();
978 QString 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 );
1041 void 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 );
1050 bool QgsModelChildAlgorithmGraphicItem::canDeleteComponent()
1052 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1054 return model()->dependentChildAlgorithms( child->childId() ).empty();
1059 void QgsModelChildAlgorithmGraphicItem::setResults(
const QVariantMap &results )
1061 if ( mResults == results )
1066 emit updateArrowPaths();
1069 void QgsModelChildAlgorithmGraphicItem::setInputs(
const QVariantMap &inputs )
1071 if ( mInputs == inputs )
1076 emit updateArrowPaths();
1079 void 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();
1098 void QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm()
1100 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1102 model()->deactivateChildAlgorithm( child->childId() );
1103 emit requestModelRepaint();
1107 void 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.." ) );
1125 QgsModelOutputGraphicItem::QgsModelOutputGraphicItem( QgsProcessingModelOutput *output, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1126 : QgsModelComponentGraphicItem( output, model, parent )
1129 QPainter painter( &mPicture );
1130 svg.render( &painter );
1132 setLabel( output->description() );
1135 QColor QgsModelOutputGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1137 QColor
c( 172, 196, 114 );
1141 c =
c.darker( 110 );
1144 c =
c.darker( 105 );
1153 QColor QgsModelOutputGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1158 return QColor( 42, 65, 42 );
1161 return QColor( 90, 140, 90 );
1166 QColor QgsModelOutputGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1171 QPicture QgsModelOutputGraphicItem::iconPicture()
const
1176 void 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 );
1185 bool QgsModelOutputGraphicItem::canDeleteComponent()
1187 if (
dynamic_cast< const QgsProcessingModelOutput *
>( component() ) )
1194 void 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();
1211 QgsModelGroupBoxGraphicItem::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 );
1223 void 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() );
1233 QgsModelGroupBoxGraphicItem::~QgsModelGroupBoxGraphicItem() =
default;
1235 QColor QgsModelGroupBoxGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1237 QColor
c( 230, 230, 230 );
1241 c =
c.darker( 110 );
1244 c =
c.darker( 105 );
1253 QColor QgsModelGroupBoxGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1258 return QColor( 50, 50, 50 );
1261 return QColor( 150, 150, 150 );
1266 QColor QgsModelGroupBoxGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1268 return QColor( 100, 100, 100 );
1271 Qt::PenStyle QgsModelGroupBoxGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1276 Qt::Alignment QgsModelGroupBoxGraphicItem::titleAlignment()
const
1278 return Qt::AlignHCenter;
1281 void 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 );
1291 bool QgsModelGroupBoxGraphicItem::canDeleteComponent()
1293 if (
dynamic_cast< QgsProcessingModelGroupBox *
>( component() ) )
1300 void 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();
1311 void 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();
1331 QgsModelCommentGraphicItem::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 );
1343 void 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() );
1353 QgsModelCommentGraphicItem::~QgsModelCommentGraphicItem() =
default;
1355 QColor QgsModelCommentGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1357 QColor
c( 230, 230, 230 );
1361 c =
c.darker( 110 );
1364 c =
c.darker( 105 );
1373 QColor QgsModelCommentGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1378 return QColor( 50, 50, 50 );
1381 return QColor( 150, 150, 150 );
1386 QColor QgsModelCommentGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1388 return QColor( 100, 100, 100 );
1391 Qt::PenStyle QgsModelCommentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1396 void QgsModelCommentGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1398 if ( QgsProcessingModelComment *comment = modelComponent() )
1400 comment->setPosition( pos );
1401 comment->setSize( size );
1405 bool QgsModelCommentGraphicItem::canDeleteComponent()
1407 if ( modelComponent() )
1414 void QgsModelCommentGraphicItem::deleteComponent()
1416 if ( QgsProcessingModelComment *comment = modelComponent() )
1418 emit aboutToChange( tr(
"Delete Comment" ) );
1419 comment->setDescription( QString() );
1421 emit requestModelRepaint();
1425 void QgsModelCommentGraphicItem::editComponent()
1429 mParentItem->editComment();
1433 QgsProcessingModelComment *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();
1450 QgsModelComponentGraphicItem *QgsModelCommentGraphicItem::parentComponentItem()
const