17#include "moc_qgsmodelcomponentgraphicitem.cpp"
33#include <QSvgRenderer>
36#include <QGraphicsSceneHoverEvent>
37#include <QApplication>
44QgsModelComponentGraphicItem::QgsModelComponentGraphicItem( QgsProcessingModelComponent *component, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
45 : QGraphicsObject( parent )
46 , mComponent( component )
49 setAcceptHoverEvents(
true );
50 setFlag( QGraphicsItem::ItemIsSelectable,
true );
51 setFlag( QGraphicsItem::ItemSendsGeometryChanges,
true );
52 setZValue( QgsModelGraphicsScene::ZValues::ModelComponent );
54 mFont.setPixelSize( 12 );
58 QPainter painter( &editPicture );
59 svg.render( &painter );
61 mEditButton =
new QgsModelDesignerFlatButtonGraphicItem(
this, editPicture, QPointF( 0, 0 ) );
62 connect( mEditButton, &QgsModelDesignerFlatButtonGraphicItem::clicked,
this, &QgsModelComponentGraphicItem::editComponent );
65 QPicture deletePicture;
66 painter.begin( &deletePicture );
67 svg2.render( &painter );
69 mDeleteButton =
new QgsModelDesignerFlatButtonGraphicItem(
this, deletePicture, QPointF( 0, 0 ) );
70 connect( mDeleteButton, &QgsModelDesignerFlatButtonGraphicItem::clicked,
this, &QgsModelComponentGraphicItem::deleteComponent );
72 updateButtonPositions();
75QgsModelComponentGraphicItem::Flags QgsModelComponentGraphicItem::flags()
const
77 return QgsModelComponentGraphicItem::Flags();
80QgsModelComponentGraphicItem::~QgsModelComponentGraphicItem() =
default;
82QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
84 return mComponent.get();
87const QgsProcessingModelComponent *QgsModelComponentGraphicItem::component()
const
89 return mComponent.get();
92QgsProcessingModelAlgorithm *QgsModelComponentGraphicItem::model()
97QgsModelGraphicsView *QgsModelComponentGraphicItem::view()
99 if ( scene()->views().isEmpty() )
102 return qobject_cast< QgsModelGraphicsView * >( scene()->views().first() );
105QFont QgsModelComponentGraphicItem::font()
const
110void QgsModelComponentGraphicItem::setFont(
const QFont &font )
116void QgsModelComponentGraphicItem::moveComponentBy( qreal dx, qreal dy )
118 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
119 mComponent->setPosition( pos() );
121 emit aboutToChange( tr(
"Move %1" ).arg( mComponent->description() ) );
122 updateStoredComponentPosition( pos(), mComponent->size() );
125 emit sizePositionChanged();
126 emit updateArrowPaths();
129void QgsModelComponentGraphicItem::previewItemMove( qreal dx, qreal dy )
131 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
132 emit updateArrowPaths();
135void QgsModelComponentGraphicItem::setItemRect( QRectF rect )
137 rect = rect.normalized();
139 if ( rect.width() < MIN_COMPONENT_WIDTH )
140 rect.setWidth( MIN_COMPONENT_WIDTH );
141 if ( rect.height() < MIN_COMPONENT_HEIGHT )
142 rect.setHeight( MIN_COMPONENT_HEIGHT );
144 setPos( rect.center() );
145 prepareGeometryChange();
147 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
149 mComponent->setPosition( pos() );
150 mComponent->setSize( rect.size() );
151 updateStoredComponentPosition( pos(), mComponent->size() );
153 updateButtonPositions();
156 emit updateArrowPaths();
157 emit sizePositionChanged();
160QRectF QgsModelComponentGraphicItem::previewItemRectChange( QRectF rect )
162 rect = rect.normalized();
164 if ( rect.width() < MIN_COMPONENT_WIDTH )
165 rect.setWidth( MIN_COMPONENT_WIDTH );
166 if ( rect.height() < MIN_COMPONENT_HEIGHT )
167 rect.setHeight( MIN_COMPONENT_HEIGHT );
169 setPos( rect.center() );
170 prepareGeometryChange();
172 mTempSize = rect.size();
174 updateButtonPositions();
175 emit updateArrowPaths();
180void QgsModelComponentGraphicItem::finalizePreviewedItemRectChange( QRectF )
182 mComponent->setPosition( pos() );
183 prepareGeometryChange();
184 mComponent->setSize( mTempSize );
185 mTempSize = QSizeF();
187 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
188 updateStoredComponentPosition( pos(), mComponent->size() );
190 updateButtonPositions();
194 emit sizePositionChanged();
195 emit updateArrowPaths();
200 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
201 updateToolTip( mapFromScene( event->
modelPoint() ) );
206 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
207 updateToolTip( mapFromScene( event->
modelPoint() ) );
212 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
214 setToolTip( QString() );
219 emit repaintArrows();
226 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
230void QgsModelComponentGraphicItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * )
232 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
236void QgsModelComponentGraphicItem::hoverEnterEvent( QGraphicsSceneHoverEvent *event )
238 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
239 updateToolTip( event->pos() );
242void QgsModelComponentGraphicItem::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
244 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
245 updateToolTip( event->pos() );
248void QgsModelComponentGraphicItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * )
250 modelHoverLeaveEvent(
nullptr );
253QVariant QgsModelComponentGraphicItem::itemChange( QGraphicsItem::GraphicsItemChange change,
const QVariant &value )
257 case QGraphicsItem::ItemSelectedChange:
259 emit repaintArrows();
263 case QGraphicsItem::ItemSceneChange:
268 if ( linkPointCount( Qt::TopEdge ) )
270 mExpandTopButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::TopEdge ), QPointF( 0, 0 ) );
271 connect( mExpandTopButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [ = ](
bool folded ) { fold( Qt::TopEdge, folded ); } );
273 if ( linkPointCount( Qt::BottomEdge ) )
275 mExpandBottomButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::BottomEdge ), QPointF( 0, 0 ) );
276 connect( mExpandBottomButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [ = ](
bool folded ) { fold( Qt::BottomEdge, folded ); } );
279 updateButtonPositions();
288 return QGraphicsObject::itemChange( change, value );
291QRectF QgsModelComponentGraphicItem::boundingRect()
const
293 const QFontMetricsF fm( mFont );
294 const int linksAbove = linkPointCount( Qt::TopEdge );
295 const int linksBelow = linkPointCount( Qt::BottomEdge );
297 const double hUp = linksAbove == 0 ? 0 :
298 fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::TopEdge ) ? 0 : linksAbove ) + 2 );
299 const double hDown = linksBelow == 0 ? 0 :
300 fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::BottomEdge ) ? 0 : linksBelow ) + 2 );
301 return QRectF( -( itemSize().width() ) / 2 - RECT_PEN_SIZE,
302 -( itemSize().height() ) / 2 - hUp - RECT_PEN_SIZE,
303 itemSize().width() + 2 * RECT_PEN_SIZE,
304 itemSize().height() + hDown + hUp + 2 * RECT_PEN_SIZE );
307bool QgsModelComponentGraphicItem::contains(
const QPointF &point )
const
309 const QRectF paintingBounds = boundingRect();
310 if ( point.x() < paintingBounds.left() + RECT_PEN_SIZE )
312 if ( point.x() > paintingBounds.right() - RECT_PEN_SIZE )
314 if ( point.y() < paintingBounds.top() + RECT_PEN_SIZE )
316 if ( point.y() > paintingBounds.bottom() - RECT_PEN_SIZE )
322void QgsModelComponentGraphicItem::paint( QPainter *painter,
const QStyleOptionGraphicsItem *, QWidget * )
324 const QRectF rect = itemRect();
328 if ( mComponent->color().isValid() )
330 color = mComponent->color();
334 color = color.darker( 110 );
337 color = color.darker( 105 );
343 stroke = color.darker( 110 );
344 foreColor = color.lightness() > 150 ? QColor( 0, 0, 0 ) : QColor( 255, 255, 255 );
348 color = fillColor( state() );
349 stroke = strokeColor( state() );
350 foreColor = textColor( state() );
353 QPen strokePen = QPen( stroke, 0 ) ;
354 strokePen.setStyle( strokeStyle( state() ) );
355 painter->setPen( strokePen );
356 painter->setBrush( QBrush( color, Qt::SolidPattern ) );
357 painter->drawRect( rect );
358 painter->setFont( font() );
359 painter->setPen( QPen( foreColor ) );
363 const QSizeF componentSize = itemSize();
365 const QFontMetricsF fm( font() );
366 double h = fm.ascent();
367 QPointF pt( -componentSize.width() / 2 + 25, componentSize.height() / 2.0 - h + 1 );
369 if ( iconPicture().isNull() && iconPixmap().isNull() )
371 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 );
373 painter->drawText( labelRect, Qt::TextWordWrap | titleAlignment(), text );
377 const QRectF labelRect = QRectF( rect.left() + 21 + TEXT_MARGIN, rect.top() + TEXT_MARGIN,
378 rect.width() - 2 * TEXT_MARGIN - mButtonSize.width() - BUTTON_MARGIN - 21, rect.height() - 2 * TEXT_MARGIN );
380 painter->drawText( labelRect, Qt::TextWordWrap | Qt::AlignVCenter, text );
383 painter->setPen( QPen( QApplication::palette().color( QPalette::Text ) ) );
385 if ( linkPointCount( Qt::TopEdge ) || linkPointCount( Qt::BottomEdge ) )
387 h = -( fm.height() * 1.2 );
388 h = h - componentSize.height() / 2.0 + 5;
389 pt = QPointF( -componentSize.width() / 2 + 25, h );
390 painter->drawText( pt, QObject::tr(
"In" ) );
392 if ( !mComponent->linksCollapsed( Qt::TopEdge ) )
394 for (
int idx = 0; idx < linkPointCount( Qt::TopEdge ); ++idx )
396 text = linkPointText( Qt::TopEdge, idx );
397 h = -( fm.height() * 1.2 ) * ( i + 1 );
398 h = h - componentSize.height() / 2.0 + 5;
399 pt = QPointF( -componentSize.width() / 2 + 33, h );
400 painter->drawText( pt, text );
405 h = fm.height() * 1.1;
406 h = h + componentSize.height() / 2.0;
407 pt = QPointF( -componentSize.width() / 2 + 25, h );
408 painter->drawText( pt, QObject::tr(
"Out" ) );
409 if ( !mComponent->linksCollapsed( Qt::BottomEdge ) )
411 for (
int idx = 0; idx < linkPointCount( Qt::BottomEdge ); ++idx )
413 text = linkPointText( Qt::BottomEdge, idx );
414 h = fm.height() * 1.2 * ( idx + 2 );
415 h = h + componentSize.height() / 2.0;
416 pt = QPointF( -componentSize.width() / 2 + 33, h );
417 painter->drawText( pt, text );
422 const QPixmap px = iconPixmap();
425 painter->drawPixmap( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), px );
429 const QPicture pic = iconPicture();
432 painter->drawPicture( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), pic );
437QRectF QgsModelComponentGraphicItem::itemRect(
bool storedRect )
const
441 return QRectF( mComponent->position().x() - ( mComponent->size().width() ) / 2.0,
442 mComponent->position().y() - ( mComponent->size().height() ) / 2.0,
443 mComponent->size().width(),
444 mComponent->size().height() );
447 return QRectF( -( itemSize().width() ) / 2.0,
448 -( itemSize().height() ) / 2.0,
450 itemSize().height() );
453QString QgsModelComponentGraphicItem::truncatedTextForItem(
const QString &text )
const
455 const QFontMetricsF fm( mFont );
456 double width = fm.boundingRect( text ).width();
457 if ( width < itemSize().width() - 25 - mButtonSize.width() )
461 t = t.left( t.length() - 3 ) + QChar( 0x2026 );
462 width = fm.boundingRect( t ).width();
463 while ( width > itemSize().width() - 25 - mButtonSize.width() )
465 if ( t.length() < 5 )
468 t = t.left( t.length() - 4 ) + QChar( 0x2026 );
469 width = fm.boundingRect( t ).width();
474Qt::PenStyle QgsModelComponentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
476 return Qt::SolidLine;
479Qt::Alignment QgsModelComponentGraphicItem::titleAlignment()
const
481 return Qt::AlignLeft;
484QPicture QgsModelComponentGraphicItem::iconPicture()
const
489QPixmap QgsModelComponentGraphicItem::iconPixmap()
const
494void QgsModelComponentGraphicItem::updateButtonPositions()
496 mEditButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN,
497 itemSize().height() / 2.0 - mButtonSize.height() / 2.0 - BUTTON_MARGIN ) );
498 mDeleteButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN,
499 mButtonSize.height() / 2.0 - itemSize().height() / 2.0 + BUTTON_MARGIN ) );
501 if ( mExpandTopButton )
503 const QPointF pt = linkPoint( Qt::TopEdge, -1,
true );
504 mExpandTopButton->setPosition( QPointF( 0, pt.y() ) );
506 if ( mExpandBottomButton )
508 const QPointF pt = linkPoint( Qt::BottomEdge, -1,
false );
509 mExpandBottomButton->setPosition( QPointF( 0, pt.y() ) );
513QSizeF QgsModelComponentGraphicItem::itemSize()
const
515 return !mTempSize.isValid() ? mComponent->size() : mTempSize;
518void QgsModelComponentGraphicItem::updateToolTip(
const QPointF &pos )
520 const bool prevHoverStatus = mIsHovering;
521 if ( itemRect().contains( pos ) )
523 setToolTip( mLabel );
528 setToolTip( QString() );
531 if ( mIsHovering != prevHoverStatus )
534 emit repaintArrows();
538void QgsModelComponentGraphicItem::fold( Qt::Edge edge,
bool folded )
540 emit aboutToChange( !folded ? tr(
"Expand Item" ) : tr(
"Collapse Item" ) );
541 mComponent->setLinksCollapsed( edge, folded );
545 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast< QgsProcessingModelChildAlgorithm *
>( mComponent.get() ) )
546 mModel->childAlgorithm( child->childId() ).setLinksCollapsed( edge, folded );
547 else if ( QgsProcessingModelParameter *param =
dynamic_cast< QgsProcessingModelParameter *
>( mComponent.get() ) )
548 mModel->parameterComponent( param->parameterName() ).setLinksCollapsed( edge, folded );
549 else if ( QgsProcessingModelOutput *output =
dynamic_cast< QgsProcessingModelOutput *
>( mComponent.get() ) )
550 mModel->childAlgorithm( output->childId() ).modelOutput( output->name() ).setLinksCollapsed( edge, folded );
552 prepareGeometryChange();
553 emit updateArrowPaths();
558QString QgsModelComponentGraphicItem::label()
const
563void QgsModelComponentGraphicItem::setLabel(
const QString &label )
569QgsModelComponentGraphicItem::State QgsModelComponentGraphicItem::state()
const
573 else if ( mIsHovering )
579int QgsModelComponentGraphicItem::linkPointCount( Qt::Edge )
const
584QString QgsModelComponentGraphicItem::linkPointText( Qt::Edge,
int )
const
589QPointF QgsModelComponentGraphicItem::linkPoint( Qt::Edge edge,
int index,
bool incoming )
const
595 if ( linkPointCount( Qt::BottomEdge ) )
598 if ( mComponent->linksCollapsed( Qt::BottomEdge ) )
602 const int pointIndex = !mComponent->linksCollapsed( Qt::BottomEdge ) ? index : -1;
603 const QString text = truncatedTextForItem( linkPointText( Qt::BottomEdge, index ) );
604 const QFontMetricsF fm( mFont );
605 const double w = fm.boundingRect( text ).width();
606 const double h = fm.height() * 1.2 * ( pointIndex + 1 ) + fm.height() / 2.0;
607 const double y = h + itemSize().height() / 2.0 + 5;
608 const double x = !mComponent->linksCollapsed( Qt::BottomEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10;
609 return QPointF( incoming ? -itemSize().width() / 2 + offsetX
618 if ( linkPointCount( Qt::TopEdge ) )
621 int paramIndex = index;
622 if ( mComponent->linksCollapsed( Qt::TopEdge ) )
627 const QFontMetricsF fm( mFont );
628 const QString text = truncatedTextForItem( linkPointText( Qt::TopEdge, index ) );
629 const double w = fm.boundingRect( text ).width();
630 double h = -( fm.height() * 1.2 ) * ( paramIndex + 2 ) - fm.height() / 2.0 + 8;
631 h = h - itemSize().height() / 2.0;
632 return QPointF( incoming ? -itemSize().width() / 2 + offsetX
633 : ( !mComponent->linksCollapsed( Qt::TopEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10 ),
646QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint( QgsModelComponentGraphicItem *other, Qt::Edge &edge )
const
649 const QgsRectangle otherRect( other->itemRect().translated( other->pos() ) );
651 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
652 const double distLeft = otherRect.distance(
QgsPointXY( leftPoint ) );
654 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
655 const double distRight = otherRect.distance(
QgsPointXY( rightPoint ) );
657 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
658 const double distTop = otherRect.distance(
QgsPointXY( topPoint ) );
660 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
661 const double distBottom = otherRect.distance(
QgsPointXY( bottomPoint ) );
663 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
668 else if ( distRight <= distTop && distRight <= distBottom )
670 edge = Qt::RightEdge;
673 else if ( distBottom <= distTop )
675 edge = Qt::BottomEdge;
685QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint(
const QPointF &point, Qt::Edge &edge )
const
689 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
690 const double distLeft = otherPt.distance(
QgsPointXY( leftPoint ) );
692 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
693 const double distRight = otherPt.distance(
QgsPointXY( rightPoint ) );
695 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
696 const double distTop = otherPt.distance(
QgsPointXY( topPoint ) );
698 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
699 const double distBottom = otherPt.distance(
QgsPointXY( bottomPoint ) );
701 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
706 else if ( distRight <= distTop && distRight <= distBottom )
708 edge = Qt::RightEdge;
711 else if ( distBottom <= distTop )
713 edge = Qt::BottomEdge;
723QgsModelParameterGraphicItem::QgsModelParameterGraphicItem( QgsProcessingModelParameter *parameter, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
724 : QgsModelComponentGraphicItem( parameter, model, parent )
727 QPainter painter( &mPicture );
728 svg.render( &painter );
732 setLabel( paramDef->description() );
734 setLabel( QObject::tr(
"Error (%1)" ).arg( parameter->parameterName() ) );
737void QgsModelParameterGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
739 QMenu *popupmenu =
new QMenu( event->widget() );
740 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
741 connect( removeAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::deleteComponent );
742 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
743 connect( editAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComponent );
744 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
745 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
747 popupmenu->exec( event->screenPos() );
750QColor QgsModelParameterGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
752 QColor
c( 238, 242, 131 );
768QColor QgsModelParameterGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
773 return QColor( 116, 113, 68 );
776 return QColor( 234, 226, 118 );
781QColor QgsModelParameterGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
786QPicture QgsModelParameterGraphicItem::iconPicture()
const
791void QgsModelParameterGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
793 if ( QgsProcessingModelParameter *param =
dynamic_cast< QgsProcessingModelParameter *
>( component() ) )
795 model()->parameterComponent( param->parameterName() ).setPosition( pos );
796 model()->parameterComponent( param->parameterName() ).setSize( size );
800bool QgsModelParameterGraphicItem::canDeleteComponent()
802 if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( component() ) )
804 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
808 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
820void QgsModelParameterGraphicItem::deleteComponent()
822 if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( component() ) )
824 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
826 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ),
827 QObject::tr(
"Algorithms depend on the selected input.\n"
828 "Remove them before trying to remove it." ) );
830 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
832 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ),
833 QObject::tr(
"Other inputs depend on the selected input.\n"
834 "Remove them before trying to remove it." ) );
838 emit aboutToChange( tr(
"Delete Input %1" ).arg( param->description() ) );
839 model()->removeModelParameter( param->parameterName() );
841 emit requestModelRepaint();
848QgsModelChildAlgorithmGraphicItem::QgsModelChildAlgorithmGraphicItem( QgsProcessingModelChildAlgorithm *child, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
849 : QgsModelComponentGraphicItem( child, model, parent )
851 if ( child->algorithm() && !child->algorithm()->svgIconPath().isEmpty() )
853 QSvgRenderer svg( child->algorithm()->svgIconPath() );
854 const QSizeF size = svg.defaultSize();
855 QPainter painter( &mPicture );
856 painter.scale( 16.0 / size.width(), 16.0 / size.width() );
857 svg.render( &painter );
860 else if ( child->algorithm() )
862 mPixmap = child->algorithm()->icon().pixmap( 15, 15 );
865 setLabel( child->description() );
868 mIsValid = model->validateChildAlgorithm( child->childId(), issues );
871void QgsModelChildAlgorithmGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
873 QMenu *popupmenu =
new QMenu( event->widget() );
877 QAction *runSelectedStepsAction = popupmenu->addAction( QObject::tr(
"Run Selected Steps…" ) );
879 connect( runSelectedStepsAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runSelected );
882 QAction *runFromHereAction = popupmenu->addAction( QObject::tr(
"Run from Here…" ) );
884 connect( runFromHereAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runFromHere );
886 popupmenu->addSeparator();
888 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
889 connect( removeAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deleteComponent );
890 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
891 connect( editAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::editComponent );
892 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
893 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
894 popupmenu->addSeparator();
896 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
898 if ( !child->isActive() )
900 QAction *activateAction = popupmenu->addAction( QObject::tr(
"Activate" ) );
901 connect( activateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::activateAlgorithm );
905 QAction *deactivateAction = popupmenu->addAction( QObject::tr(
"Deactivate" ) );
906 connect( deactivateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm );
913 if ( !outputParams.isEmpty() )
915 popupmenu->addSeparator();
916 QAction *viewOutputLayersAction = popupmenu->addAction( QObject::tr(
"View Output Layers" ) );
918 connect( viewOutputLayersAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showPreviousResults );
920 switch ( mResults.executionStatus() )
924 viewOutputLayersAction->setEnabled(
false );
933 QAction *viewLogAction = popupmenu->addAction( QObject::tr(
"View Log…" ) );
934 connect( viewLogAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showLog );
936 switch ( mResults.executionStatus() )
939 viewLogAction->setEnabled(
false );
948 popupmenu->exec( event->screenPos() );
951QColor QgsModelChildAlgorithmGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
956 c = QColor( 255, 255, 255 );
958 c = QColor( 208, 0, 0 );
975QColor QgsModelChildAlgorithmGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
980 return mIsValid ? QColor( 50, 50, 50 ) : QColor( 80, 0, 0 );
983 return mIsValid ? Qt::gray : QColor( 134, 0, 0 );
988QColor QgsModelChildAlgorithmGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
990 return mIsValid ? ( qgis::down_cast< const QgsProcessingModelChildAlgorithm * >( component() )->isActive() ? Qt::black : Qt::gray ) : QColor( 255, 255, 255 );
993QPixmap QgsModelChildAlgorithmGraphicItem::iconPixmap()
const
998QPicture QgsModelChildAlgorithmGraphicItem::iconPicture()
const
1003int QgsModelChildAlgorithmGraphicItem::linkPointCount( Qt::Edge edge )
const
1005 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1007 if ( !child->algorithm() )
1012 case Qt::BottomEdge:
1013 return child->algorithm()->outputDefinitions().size();
1019 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1020 } ), params.end() );
1021 return params.size();
1032QString QgsModelChildAlgorithmGraphicItem::linkPointText( Qt::Edge edge,
int index )
const
1037 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1039 if ( !child->algorithm() )
1042 const QVariantMap inputs = mResults.inputs();
1043 const QVariantMap outputs = mResults.outputs();
1046 case Qt::BottomEdge:
1048 if ( index >= child->algorithm()->outputDefinitions().length() )
1052 tr(
"Cannot link output for child: %1" ).arg( child->algorithm()->name() ),
1059 if ( outputs.contains( output->
name() ) )
1061 title += QStringLiteral(
": %1" ).arg( outputs.value( output->
name() ).toString() );
1063 return truncatedTextForItem( title );
1071 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1072 } ), params.end() );
1074 if ( index >= params.length() )
1078 tr(
"Cannot link source for child: %1" ).arg( child->algorithm()->name() ),
1083 QString title = params.at( index )->description();
1084 if ( !inputs.value( params.at( index )->name() ).toString().isEmpty() )
1085 title += QStringLiteral(
": %1" ).arg( inputs.value( params.at( index )->name() ).toString() );
1086 return truncatedTextForItem( title );
1097void QgsModelChildAlgorithmGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1099 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast< QgsProcessingModelChildAlgorithm *
>( component() ) )
1101 model()->childAlgorithm( child->childId() ).setPosition( pos );
1102 model()->childAlgorithm( child->childId() ).setSize( size );
1106bool QgsModelChildAlgorithmGraphicItem::canDeleteComponent()
1108 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1110 return model()->dependentChildAlgorithms( child->childId() ).empty();
1117 if ( mResults == results )
1122 emit updateArrowPaths();
1125void QgsModelChildAlgorithmGraphicItem::deleteComponent()
1127 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1129 emit aboutToChange( tr(
"Remove %1" ).arg( child->algorithm() ? child->algorithm()->displayName() : tr(
"Algorithm" ) ) );
1130 if ( !model()->removeChildAlgorithm( child->childId() ) )
1132 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove algorithm" ),
1133 QObject::tr(
"Other algorithms depend on the selected one.\n"
1134 "Remove them before trying to remove it." ) );
1139 emit requestModelRepaint();
1144void QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm()
1146 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1148 model()->deactivateChildAlgorithm( child->childId() );
1149 emit requestModelRepaint();
1153void QgsModelChildAlgorithmGraphicItem::activateAlgorithm()
1155 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( component() ) )
1157 if ( model()->activateChildAlgorithm( child->childId() ) )
1159 emit requestModelRepaint();
1163 QMessageBox::warning(
nullptr, QObject::tr(
"Could not activate algorithm" ),
1164 QObject::tr(
"The selected algorithm depends on other currently non-active algorithms.\n"
1165 "Activate them them before trying to activate it.." ) );
1171QgsModelOutputGraphicItem::QgsModelOutputGraphicItem( QgsProcessingModelOutput *output, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1172 : QgsModelComponentGraphicItem( output, model, parent )
1175 QPainter painter( &mPicture );
1176 svg.render( &painter );
1178 setLabel( output->description() );
1181QColor QgsModelOutputGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1183 QColor
c( 172, 196, 114 );
1187 c =
c.darker( 110 );
1190 c =
c.darker( 105 );
1199QColor QgsModelOutputGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1204 return QColor( 42, 65, 42 );
1207 return QColor( 90, 140, 90 );
1212QColor QgsModelOutputGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1217QPicture QgsModelOutputGraphicItem::iconPicture()
const
1222void QgsModelOutputGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1224 if ( QgsProcessingModelOutput *output =
dynamic_cast< QgsProcessingModelOutput *
>( component() ) )
1226 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setPosition( pos );
1227 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setSize( size );
1231bool QgsModelOutputGraphicItem::canDeleteComponent()
1233 if (
dynamic_cast< const QgsProcessingModelOutput *
>( component() ) )
1240void QgsModelOutputGraphicItem::deleteComponent()
1242 if (
const QgsProcessingModelOutput *output =
dynamic_cast< const QgsProcessingModelOutput *
>( component() ) )
1244 emit aboutToChange( tr(
"Delete Output %1" ).arg( output->description() ) );
1245 model()->childAlgorithm( output->childId() ).removeModelOutput( output->name() );
1246 model()->updateDestinationParameters();
1248 emit requestModelRepaint();
1257QgsModelGroupBoxGraphicItem::QgsModelGroupBoxGraphicItem( QgsProcessingModelGroupBox *box, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1258 : QgsModelComponentGraphicItem( box, model, parent )
1260 setZValue( QgsModelGraphicsScene::ZValues::GroupBox );
1261 setLabel( box->description() );
1265 f.setPixelSize( 14 );
1269void QgsModelGroupBoxGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1271 QMenu *popupmenu =
new QMenu( event->widget() );
1272 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1273 connect( removeAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::deleteComponent );
1274 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1275 connect( editAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::editComponent );
1276 popupmenu->exec( event->screenPos() );
1279QgsModelGroupBoxGraphicItem::~QgsModelGroupBoxGraphicItem() =
default;
1281QColor QgsModelGroupBoxGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1283 QColor
c( 230, 230, 230 );
1287 c =
c.darker( 110 );
1290 c =
c.darker( 105 );
1299QColor QgsModelGroupBoxGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1304 return QColor( 50, 50, 50 );
1307 return QColor( 150, 150, 150 );
1312QColor QgsModelGroupBoxGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1314 return QColor( 100, 100, 100 );
1317Qt::PenStyle QgsModelGroupBoxGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1322Qt::Alignment QgsModelGroupBoxGraphicItem::titleAlignment()
const
1324 return Qt::AlignHCenter;
1327void QgsModelGroupBoxGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1329 if ( QgsProcessingModelGroupBox *box =
dynamic_cast< QgsProcessingModelGroupBox *
>( component() ) )
1331 box->setPosition( pos );
1332 box->setSize( size );
1333 model()->addGroupBox( *box );
1337bool QgsModelGroupBoxGraphicItem::canDeleteComponent()
1339 if (
dynamic_cast< QgsProcessingModelGroupBox *
>( component() ) )
1346void QgsModelGroupBoxGraphicItem::deleteComponent()
1348 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast< const QgsProcessingModelGroupBox *
>( component() ) )
1350 emit aboutToChange( tr(
"Delete Group Box" ) );
1351 model()->removeGroupBox( box->uuid() );
1353 emit requestModelRepaint();
1357void QgsModelGroupBoxGraphicItem::editComponent()
1359 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast< const QgsProcessingModelGroupBox *
>( component() ) )
1365 emit aboutToChange( tr(
"Edit Group Box" ) );
1366 model()->addGroupBox( dlg.groupBox() );
1368 emit requestModelRepaint();
1377QgsModelCommentGraphicItem::QgsModelCommentGraphicItem( QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1378 : QgsModelComponentGraphicItem( comment, model, parent )
1379 , mParentComponent( parentItem->component()->clone() )
1380 , mParentItem( parentItem )
1382 setLabel( comment->description() );
1385 f.setPixelSize( 9 );
1389void QgsModelCommentGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1391 QMenu *popupmenu =
new QMenu( event->widget() );
1392 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1393 connect( removeAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::deleteComponent );
1394 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1395 connect( editAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::editComponent );
1396 popupmenu->exec( event->screenPos() );
1399QgsModelCommentGraphicItem::~QgsModelCommentGraphicItem() =
default;
1401QColor QgsModelCommentGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1403 QColor
c( 230, 230, 230 );
1407 c =
c.darker( 110 );
1410 c =
c.darker( 105 );
1419QColor QgsModelCommentGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1424 return QColor( 50, 50, 50 );
1427 return QColor( 150, 150, 150 );
1432QColor QgsModelCommentGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1434 return QColor( 100, 100, 100 );
1437Qt::PenStyle QgsModelCommentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1442void QgsModelCommentGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1444 if ( QgsProcessingModelComment *comment = modelComponent() )
1446 comment->setPosition( pos );
1447 comment->setSize( size );
1451bool QgsModelCommentGraphicItem::canDeleteComponent()
1453 if ( modelComponent() )
1460void QgsModelCommentGraphicItem::deleteComponent()
1462 if ( QgsProcessingModelComment *comment = modelComponent() )
1464 emit aboutToChange( tr(
"Delete Comment" ) );
1465 comment->setDescription( QString() );
1467 emit requestModelRepaint();
1471void QgsModelCommentGraphicItem::editComponent()
1475 mParentItem->editComment();
1479QgsProcessingModelComment *QgsModelCommentGraphicItem::modelComponent()
1481 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast< const QgsProcessingModelChildAlgorithm *
>( mParentComponent.get() ) )
1483 return model()->childAlgorithm( child->childId() ).comment();
1485 else if (
const QgsProcessingModelParameter *param =
dynamic_cast< const QgsProcessingModelParameter *
>( mParentComponent.get() ) )
1487 return model()->parameterComponent( param->parameterName() ).comment();
1489 else if (
const QgsProcessingModelOutput *output =
dynamic_cast< const QgsProcessingModelOutput *
>( mParentComponent.get() ) )
1491 return model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).comment();
1496QgsModelComponentGraphicItem *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.