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 : fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::TopEdge ) ? 0 : linksAbove ) + 2 );
298 const double hDown = linksBelow == 0 ? 0 : fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::BottomEdge ) ? 0 : linksBelow ) + 2 );
299 return QRectF( -( itemSize().width() ) / 2 - RECT_PEN_SIZE, -( itemSize().height() ) / 2 - hUp - RECT_PEN_SIZE, itemSize().width() + 2 * RECT_PEN_SIZE, itemSize().height() + hDown + hUp + 2 * RECT_PEN_SIZE );
302bool QgsModelComponentGraphicItem::contains(
const QPointF &point )
const
304 const QRectF paintingBounds = boundingRect();
305 if ( point.x() < paintingBounds.left() + RECT_PEN_SIZE )
307 if ( point.x() > paintingBounds.right() - RECT_PEN_SIZE )
309 if ( point.y() < paintingBounds.top() + RECT_PEN_SIZE )
311 if ( point.y() > paintingBounds.bottom() - RECT_PEN_SIZE )
317void QgsModelComponentGraphicItem::paint( QPainter *painter,
const QStyleOptionGraphicsItem *, QWidget * )
319 const QRectF rect = itemRect();
323 if ( mComponent->color().isValid() )
325 color = mComponent->color();
329 color = color.darker( 110 );
332 color = color.darker( 105 );
338 stroke = color.darker( 110 );
339 foreColor = color.lightness() > 150 ? QColor( 0, 0, 0 ) : QColor( 255, 255, 255 );
343 color = fillColor( state() );
344 stroke = strokeColor( state() );
345 foreColor = textColor( state() );
348 QPen strokePen = QPen( stroke, 0 );
349 strokePen.setStyle( strokeStyle( state() ) );
350 painter->setPen( strokePen );
351 painter->setBrush( QBrush( color, Qt::SolidPattern ) );
352 painter->drawRect( rect );
353 painter->setFont( font() );
354 painter->setPen( QPen( foreColor ) );
358 const QSizeF componentSize = itemSize();
360 const QFontMetricsF fm( font() );
361 double h = fm.ascent();
362 QPointF pt( -componentSize.width() / 2 + 25, componentSize.height() / 2.0 - h + 1 );
364 if ( iconPicture().isNull() && iconPixmap().isNull() )
366 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 );
368 painter->drawText( labelRect, Qt::TextWordWrap | titleAlignment(), text );
372 const QRectF labelRect = QRectF( rect.left() + 21 + TEXT_MARGIN, rect.top() + TEXT_MARGIN, rect.width() - 2 * TEXT_MARGIN - mButtonSize.width() - BUTTON_MARGIN - 21, rect.height() - 2 * TEXT_MARGIN );
374 painter->drawText( labelRect, Qt::TextWordWrap | Qt::AlignVCenter, text );
377 painter->setPen( QPen( QApplication::palette().color( QPalette::Text ) ) );
379 if ( linkPointCount( Qt::TopEdge ) || linkPointCount( Qt::BottomEdge ) )
381 h = -( fm.height() * 1.2 );
382 h = h - componentSize.height() / 2.0 + 5;
383 pt = QPointF( -componentSize.width() / 2 + 25, h );
384 painter->drawText( pt, QObject::tr(
"In" ) );
386 if ( !mComponent->linksCollapsed( Qt::TopEdge ) )
388 for (
int idx = 0; idx < linkPointCount( Qt::TopEdge ); ++idx )
390 text = linkPointText( Qt::TopEdge, idx );
391 h = -( fm.height() * 1.2 ) * ( i + 1 );
392 h = h - componentSize.height() / 2.0 + 5;
393 pt = QPointF( -componentSize.width() / 2 + 33, h );
394 painter->drawText( pt, text );
399 h = fm.height() * 1.1;
400 h = h + componentSize.height() / 2.0;
401 pt = QPointF( -componentSize.width() / 2 + 25, h );
402 painter->drawText( pt, QObject::tr(
"Out" ) );
403 if ( !mComponent->linksCollapsed( Qt::BottomEdge ) )
405 for (
int idx = 0; idx < linkPointCount( Qt::BottomEdge ); ++idx )
407 text = linkPointText( Qt::BottomEdge, idx );
408 h = fm.height() * 1.2 * ( idx + 2 );
409 h = h + componentSize.height() / 2.0;
410 pt = QPointF( -componentSize.width() / 2 + 33, h );
411 painter->drawText( pt, text );
416 const QPixmap px = iconPixmap();
419 painter->drawPixmap( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), px );
423 const QPicture pic = iconPicture();
426 painter->drawPicture( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), pic );
431QRectF QgsModelComponentGraphicItem::itemRect(
bool storedRect )
const
435 return QRectF( mComponent->position().x() - ( mComponent->size().width() ) / 2.0, mComponent->position().y() - ( mComponent->size().height() ) / 2.0, mComponent->size().width(), mComponent->size().height() );
438 return QRectF( -( itemSize().width() ) / 2.0, -( itemSize().height() ) / 2.0, itemSize().width(), itemSize().height() );
441QString QgsModelComponentGraphicItem::truncatedTextForItem(
const QString &text )
const
443 const QFontMetricsF fm( mFont );
444 double width = fm.boundingRect( text ).width();
445 if ( width < itemSize().width() - 25 - mButtonSize.width() )
449 t = t.left( t.length() - 3 ) + QChar( 0x2026 );
450 width = fm.boundingRect( t ).width();
451 while ( width > itemSize().width() - 25 - mButtonSize.width() )
453 if ( t.length() < 5 )
456 t = t.left( t.length() - 4 ) + QChar( 0x2026 );
457 width = fm.boundingRect( t ).width();
462Qt::PenStyle QgsModelComponentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
464 return Qt::SolidLine;
467Qt::Alignment QgsModelComponentGraphicItem::titleAlignment()
const
469 return Qt::AlignLeft;
472QPicture QgsModelComponentGraphicItem::iconPicture()
const
477QPixmap QgsModelComponentGraphicItem::iconPixmap()
const
482void QgsModelComponentGraphicItem::updateButtonPositions()
484 mEditButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN, itemSize().height() / 2.0 - mButtonSize.height() / 2.0 - BUTTON_MARGIN ) );
485 mDeleteButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN, mButtonSize.height() / 2.0 - itemSize().height() / 2.0 + BUTTON_MARGIN ) );
487 if ( mExpandTopButton )
489 const QPointF pt = linkPoint( Qt::TopEdge, -1,
true );
490 mExpandTopButton->setPosition( QPointF( 0, pt.y() ) );
492 if ( mExpandBottomButton )
494 const QPointF pt = linkPoint( Qt::BottomEdge, -1,
false );
495 mExpandBottomButton->setPosition( QPointF( 0, pt.y() ) );
499QSizeF QgsModelComponentGraphicItem::itemSize()
const
501 return !mTempSize.isValid() ? mComponent->size() : mTempSize;
504void QgsModelComponentGraphicItem::updateToolTip(
const QPointF &pos )
506 const bool prevHoverStatus = mIsHovering;
507 if ( itemRect().contains( pos ) )
509 setToolTip( mLabel );
514 setToolTip( QString() );
517 if ( mIsHovering != prevHoverStatus )
520 emit repaintArrows();
524void QgsModelComponentGraphicItem::fold( Qt::Edge edge,
bool folded )
526 emit aboutToChange( !folded ? tr(
"Expand Item" ) : tr(
"Collapse Item" ) );
527 mComponent->setLinksCollapsed( edge, folded );
531 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast<QgsProcessingModelChildAlgorithm *
>( mComponent.get() ) )
532 mModel->childAlgorithm( child->childId() ).setLinksCollapsed( edge, folded );
533 else if ( QgsProcessingModelParameter *param =
dynamic_cast<QgsProcessingModelParameter *
>( mComponent.get() ) )
534 mModel->parameterComponent( param->parameterName() ).setLinksCollapsed( edge, folded );
535 else if ( QgsProcessingModelOutput *output =
dynamic_cast<QgsProcessingModelOutput *
>( mComponent.get() ) )
536 mModel->childAlgorithm( output->childId() ).modelOutput( output->name() ).setLinksCollapsed( edge, folded );
538 prepareGeometryChange();
539 emit updateArrowPaths();
544QString QgsModelComponentGraphicItem::label()
const
549void QgsModelComponentGraphicItem::setLabel(
const QString &label )
555QgsModelComponentGraphicItem::State QgsModelComponentGraphicItem::state()
const
559 else if ( mIsHovering )
565int QgsModelComponentGraphicItem::linkPointCount( Qt::Edge )
const
570QString QgsModelComponentGraphicItem::linkPointText( Qt::Edge,
int )
const
575QPointF QgsModelComponentGraphicItem::linkPoint( Qt::Edge edge,
int index,
bool incoming )
const
581 if ( linkPointCount( Qt::BottomEdge ) )
584 if ( mComponent->linksCollapsed( Qt::BottomEdge ) )
588 const int pointIndex = !mComponent->linksCollapsed( Qt::BottomEdge ) ? index : -1;
589 const QString text = truncatedTextForItem( linkPointText( Qt::BottomEdge, index ) );
590 const QFontMetricsF fm( mFont );
591 const double w = fm.boundingRect( text ).width();
592 const double h = fm.height() * 1.2 * ( pointIndex + 1 ) + fm.height() / 2.0;
593 const double y = h + itemSize().height() / 2.0 + 5;
594 const double x = !mComponent->linksCollapsed( Qt::BottomEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10;
595 return QPointF( incoming ? -itemSize().width() / 2 + offsetX : x, y );
602 if ( linkPointCount( Qt::TopEdge ) )
605 int paramIndex = index;
606 if ( mComponent->linksCollapsed( Qt::TopEdge ) )
611 const QFontMetricsF fm( mFont );
612 const QString text = truncatedTextForItem( linkPointText( Qt::TopEdge, index ) );
613 const double w = fm.boundingRect( text ).width();
614 double h = -( fm.height() * 1.2 ) * ( paramIndex + 2 ) - fm.height() / 2.0 + 8;
615 h = h - itemSize().height() / 2.0;
616 return QPointF( incoming ? -itemSize().width() / 2 + offsetX : ( !mComponent->linksCollapsed( Qt::TopEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10 ), h );
628QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint( QgsModelComponentGraphicItem *other, Qt::Edge &edge )
const
631 const QgsRectangle otherRect( other->itemRect().translated( other->pos() ) );
633 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
634 const double distLeft = otherRect.distance(
QgsPointXY( leftPoint ) );
636 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
637 const double distRight = otherRect.distance(
QgsPointXY( rightPoint ) );
639 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
640 const double distTop = otherRect.distance(
QgsPointXY( topPoint ) );
642 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
643 const double distBottom = otherRect.distance(
QgsPointXY( bottomPoint ) );
645 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
650 else if ( distRight <= distTop && distRight <= distBottom )
652 edge = Qt::RightEdge;
655 else if ( distBottom <= distTop )
657 edge = Qt::BottomEdge;
667QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint(
const QPointF &point, Qt::Edge &edge )
const
671 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
672 const double distLeft = otherPt.distance(
QgsPointXY( leftPoint ) );
674 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
675 const double distRight = otherPt.distance(
QgsPointXY( rightPoint ) );
677 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
678 const double distTop = otherPt.distance(
QgsPointXY( topPoint ) );
680 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
681 const double distBottom = otherPt.distance(
QgsPointXY( bottomPoint ) );
683 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
688 else if ( distRight <= distTop && distRight <= distBottom )
690 edge = Qt::RightEdge;
693 else if ( distBottom <= distTop )
695 edge = Qt::BottomEdge;
705QgsModelParameterGraphicItem::QgsModelParameterGraphicItem( QgsProcessingModelParameter *parameter, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
706 : QgsModelComponentGraphicItem( parameter, model, parent )
709 QPainter painter( &mPicture );
710 svg.render( &painter );
714 setLabel( paramDef->description() );
716 setLabel( QObject::tr(
"Error (%1)" ).arg( parameter->parameterName() ) );
719void QgsModelParameterGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
721 QMenu *popupmenu =
new QMenu( event->widget() );
722 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
723 connect( removeAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::deleteComponent );
724 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
725 connect( editAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComponent );
726 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
727 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
729 popupmenu->exec( event->screenPos() );
732QColor QgsModelParameterGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
734 QColor
c( 238, 242, 131 );
750QColor QgsModelParameterGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
755 return QColor( 116, 113, 68 );
758 return QColor( 234, 226, 118 );
763QColor QgsModelParameterGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
768QPicture QgsModelParameterGraphicItem::iconPicture()
const
773void QgsModelParameterGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
775 if ( QgsProcessingModelParameter *param =
dynamic_cast<QgsProcessingModelParameter *
>( component() ) )
777 model()->parameterComponent( param->parameterName() ).setPosition( pos );
778 model()->parameterComponent( param->parameterName() ).setSize( size );
782bool QgsModelParameterGraphicItem::canDeleteComponent()
784 if (
const QgsProcessingModelParameter *param =
dynamic_cast<const QgsProcessingModelParameter *
>( component() ) )
786 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
790 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
802void QgsModelParameterGraphicItem::deleteComponent()
804 if (
const QgsProcessingModelParameter *param =
dynamic_cast<const QgsProcessingModelParameter *
>( component() ) )
806 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
808 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ), QObject::tr(
"Algorithms depend on the selected input.\n"
809 "Remove them before trying to remove it." ) );
811 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
813 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ), QObject::tr(
"Other inputs depend on the selected input.\n"
814 "Remove them before trying to remove it." ) );
818 emit aboutToChange( tr(
"Delete Input %1" ).arg( param->description() ) );
819 model()->removeModelParameter( param->parameterName() );
821 emit requestModelRepaint();
827QgsModelChildAlgorithmGraphicItem::QgsModelChildAlgorithmGraphicItem( QgsProcessingModelChildAlgorithm *child, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
828 : QgsModelComponentGraphicItem( child, model, parent )
830 if ( child->algorithm() && !child->algorithm()->svgIconPath().isEmpty() )
832 QSvgRenderer svg( child->algorithm()->svgIconPath() );
833 const QSizeF size = svg.defaultSize();
834 QPainter painter( &mPicture );
835 painter.scale( 16.0 / size.width(), 16.0 / size.width() );
836 svg.render( &painter );
839 else if ( child->algorithm() )
841 mPixmap = child->algorithm()->icon().pixmap( 15, 15 );
844 setLabel( child->description() );
847 mIsValid = model->validateChildAlgorithm( child->childId(), issues );
850void QgsModelChildAlgorithmGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
852 QMenu *popupmenu =
new QMenu( event->widget() );
856 QAction *runSelectedStepsAction = popupmenu->addAction( QObject::tr(
"Run Selected Steps…" ) );
858 connect( runSelectedStepsAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runSelected );
861 QAction *runFromHereAction = popupmenu->addAction( QObject::tr(
"Run from Here…" ) );
863 connect( runFromHereAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runFromHere );
865 popupmenu->addSeparator();
867 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
868 connect( removeAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deleteComponent );
869 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
870 connect( editAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::editComponent );
871 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
872 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
873 popupmenu->addSeparator();
875 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
877 if ( !child->isActive() )
879 QAction *activateAction = popupmenu->addAction( QObject::tr(
"Activate" ) );
880 connect( activateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::activateAlgorithm );
884 QAction *deactivateAction = popupmenu->addAction( QObject::tr(
"Deactivate" ) );
885 connect( deactivateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm );
892 if ( !outputParams.isEmpty() )
894 popupmenu->addSeparator();
895 QAction *viewOutputLayersAction = popupmenu->addAction( QObject::tr(
"View Output Layers" ) );
897 connect( viewOutputLayersAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showPreviousResults );
899 switch ( mResults.executionStatus() )
903 viewOutputLayersAction->setEnabled(
false );
912 QAction *viewLogAction = popupmenu->addAction( QObject::tr(
"View Log…" ) );
913 connect( viewLogAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showLog );
915 switch ( mResults.executionStatus() )
918 viewLogAction->setEnabled(
false );
927 popupmenu->exec( event->screenPos() );
930QColor QgsModelChildAlgorithmGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
935 c = QColor( 255, 255, 255 );
937 c = QColor( 208, 0, 0 );
954QColor QgsModelChildAlgorithmGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
959 return mIsValid ? QColor( 50, 50, 50 ) : QColor( 80, 0, 0 );
962 return mIsValid ? Qt::gray : QColor( 134, 0, 0 );
967QColor QgsModelChildAlgorithmGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
969 return mIsValid ? ( qgis::down_cast<const QgsProcessingModelChildAlgorithm *>( component() )->isActive() ? Qt::black : Qt::gray ) : QColor( 255, 255, 255 );
972QPixmap QgsModelChildAlgorithmGraphicItem::iconPixmap()
const
977QPicture QgsModelChildAlgorithmGraphicItem::iconPicture()
const
982int QgsModelChildAlgorithmGraphicItem::linkPointCount( Qt::Edge edge )
const
984 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
986 if ( !child->algorithm() )
992 return child->algorithm()->outputDefinitions().size();
997 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1000 return params.size();
1011QString QgsModelChildAlgorithmGraphicItem::linkPointText( Qt::Edge edge,
int index )
const
1016 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1018 if ( !child->algorithm() )
1021 const QVariantMap inputs = mResults.inputs();
1022 const QVariantMap outputs = mResults.outputs();
1025 case Qt::BottomEdge:
1027 if ( index >= child->algorithm()->outputDefinitions().length() )
1031 tr(
"Cannot link output for child: %1" ).arg( child->algorithm()->name() ),
1039 if ( outputs.contains( output->
name() ) )
1041 title += QStringLiteral(
": %1" ).arg( outputs.value( output->
name() ).toString() );
1043 return truncatedTextForItem( title );
1050 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1054 if ( index >= params.length() )
1058 tr(
"Cannot link source for child: %1" ).arg( child->algorithm()->name() ),
1064 QString title = params.at( index )->description();
1065 if ( !inputs.value( params.at( index )->name() ).toString().isEmpty() )
1066 title += QStringLiteral(
": %1" ).arg( inputs.value( params.at( index )->name() ).toString() );
1067 return truncatedTextForItem( title );
1078void QgsModelChildAlgorithmGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1080 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast<QgsProcessingModelChildAlgorithm *
>( component() ) )
1082 model()->childAlgorithm( child->childId() ).setPosition( pos );
1083 model()->childAlgorithm( child->childId() ).setSize( size );
1087bool QgsModelChildAlgorithmGraphicItem::canDeleteComponent()
1089 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1091 return model()->dependentChildAlgorithms( child->childId() ).empty();
1098 if ( mResults == results )
1103 emit updateArrowPaths();
1106void QgsModelChildAlgorithmGraphicItem::deleteComponent()
1108 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1110 emit aboutToChange( tr(
"Remove %1" ).arg( child->algorithm() ? child->algorithm()->displayName() : tr(
"Algorithm" ) ) );
1111 if ( !model()->removeChildAlgorithm( child->childId() ) )
1113 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove algorithm" ), QObject::tr(
"Other algorithms depend on the selected one.\n"
1114 "Remove them before trying to remove it." ) );
1119 emit requestModelRepaint();
1124void QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm()
1126 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1128 model()->deactivateChildAlgorithm( child->childId() );
1129 emit requestModelRepaint();
1133void QgsModelChildAlgorithmGraphicItem::activateAlgorithm()
1135 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1137 if ( model()->activateChildAlgorithm( child->childId() ) )
1139 emit requestModelRepaint();
1143 QMessageBox::warning(
nullptr, QObject::tr(
"Could not activate algorithm" ), QObject::tr(
"The selected algorithm depends on other currently non-active algorithms.\n"
1144 "Activate them them before trying to activate it.." ) );
1150QgsModelOutputGraphicItem::QgsModelOutputGraphicItem( QgsProcessingModelOutput *output, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1151 : QgsModelComponentGraphicItem( output, model, parent )
1154 QPainter painter( &mPicture );
1155 svg.render( &painter );
1157 setLabel( output->description() );
1160QColor QgsModelOutputGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1162 QColor
c( 172, 196, 114 );
1166 c =
c.darker( 110 );
1169 c =
c.darker( 105 );
1178QColor QgsModelOutputGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1183 return QColor( 42, 65, 42 );
1186 return QColor( 90, 140, 90 );
1191QColor QgsModelOutputGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1196QPicture QgsModelOutputGraphicItem::iconPicture()
const
1201void QgsModelOutputGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1203 if ( QgsProcessingModelOutput *output =
dynamic_cast<QgsProcessingModelOutput *
>( component() ) )
1205 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setPosition( pos );
1206 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setSize( size );
1210bool QgsModelOutputGraphicItem::canDeleteComponent()
1212 if (
dynamic_cast<const QgsProcessingModelOutput *
>( component() ) )
1219void QgsModelOutputGraphicItem::deleteComponent()
1221 if (
const QgsProcessingModelOutput *output =
dynamic_cast<const QgsProcessingModelOutput *
>( component() ) )
1223 emit aboutToChange( tr(
"Delete Output %1" ).arg( output->description() ) );
1224 model()->childAlgorithm( output->childId() ).removeModelOutput( output->name() );
1225 model()->updateDestinationParameters();
1227 emit requestModelRepaint();
1236QgsModelGroupBoxGraphicItem::QgsModelGroupBoxGraphicItem( QgsProcessingModelGroupBox *box, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1237 : QgsModelComponentGraphicItem( box, model, parent )
1239 setZValue( QgsModelGraphicsScene::ZValues::GroupBox );
1240 setLabel( box->description() );
1244 f.setPixelSize( 14 );
1248void QgsModelGroupBoxGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1250 QMenu *popupmenu =
new QMenu( event->widget() );
1251 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1252 connect( removeAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::deleteComponent );
1253 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1254 connect( editAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::editComponent );
1255 popupmenu->exec( event->screenPos() );
1258QgsModelGroupBoxGraphicItem::~QgsModelGroupBoxGraphicItem() =
default;
1260QColor QgsModelGroupBoxGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1262 QColor
c( 230, 230, 230 );
1266 c =
c.darker( 110 );
1269 c =
c.darker( 105 );
1278QColor QgsModelGroupBoxGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1283 return QColor( 50, 50, 50 );
1286 return QColor( 150, 150, 150 );
1291QColor QgsModelGroupBoxGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1293 return QColor( 100, 100, 100 );
1296Qt::PenStyle QgsModelGroupBoxGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1301Qt::Alignment QgsModelGroupBoxGraphicItem::titleAlignment()
const
1303 return Qt::AlignHCenter;
1306void QgsModelGroupBoxGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1308 if ( QgsProcessingModelGroupBox *box =
dynamic_cast<QgsProcessingModelGroupBox *
>( component() ) )
1310 box->setPosition( pos );
1311 box->setSize( size );
1312 model()->addGroupBox( *box );
1316bool QgsModelGroupBoxGraphicItem::canDeleteComponent()
1318 if (
dynamic_cast<QgsProcessingModelGroupBox *
>( component() ) )
1325void QgsModelGroupBoxGraphicItem::deleteComponent()
1327 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast<const QgsProcessingModelGroupBox *
>( component() ) )
1329 emit aboutToChange( tr(
"Delete Group Box" ) );
1330 model()->removeGroupBox( box->uuid() );
1332 emit requestModelRepaint();
1336void QgsModelGroupBoxGraphicItem::editComponent()
1338 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast<const QgsProcessingModelGroupBox *
>( component() ) )
1344 emit aboutToChange( tr(
"Edit Group Box" ) );
1345 model()->addGroupBox( dlg.groupBox() );
1347 emit requestModelRepaint();
1356QgsModelCommentGraphicItem::QgsModelCommentGraphicItem( QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1357 : QgsModelComponentGraphicItem( comment, model, parent )
1358 , mParentComponent( parentItem->component()->clone() )
1359 , mParentItem( parentItem )
1361 setLabel( comment->description() );
1364 f.setPixelSize( 9 );
1368void QgsModelCommentGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1370 QMenu *popupmenu =
new QMenu( event->widget() );
1371 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1372 connect( removeAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::deleteComponent );
1373 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1374 connect( editAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::editComponent );
1375 popupmenu->exec( event->screenPos() );
1378QgsModelCommentGraphicItem::~QgsModelCommentGraphicItem() =
default;
1380QColor QgsModelCommentGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1382 QColor
c( 230, 230, 230 );
1386 c =
c.darker( 110 );
1389 c =
c.darker( 105 );
1398QColor QgsModelCommentGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1403 return QColor( 50, 50, 50 );
1406 return QColor( 150, 150, 150 );
1411QColor QgsModelCommentGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1413 return QColor( 100, 100, 100 );
1416Qt::PenStyle QgsModelCommentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1421void QgsModelCommentGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1423 if ( QgsProcessingModelComment *comment = modelComponent() )
1425 comment->setPosition( pos );
1426 comment->setSize( size );
1430bool QgsModelCommentGraphicItem::canDeleteComponent()
1432 if ( modelComponent() )
1439void QgsModelCommentGraphicItem::deleteComponent()
1441 if ( QgsProcessingModelComment *comment = modelComponent() )
1443 emit aboutToChange( tr(
"Delete Comment" ) );
1444 comment->setDescription( QString() );
1446 emit requestModelRepaint();
1450void QgsModelCommentGraphicItem::editComponent()
1454 mParentItem->editComment();
1458QgsProcessingModelComment *QgsModelCommentGraphicItem::modelComponent()
1460 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( mParentComponent.get() ) )
1462 return model()->childAlgorithm( child->childId() ).comment();
1464 else if (
const QgsProcessingModelParameter *param =
dynamic_cast<const QgsProcessingModelParameter *
>( mParentComponent.get() ) )
1466 return model()->parameterComponent( param->parameterName() ).comment();
1468 else if (
const QgsProcessingModelOutput *output =
dynamic_cast<const QgsProcessingModelOutput *
>( mParentComponent.get() ) )
1470 return model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).comment();
1475QgsModelComponentGraphicItem *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.