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