32#include <QSvgRenderer>
35#include <QGraphicsSceneHoverEvent>
36#include <QApplication>
43QgsModelComponentGraphicItem::QgsModelComponentGraphicItem( QgsProcessingModelComponent *component, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
44 : QGraphicsObject( parent )
45 , mComponent( component )
48 setAcceptHoverEvents(
true );
49 setFlag( QGraphicsItem::ItemIsSelectable,
true );
50 setFlag( QGraphicsItem::ItemSendsGeometryChanges,
true );
51 setZValue( QgsModelGraphicsScene::ZValues::ModelComponent );
53 mFont.setPixelSize( 12 );
57 QPainter painter( &editPicture );
58 svg.render( &painter );
60 mEditButton =
new QgsModelDesignerFlatButtonGraphicItem(
this, editPicture, QPointF( 0, 0 ) );
61 connect( mEditButton, &QgsModelDesignerFlatButtonGraphicItem::clicked,
this, &QgsModelComponentGraphicItem::editComponent );
64 QPicture deletePicture;
65 painter.begin( &deletePicture );
66 svg2.render( &painter );
68 mDeleteButton =
new QgsModelDesignerFlatButtonGraphicItem(
this, deletePicture, QPointF( 0, 0 ) );
69 connect( mDeleteButton, &QgsModelDesignerFlatButtonGraphicItem::clicked,
this, &QgsModelComponentGraphicItem::deleteComponent );
71 updateButtonPositions();
74QgsModelComponentGraphicItem::Flags QgsModelComponentGraphicItem::flags()
const
76 return QgsModelComponentGraphicItem::Flags();
79QgsModelComponentGraphicItem::~QgsModelComponentGraphicItem() =
default;
81QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
83 return mComponent.get();
86const QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
const
88 return mComponent.get();
91QgsProcessingModelAlgorithm *QgsModelComponentGraphicItem::model()
96QgsModelGraphicsView *QgsModelComponentGraphicItem::view()
98 if ( scene()->views().isEmpty() )
101 return qobject_cast< QgsModelGraphicsView * >( scene()->views().first() );
104QFont QgsModelComponentGraphicItem::font()
const
109void QgsModelComponentGraphicItem::setFont(
const QFont &font )
115void QgsModelComponentGraphicItem::moveComponentBy( qreal dx, qreal dy )
117 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
118 mComponent->setPosition( pos() );
120 emit aboutToChange( tr(
"Move %1" ).arg( mComponent->description() ) );
121 updateStoredComponentPosition( pos(), mComponent->size() );
124 emit sizePositionChanged();
125 emit updateArrowPaths();
128void QgsModelComponentGraphicItem::previewItemMove( qreal dx, qreal dy )
130 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
131 emit updateArrowPaths();
134void QgsModelComponentGraphicItem::setItemRect( QRectF rect )
136 rect = rect.normalized();
138 if ( rect.width() < MIN_COMPONENT_WIDTH )
139 rect.setWidth( MIN_COMPONENT_WIDTH );
140 if ( rect.height() < MIN_COMPONENT_HEIGHT )
141 rect.setHeight( MIN_COMPONENT_HEIGHT );
143 setPos( rect.center() );
144 prepareGeometryChange();
146 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
148 mComponent->setPosition( pos() );
149 mComponent->setSize( rect.size() );
150 updateStoredComponentPosition( pos(), mComponent->size() );
152 updateButtonPositions();
155 emit updateArrowPaths();
156 emit sizePositionChanged();
159QRectF QgsModelComponentGraphicItem::previewItemRectChange( QRectF rect )
161 rect = rect.normalized();
163 if ( rect.width() < MIN_COMPONENT_WIDTH )
164 rect.setWidth( MIN_COMPONENT_WIDTH );
165 if ( rect.height() < MIN_COMPONENT_HEIGHT )
166 rect.setHeight( MIN_COMPONENT_HEIGHT );
168 setPos( rect.center() );
169 prepareGeometryChange();
171 mTempSize = rect.size();
173 updateButtonPositions();
174 emit updateArrowPaths();
179void QgsModelComponentGraphicItem::finalizePreviewedItemRectChange( QRectF )
181 mComponent->setPosition( pos() );
182 prepareGeometryChange();
183 mComponent->setSize( mTempSize );
184 mTempSize = QSizeF();
186 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
187 updateStoredComponentPosition( pos(), mComponent->size() );
189 updateButtonPositions();
193 emit sizePositionChanged();
194 emit updateArrowPaths();
199 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
200 updateToolTip( mapFromScene( event->
modelPoint() ) );
205 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
206 updateToolTip( mapFromScene( event->
modelPoint() ) );
211 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
213 setToolTip( QString() );
218 emit repaintArrows();
225 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
229void QgsModelComponentGraphicItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * )
231 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
235void QgsModelComponentGraphicItem::hoverEnterEvent( QGraphicsSceneHoverEvent *event )
237 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
238 updateToolTip( event->pos() );
241void QgsModelComponentGraphicItem::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
243 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
244 updateToolTip( event->pos() );
247void QgsModelComponentGraphicItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * )
249 modelHoverLeaveEvent(
nullptr );
252QVariant QgsModelComponentGraphicItem::itemChange( QGraphicsItem::GraphicsItemChange change,
const QVariant &value )
256 case QGraphicsItem::ItemSelectedChange:
258 emit repaintArrows();
262 case QGraphicsItem::ItemSceneChange:
267 if ( linkPointCount( Qt::TopEdge ) )
269 mExpandTopButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::TopEdge ), QPointF( 0, 0 ) );
270 connect( mExpandTopButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [ = ](
bool folded ) { fold( Qt::TopEdge, folded ); } );
272 if ( linkPointCount( Qt::BottomEdge ) )
274 mExpandBottomButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::BottomEdge ), QPointF( 0, 0 ) );
275 connect( mExpandBottomButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [ = ](
bool folded ) { fold( Qt::BottomEdge, folded ); } );
278 updateButtonPositions();
287 return QGraphicsObject::itemChange( change, value );
290QRectF QgsModelComponentGraphicItem::boundingRect()
const
292 const QFontMetricsF fm( mFont );
293 const int linksAbove = linkPointCount( Qt::TopEdge );
294 const int linksBelow = linkPointCount( Qt::BottomEdge );
296 const double hUp = linksAbove == 0 ? 0 :
297 fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::TopEdge ) ? 0 : linksAbove ) + 2 );
298 const double hDown = linksBelow == 0 ? 0 :
299 fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::BottomEdge ) ? 0 : linksBelow ) + 2 );
300 return QRectF( -( itemSize().width() ) / 2 - RECT_PEN_SIZE,
301 -( itemSize().height() ) / 2 - hUp - RECT_PEN_SIZE,
302 itemSize().width() + 2 * RECT_PEN_SIZE,
303 itemSize().height() + hDown + hUp + 2 * RECT_PEN_SIZE );
306bool QgsModelComponentGraphicItem::contains(
const QPointF &point )
const
308 const QRectF paintingBounds = boundingRect();
309 if ( point.x() < paintingBounds.left() + RECT_PEN_SIZE )
311 if ( point.x() > paintingBounds.right() - RECT_PEN_SIZE )
313 if ( point.y() < paintingBounds.top() + RECT_PEN_SIZE )
315 if ( point.y() > paintingBounds.bottom() - RECT_PEN_SIZE )
321void QgsModelComponentGraphicItem::paint( QPainter *painter,
const QStyleOptionGraphicsItem *, QWidget * )
323 const QRectF rect = itemRect();
327 if ( mComponent->color().isValid() )
329 color = mComponent->color();
333 color = color.darker( 110 );
336 color = color.darker( 105 );
342 stroke = color.darker( 110 );
343 foreColor = color.lightness() > 150 ? QColor( 0, 0, 0 ) : QColor( 255, 255, 255 );
347 color = fillColor( state() );
348 stroke = strokeColor( state() );
349 foreColor = textColor( state() );
352 QPen strokePen = QPen( stroke, 0 ) ;
353 strokePen.setStyle( strokeStyle( state() ) );
354 painter->setPen( strokePen );
355 painter->setBrush( QBrush( color, Qt::SolidPattern ) );
356 painter->drawRect( rect );
357 painter->setFont( font() );
358 painter->setPen( QPen( foreColor ) );
362 const QSizeF componentSize = itemSize();
364 const QFontMetricsF fm( font() );
365 double h = fm.ascent();
366 QPointF pt( -componentSize.width() / 2 + 25, componentSize.height() / 2.0 - h + 1 );
368 if ( iconPicture().isNull() && iconPixmap().isNull() )
370 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 );
372 painter->drawText( labelRect, Qt::TextWordWrap | titleAlignment(), text );
376 const QRectF labelRect = QRectF( rect.left() + 21 + TEXT_MARGIN, rect.top() + TEXT_MARGIN,
377 rect.width() - 2 * TEXT_MARGIN - mButtonSize.width() - BUTTON_MARGIN - 21, rect.height() - 2 * TEXT_MARGIN );
379 painter->drawText( labelRect, Qt::TextWordWrap | Qt::AlignVCenter, text );
382 painter->setPen( QPen( QApplication::palette().color( QPalette::Text ) ) );
384 if ( linkPointCount( Qt::TopEdge ) || linkPointCount( Qt::BottomEdge ) )
386 h = -( fm.height() * 1.2 );
387 h = h - componentSize.height() / 2.0 + 5;
388 pt = QPointF( -componentSize.width() / 2 + 25, h );
389 painter->drawText( pt, QObject::tr(
"In" ) );
391 if ( !mComponent->linksCollapsed( Qt::TopEdge ) )
393 for (
int idx = 0; idx < linkPointCount( Qt::TopEdge ); ++idx )
395 text = linkPointText( Qt::TopEdge, idx );
396 h = -( fm.height() * 1.2 ) * ( i + 1 );
397 h = h - componentSize.height() / 2.0 + 5;
398 pt = QPointF( -componentSize.width() / 2 + 33, h );
399 painter->drawText( pt, text );
404 h = fm.height() * 1.1;
405 h = h + componentSize.height() / 2.0;
406 pt = QPointF( -componentSize.width() / 2 + 25, h );
407 painter->drawText( pt, QObject::tr(
"Out" ) );
408 if ( !mComponent->linksCollapsed( Qt::BottomEdge ) )
410 for (
int idx = 0; idx < linkPointCount( Qt::BottomEdge ); ++idx )
412 text = linkPointText( Qt::BottomEdge, idx );
413 h = fm.height() * 1.2 * ( idx + 2 );
414 h = h + componentSize.height() / 2.0;
415 pt = QPointF( -componentSize.width() / 2 + 33, h );
416 painter->drawText( pt, text );
421 const QPixmap px = iconPixmap();
424 painter->drawPixmap( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), px );
428 const QPicture pic = iconPicture();
431 painter->drawPicture( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), pic );
436QRectF QgsModelComponentGraphicItem::itemRect(
bool storedRect )
const
440 return QRectF( mComponent->position().x() - ( mComponent->size().width() ) / 2.0,
441 mComponent->position().y() - ( mComponent->size().height() ) / 2.0,
442 mComponent->size().width(),
443 mComponent->size().height() );
446 return QRectF( -( itemSize().width() ) / 2.0,
447 -( itemSize().height() ) / 2.0,
449 itemSize().height() );
452QString QgsModelComponentGraphicItem::truncatedTextForItem(
const QString &text )
const
454 const QFontMetricsF fm( mFont );
455 double width = fm.boundingRect( text ).width();
456 if ( width < itemSize().width() - 25 - mButtonSize.width() )
460 t = t.left( t.length() - 3 ) + QChar( 0x2026 );
461 width = fm.boundingRect( t ).width();
462 while ( width > itemSize().width() - 25 - mButtonSize.width() )
464 if ( t.length() < 5 )
467 t = t.left( t.length() - 4 ) + QChar( 0x2026 );
468 width = fm.boundingRect( t ).width();
473Qt::PenStyle QgsModelComponentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
475 return Qt::SolidLine;
478Qt::Alignment QgsModelComponentGraphicItem::titleAlignment()
const
480 return Qt::AlignLeft;
483QPicture QgsModelComponentGraphicItem::iconPicture()
const
488QPixmap QgsModelComponentGraphicItem::iconPixmap()
const
493void QgsModelComponentGraphicItem::updateButtonPositions()
495 mEditButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN,
496 itemSize().height() / 2.0 - mButtonSize.height() / 2.0 - BUTTON_MARGIN ) );
497 mDeleteButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN,
498 mButtonSize.height() / 2.0 - itemSize().height() / 2.0 + BUTTON_MARGIN ) );
500 if ( mExpandTopButton )
502 const QPointF pt = linkPoint( Qt::TopEdge, -1,
true );
503 mExpandTopButton->setPosition( QPointF( 0, pt.y() ) );
505 if ( mExpandBottomButton )
507 const QPointF pt = linkPoint( Qt::BottomEdge, -1,
false );
508 mExpandBottomButton->setPosition( QPointF( 0, pt.y() ) );
512QSizeF QgsModelComponentGraphicItem::itemSize()
const
514 return !mTempSize.isValid() ? mComponent->size() : mTempSize;
517void QgsModelComponentGraphicItem::updateToolTip(
const QPointF &pos )
519 const bool prevHoverStatus = mIsHovering;
520 if ( itemRect().contains( pos ) )
522 setToolTip( mLabel );
527 setToolTip( QString() );
530 if ( mIsHovering != prevHoverStatus )
533 emit repaintArrows();
537void QgsModelComponentGraphicItem::fold( Qt::Edge edge,
bool folded )
539 emit aboutToChange( !folded ? tr(
"Expand Item" ) : tr(
"Collapse Item" ) );
540 mComponent->setLinksCollapsed( edge, folded );
544 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast< QgsProcessingModelChildAlgorithm *
>( mComponent.get() ) )
545 mModel->childAlgorithm( child->childId() ).setLinksCollapsed( edge, folded );
546 else if ( QgsProcessingModelParameter *param =
dynamic_cast< QgsProcessingModelParameter *
>( mComponent.get() ) )
547 mModel->parameterComponent( param->parameterName() ).setLinksCollapsed( edge, folded );
548 else if ( QgsProcessingModelOutput *output =
dynamic_cast< QgsProcessingModelOutput *
>( mComponent.get() ) )
549 mModel->childAlgorithm( output->childId() ).modelOutput( output->name() ).setLinksCollapsed( edge, folded );
551 prepareGeometryChange();
552 emit updateArrowPaths();
557QString QgsModelComponentGraphicItem::label()
const
562void QgsModelComponentGraphicItem::setLabel(
const QString &label )
568QgsModelComponentGraphicItem::State QgsModelComponentGraphicItem::state()
const
572 else if ( mIsHovering )
578int QgsModelComponentGraphicItem::linkPointCount( Qt::Edge )
const
583QString QgsModelComponentGraphicItem::linkPointText( Qt::Edge,
int )
const
588QPointF QgsModelComponentGraphicItem::linkPoint( Qt::Edge edge,
int index,
bool incoming )
const
594 if ( linkPointCount( Qt::BottomEdge ) )
597 if ( mComponent->linksCollapsed( Qt::BottomEdge ) )
601 const int pointIndex = !mComponent->linksCollapsed( Qt::BottomEdge ) ? index : -1;
602 const QString text = truncatedTextForItem( linkPointText( Qt::BottomEdge, index ) );
603 const QFontMetricsF fm( mFont );
604 const double w = fm.boundingRect( text ).width();
605 const double h = fm.height() * 1.2 * ( pointIndex + 1 ) + fm.height() / 2.0;
606 const double y = h + itemSize().height() / 2.0 + 5;
607 const double x = !mComponent->linksCollapsed( Qt::BottomEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10;
608 return QPointF( incoming ? -itemSize().width() / 2 + offsetX
617 if ( linkPointCount( Qt::TopEdge ) )
620 int paramIndex = index;
621 if ( mComponent->linksCollapsed( Qt::TopEdge ) )
626 const QFontMetricsF fm( mFont );
627 const QString text = truncatedTextForItem( linkPointText( Qt::TopEdge, index ) );
628 const double w = fm.boundingRect( text ).width();
629 double h = -( fm.height() * 1.2 ) * ( paramIndex + 2 ) - fm.height() / 2.0 + 8;
630 h = h - itemSize().height() / 2.0;
631 return QPointF( incoming ? -itemSize().width() / 2 + offsetX
632 : ( !mComponent->linksCollapsed( Qt::TopEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10 ),
645QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint( QgsModelComponentGraphicItem *other, Qt::Edge &edge )
const
648 const QgsRectangle otherRect( other->itemRect().translated( other->pos() ) );
650 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
651 const double distLeft = otherRect.distance(
QgsPointXY( leftPoint ) );
653 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
654 const double distRight = otherRect.distance(
QgsPointXY( rightPoint ) );
656 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
657 const double distTop = otherRect.distance(
QgsPointXY( topPoint ) );
659 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
660 const double distBottom = otherRect.distance(
QgsPointXY( bottomPoint ) );
662 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
667 else if ( distRight <= distTop && distRight <= distBottom )
669 edge = Qt::RightEdge;
672 else if ( distBottom <= distTop )
674 edge = Qt::BottomEdge;
684QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint(
const QPointF &point, Qt::Edge &edge )
const
688 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
689 const double distLeft = otherPt.distance(
QgsPointXY( leftPoint ) );
691 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
692 const double distRight = otherPt.distance(
QgsPointXY( rightPoint ) );
694 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
695 const double distTop = otherPt.distance(
QgsPointXY( topPoint ) );
697 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
698 const double distBottom = otherPt.distance(
QgsPointXY( bottomPoint ) );
700 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
705 else if ( distRight <= distTop && distRight <= distBottom )
707 edge = Qt::RightEdge;
710 else if ( distBottom <= distTop )
712 edge = Qt::BottomEdge;
722QgsModelParameterGraphicItem::QgsModelParameterGraphicItem( QgsProcessingModelParameter *parameter, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
723 : QgsModelComponentGraphicItem( parameter, model, parent )
726 QPainter painter( &mPicture );
727 svg.render( &painter );
731 setLabel( paramDef->description() );
733 setLabel( QObject::tr(
"Error (%1)" ).arg( parameter->parameterName() ) );
736void QgsModelParameterGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
738 QMenu *popupmenu =
new QMenu( event->widget() );
739 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
740 connect( removeAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::deleteComponent );
741 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
742 connect( editAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComponent );
743 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
744 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
746 popupmenu->exec( event->screenPos() );
749QColor QgsModelParameterGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
751 QColor
c( 238, 242, 131 );
767QColor QgsModelParameterGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
772 return QColor( 116, 113, 68 );
775 return QColor( 234, 226, 118 );
780QColor QgsModelParameterGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
785QPicture QgsModelParameterGraphicItem::iconPicture()
const
790void QgsModelParameterGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
792 if ( QgsProcessingModelParameter *param =
dynamic_cast< QgsProcessingModelParameter *
>( component() ) )
794 model()->parameterComponent( param->parameterName() ).setPosition( pos );
795 model()->parameterComponent( param->parameterName() ).setSize( size );
799bool QgsModelParameterGraphicItem::canDeleteComponent()
801 if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( component() ) )
803 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
807 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
819void QgsModelParameterGraphicItem::deleteComponent()
821 if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( component() ) )
823 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
825 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ),
826 QObject::tr(
"Algorithms depend on the selected input.\n"
827 "Remove them before trying to remove it." ) );
829 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
831 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ),
832 QObject::tr(
"Other inputs depend on the selected input.\n"
833 "Remove them before trying to remove it." ) );
837 emit aboutToChange( tr(
"Delete Input %1" ).arg( param->description() ) );
838 model()->removeModelParameter( param->parameterName() );
840 emit requestModelRepaint();
847QgsModelChildAlgorithmGraphicItem::QgsModelChildAlgorithmGraphicItem( QgsProcessingModelChildAlgorithm *child, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
848 : QgsModelComponentGraphicItem( child, model, parent )
850 if ( child->algorithm() && !child->algorithm()->svgIconPath().isEmpty() )
852 QSvgRenderer svg( child->algorithm()->svgIconPath() );
853 const QSizeF size = svg.defaultSize();
854 QPainter painter( &mPicture );
855 painter.scale( 16.0 / size.width(), 16.0 / size.width() );
856 svg.render( &painter );
859 else if ( child->algorithm() )
861 mPixmap = child->algorithm()->icon().pixmap( 15, 15 );
864 setLabel( child->description() );
867 mIsValid = model->validateChildAlgorithm( child->childId(), issues );
870void QgsModelChildAlgorithmGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
872 QMenu *popupmenu =
new QMenu( event->widget() );
876 QAction *runSelectedStepsAction = popupmenu->addAction( QObject::tr(
"Run Selected Steps…" ) );
878 connect( runSelectedStepsAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runSelected );
881 QAction *runFromHereAction = popupmenu->addAction( QObject::tr(
"Run from Here…" ) );
883 connect( runFromHereAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runFromHere );
885 popupmenu->addSeparator();
887 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
888 connect( removeAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deleteComponent );
889 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
890 connect( editAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::editComponent );
891 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
892 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
893 popupmenu->addSeparator();
895 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
897 if ( !child->isActive() )
899 QAction *activateAction = popupmenu->addAction( QObject::tr(
"Activate" ) );
900 connect( activateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::activateAlgorithm );
904 QAction *deactivateAction = popupmenu->addAction( QObject::tr(
"Deactivate" ) );
905 connect( deactivateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm );
912 if ( !outputParams.isEmpty() )
914 popupmenu->addSeparator();
915 QAction *viewOutputLayersAction = popupmenu->addAction( QObject::tr(
"View Output Layers" ) );
917 connect( viewOutputLayersAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showPreviousResults );
919 switch ( mResults.executionStatus() )
923 viewOutputLayersAction->setEnabled(
false );
932 QAction *viewLogAction = popupmenu->addAction( QObject::tr(
"View Log…" ) );
933 connect( viewLogAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showLog );
935 switch ( mResults.executionStatus() )
938 viewLogAction->setEnabled(
false );
947 popupmenu->exec( event->screenPos() );
950QColor QgsModelChildAlgorithmGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
955 c = QColor( 255, 255, 255 );
957 c = QColor( 208, 0, 0 );
974QColor QgsModelChildAlgorithmGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
979 return mIsValid ? QColor( 50, 50, 50 ) : QColor( 80, 0, 0 );
982 return mIsValid ? Qt::gray : QColor( 134, 0, 0 );
987QColor QgsModelChildAlgorithmGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
989 return mIsValid ? ( qgis::down_cast< const QgsProcessingModelChildAlgorithm * >( component() )->isActive() ? Qt::black : Qt::gray ) : QColor( 255, 255, 255 );
992QPixmap QgsModelChildAlgorithmGraphicItem::iconPixmap()
const
997QPicture QgsModelChildAlgorithmGraphicItem::iconPicture()
const
1002int QgsModelChildAlgorithmGraphicItem::linkPointCount( Qt::Edge edge )
const
1004 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1006 if ( !child->algorithm() )
1011 case Qt::BottomEdge:
1012 return child->algorithm()->outputDefinitions().size();
1018 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1019 } ), params.end() );
1020 return params.size();
1031QString QgsModelChildAlgorithmGraphicItem::linkPointText( Qt::Edge edge,
int index )
const
1036 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1038 if ( !child->algorithm() )
1041 const QVariantMap inputs = mResults.inputs();
1042 const QVariantMap outputs = mResults.outputs();
1045 case Qt::BottomEdge:
1047 if ( index >= child->algorithm()->outputDefinitions().length() )
1051 tr(
"Cannot link output for child: %1" ).arg( child->algorithm()->name() ),
1058 if ( outputs.contains( output->
name() ) )
1060 title += QStringLiteral(
": %1" ).arg( outputs.value( output->
name() ).toString() );
1062 return truncatedTextForItem( title );
1070 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1071 } ), params.end() );
1073 if ( index >= params.length() )
1077 tr(
"Cannot link source for child: %1" ).arg( child->algorithm()->name() ),
1082 QString title = params.at( index )->description();
1083 if ( !inputs.value( params.at( index )->name() ).toString().isEmpty() )
1084 title += QStringLiteral(
": %1" ).arg( inputs.value( params.at( index )->name() ).toString() );
1085 return truncatedTextForItem( title );
1096void QgsModelChildAlgorithmGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1098 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast< QgsProcessingModelChildAlgorithm *
>( component() ) )
1100 model()->childAlgorithm( child->childId() ).setPosition( pos );
1101 model()->childAlgorithm( child->childId() ).setSize( size );
1105bool QgsModelChildAlgorithmGraphicItem::canDeleteComponent()
1107 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1109 return model()->dependentChildAlgorithms( child->childId() ).empty();
1116 if ( mResults == results )
1121 emit updateArrowPaths();
1124void QgsModelChildAlgorithmGraphicItem::deleteComponent()
1126 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1128 emit aboutToChange( tr(
"Remove %1" ).arg( child->algorithm() ? child->algorithm()->displayName() : tr(
"Algorithm" ) ) );
1129 if ( !model()->removeChildAlgorithm( child->childId() ) )
1131 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove algorithm" ),
1132 QObject::tr(
"Other algorithms depend on the selected one.\n"
1133 "Remove them before trying to remove it." ) );
1138 emit requestModelRepaint();
1143void QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm()
1145 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1147 model()->deactivateChildAlgorithm( child->childId() );
1148 emit requestModelRepaint();
1152void QgsModelChildAlgorithmGraphicItem::activateAlgorithm()
1154 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1156 if ( model()->activateChildAlgorithm( child->childId() ) )
1158 emit requestModelRepaint();
1162 QMessageBox::warning(
nullptr, QObject::tr(
"Could not activate algorithm" ),
1163 QObject::tr(
"The selected algorithm depends on other currently non-active algorithms.\n"
1164 "Activate them them before trying to activate it.." ) );
1170QgsModelOutputGraphicItem::QgsModelOutputGraphicItem( QgsProcessingModelOutput *output, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1171 : QgsModelComponentGraphicItem( output, model, parent )
1174 QPainter painter( &mPicture );
1175 svg.render( &painter );
1177 setLabel( output->description() );
1180QColor QgsModelOutputGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1182 QColor
c( 172, 196, 114 );
1186 c =
c.darker( 110 );
1189 c =
c.darker( 105 );
1198QColor QgsModelOutputGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1203 return QColor( 42, 65, 42 );
1206 return QColor( 90, 140, 90 );
1211QColor QgsModelOutputGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1216QPicture QgsModelOutputGraphicItem::iconPicture()
const
1221void QgsModelOutputGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1223 if ( QgsProcessingModelOutput *output =
dynamic_cast< QgsProcessingModelOutput *
>( component() ) )
1225 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setPosition( pos );
1226 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setSize( size );
1230bool QgsModelOutputGraphicItem::canDeleteComponent()
1232 if (
dynamic_cast< const QgsProcessingModelOutput *
>( component() ) )
1239void QgsModelOutputGraphicItem::deleteComponent()
1241 if (
const QgsProcessingModelOutput *output =
dynamic_cast< const QgsProcessingModelOutput *
>( component() ) )
1243 emit aboutToChange( tr(
"Delete Output %1" ).arg( output->description() ) );
1244 model()->childAlgorithm( output->childId() ).removeModelOutput( output->name() );
1245 model()->updateDestinationParameters();
1247 emit requestModelRepaint();
1256QgsModelGroupBoxGraphicItem::QgsModelGroupBoxGraphicItem( QgsProcessingModelGroupBox *box, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1257 : QgsModelComponentGraphicItem( box, model, parent )
1259 setZValue( QgsModelGraphicsScene::ZValues::GroupBox );
1260 setLabel( box->description() );
1264 f.setPixelSize( 14 );
1268void QgsModelGroupBoxGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1270 QMenu *popupmenu =
new QMenu( event->widget() );
1271 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1272 connect( removeAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::deleteComponent );
1273 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1274 connect( editAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::editComponent );
1275 popupmenu->exec( event->screenPos() );
1278QgsModelGroupBoxGraphicItem::~QgsModelGroupBoxGraphicItem() =
default;
1280QColor QgsModelGroupBoxGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1282 QColor
c( 230, 230, 230 );
1286 c =
c.darker( 110 );
1289 c =
c.darker( 105 );
1298QColor QgsModelGroupBoxGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1303 return QColor( 50, 50, 50 );
1306 return QColor( 150, 150, 150 );
1311QColor QgsModelGroupBoxGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1313 return QColor( 100, 100, 100 );
1316Qt::PenStyle QgsModelGroupBoxGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1321Qt::Alignment QgsModelGroupBoxGraphicItem::titleAlignment()
const
1323 return Qt::AlignHCenter;
1326void QgsModelGroupBoxGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1328 if ( QgsProcessingModelGroupBox *box =
dynamic_cast< QgsProcessingModelGroupBox *
>( component() ) )
1330 box->setPosition( pos );
1331 box->setSize( size );
1332 model()->addGroupBox( *box );
1336bool QgsModelGroupBoxGraphicItem::canDeleteComponent()
1338 if (
dynamic_cast< QgsProcessingModelGroupBox *
>( component() ) )
1345void QgsModelGroupBoxGraphicItem::deleteComponent()
1347 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast< const QgsProcessingModelGroupBox *
>( component() ) )
1349 emit aboutToChange( tr(
"Delete Group Box" ) );
1350 model()->removeGroupBox( box->uuid() );
1352 emit requestModelRepaint();
1356void QgsModelGroupBoxGraphicItem::editComponent()
1358 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast< const QgsProcessingModelGroupBox *
>( component() ) )
1364 emit aboutToChange( tr(
"Edit Group Box" ) );
1365 model()->addGroupBox( dlg.groupBox() );
1367 emit requestModelRepaint();
1376QgsModelCommentGraphicItem::QgsModelCommentGraphicItem( QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1377 : QgsModelComponentGraphicItem( comment, model, parent )
1378 , mParentComponent( parentItem->component()->clone() )
1379 , mParentItem( parentItem )
1381 setLabel( comment->description() );
1384 f.setPixelSize( 9 );
1388void QgsModelCommentGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1390 QMenu *popupmenu =
new QMenu( event->widget() );
1391 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1392 connect( removeAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::deleteComponent );
1393 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1394 connect( editAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::editComponent );
1395 popupmenu->exec( event->screenPos() );
1398QgsModelCommentGraphicItem::~QgsModelCommentGraphicItem() =
default;
1400QColor QgsModelCommentGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1402 QColor
c( 230, 230, 230 );
1406 c =
c.darker( 110 );
1409 c =
c.darker( 105 );
1418QColor QgsModelCommentGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1423 return QColor( 50, 50, 50 );
1426 return QColor( 150, 150, 150 );
1431QColor QgsModelCommentGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1433 return QColor( 100, 100, 100 );
1436Qt::PenStyle QgsModelCommentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1441void QgsModelCommentGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1443 if ( QgsProcessingModelComment *comment = modelComponent() )
1445 comment->setPosition( pos );
1446 comment->setSize( size );
1450bool QgsModelCommentGraphicItem::canDeleteComponent()
1452 if ( modelComponent() )
1459void QgsModelCommentGraphicItem::deleteComponent()
1461 if ( QgsProcessingModelComment *comment = modelComponent() )
1463 emit aboutToChange( tr(
"Delete Comment" ) );
1464 comment->setDescription( QString() );
1466 emit requestModelRepaint();
1470void QgsModelCommentGraphicItem::editComponent()
1474 mParentItem->editComment();
1478QgsProcessingModelComment *QgsModelCommentGraphicItem::modelComponent()
1480 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( mParentComponent.get() ) )
1482 return model()->childAlgorithm( child->childId() ).comment();
1484 else if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( mParentComponent.get() ) )
1486 return model()->parameterComponent( param->parameterName() ).comment();
1488 else if (
const QgsProcessingModelOutput *output =
dynamic_cast< const QgsProcessingModelOutput *
>( mParentComponent.get() ) )
1490 return model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).comment();
1495QgsModelComponentGraphicItem *QgsModelCommentGraphicItem::parentComponentItem()
const
@ Success
Child was successfully executed.
@ NotExecuted
Child has not been executed.
@ Failed
Child encountered an error while executing.
@ Warning
Warning message.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
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.
Abstract base class for processing algorithms.
QgsProcessingParameterDefinitions destinationParameterDefinitions() const
Returns a list of destination parameters definitions utilized by the algorithm.
Encapsulates the results of running a child algorithm within a model.
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 allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
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.