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()
97const QgsProcessingModelAlgorithm *QgsModelComponentGraphicItem::model()
const
102QgsModelGraphicsView *QgsModelComponentGraphicItem::view()
104 if ( scene()->views().isEmpty() )
107 return qobject_cast<QgsModelGraphicsView *>( scene()->views().first() );
110QFont QgsModelComponentGraphicItem::font()
const
115void QgsModelComponentGraphicItem::setFont(
const QFont &font )
121void QgsModelComponentGraphicItem::moveComponentBy( qreal dx, qreal dy )
123 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
124 mComponent->setPosition( pos() );
126 emit aboutToChange( tr(
"Move %1" ).arg( mComponent->description() ) );
127 updateStoredComponentPosition( pos(), mComponent->size() );
130 emit sizePositionChanged();
131 emit updateArrowPaths();
134void QgsModelComponentGraphicItem::previewItemMove( qreal dx, qreal dy )
136 setPos( mComponent->position().x() + dx, mComponent->position().y() + dy );
137 emit updateArrowPaths();
140void QgsModelComponentGraphicItem::setItemRect( QRectF rect )
142 rect = rect.normalized();
144 if ( rect.width() < MIN_COMPONENT_WIDTH )
145 rect.setWidth( MIN_COMPONENT_WIDTH );
146 if ( rect.height() < MIN_COMPONENT_HEIGHT )
147 rect.setHeight( MIN_COMPONENT_HEIGHT );
149 setPos( rect.center() );
150 prepareGeometryChange();
152 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
154 mComponent->setPosition( pos() );
155 mComponent->setSize( rect.size() );
156 updateStoredComponentPosition( pos(), mComponent->size() );
158 updateButtonPositions();
161 emit updateArrowPaths();
162 emit sizePositionChanged();
165QRectF QgsModelComponentGraphicItem::previewItemRectChange( QRectF rect )
167 rect = rect.normalized();
169 if ( rect.width() < MIN_COMPONENT_WIDTH )
170 rect.setWidth( MIN_COMPONENT_WIDTH );
171 if ( rect.height() < MIN_COMPONENT_HEIGHT )
172 rect.setHeight( MIN_COMPONENT_HEIGHT );
174 setPos( rect.center() );
175 prepareGeometryChange();
177 mTempSize = rect.size();
179 updateButtonPositions();
180 emit updateArrowPaths();
185void QgsModelComponentGraphicItem::finalizePreviewedItemRectChange( QRectF )
187 mComponent->setPosition( pos() );
188 prepareGeometryChange();
189 mComponent->setSize( mTempSize );
190 mTempSize = QSizeF();
192 emit aboutToChange( tr(
"Resize %1" ).arg( mComponent->description() ) );
193 updateStoredComponentPosition( pos(), mComponent->size() );
195 updateButtonPositions();
199 emit sizePositionChanged();
200 emit updateArrowPaths();
205 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
206 updateToolTip( mapFromScene( event->
modelPoint() ) );
211 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
212 updateToolTip( mapFromScene( event->
modelPoint() ) );
217 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
219 setToolTip( QString() );
224 emit repaintArrows();
231 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
235void QgsModelComponentGraphicItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * )
237 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
241void QgsModelComponentGraphicItem::hoverEnterEvent( QGraphicsSceneHoverEvent *event )
243 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
244 updateToolTip( event->pos() );
247void QgsModelComponentGraphicItem::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
249 if ( view() && view()->tool() && view()->tool()->allowItemInteraction() )
250 updateToolTip( event->pos() );
253void QgsModelComponentGraphicItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * )
255 modelHoverLeaveEvent(
nullptr );
258QVariant QgsModelComponentGraphicItem::itemChange( QGraphicsItem::GraphicsItemChange change,
const QVariant &value )
262 case QGraphicsItem::ItemSelectedChange:
264 emit repaintArrows();
268 case QGraphicsItem::ItemSceneChange:
273 if ( linkPointCount( Qt::TopEdge ) )
275 mExpandTopButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::TopEdge ), QPointF( 0, 0 ) );
276 connect( mExpandTopButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [=](
bool folded ) { fold( Qt::TopEdge, folded ); } );
278 for (
int idx = 0; idx < linkPointCount( Qt::TopEdge ); ++idx )
280 mInSockets.append(
new QgsModelDesignerSocketGraphicItem(
this, mComponent.get(), idx, QPointF( 0, 0 ), Qt::TopEdge ) );
283 if ( linkPointCount( Qt::BottomEdge ) )
285 mExpandBottomButton =
new QgsModelDesignerFoldButtonGraphicItem(
this, mComponent->linksCollapsed( Qt::BottomEdge ), QPointF( 0, 0 ) );
286 connect( mExpandBottomButton, &QgsModelDesignerFoldButtonGraphicItem::folded,
this, [=](
bool folded ) { fold( Qt::BottomEdge, folded ); } );
288 for (
int idx = 0; idx < linkPointCount( Qt::BottomEdge ); ++idx )
290 mOutSockets.append(
new QgsModelDesignerSocketGraphicItem(
this, mComponent.get(), idx, QPointF( 0, 0 ), Qt::BottomEdge ) );
294 updateButtonPositions();
303 return QGraphicsObject::itemChange( change, value );
306QRectF QgsModelComponentGraphicItem::boundingRect()
const
308 const QFontMetricsF fm( mFont );
309 const int linksAbove = linkPointCount( Qt::TopEdge );
310 const int linksBelow = linkPointCount( Qt::BottomEdge );
312 const double hUp = linksAbove == 0 ? 0 : fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::TopEdge ) ? 0 : linksAbove ) + 2 );
313 const double hDown = linksBelow == 0 ? 0 : fm.height() * 1.2 * ( ( mComponent->linksCollapsed( Qt::BottomEdge ) ? 0 : linksBelow ) + 2 );
314 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 );
317bool QgsModelComponentGraphicItem::contains(
const QPointF &point )
const
319 const QRectF paintingBounds = boundingRect();
320 if ( point.x() < paintingBounds.left() + RECT_PEN_SIZE )
322 if ( point.x() > paintingBounds.right() - RECT_PEN_SIZE )
324 if ( point.y() < paintingBounds.top() + RECT_PEN_SIZE )
326 if ( point.y() > paintingBounds.bottom() - RECT_PEN_SIZE )
332void QgsModelComponentGraphicItem::paint( QPainter *painter,
const QStyleOptionGraphicsItem *, QWidget * )
334 const QRectF rect = itemRect();
338 if ( mComponent->color().isValid() )
340 color = mComponent->color();
344 color = color.darker( 110 );
347 color = color.darker( 105 );
353 stroke = color.darker( 110 );
354 foreColor = color.lightness() > 150 ? QColor( 0, 0, 0 ) : QColor( 255, 255, 255 );
358 color = fillColor( state() );
359 stroke = strokeColor( state() );
360 foreColor = textColor( state() );
363 QPen strokePen = QPen( stroke, 0 );
364 strokePen.setStyle( strokeStyle( state() ) );
365 painter->setPen( strokePen );
366 painter->setBrush( QBrush( color, Qt::SolidPattern ) );
367 painter->drawRect( rect );
368 painter->setFont( font() );
369 painter->setPen( QPen( foreColor ) );
373 const QSizeF componentSize = itemSize();
375 const QFontMetricsF fm( font() );
376 double h = fm.ascent();
377 QPointF pt( -componentSize.width() / 2 + 25, componentSize.height() / 2.0 - h + 1 );
379 if ( iconPicture().isNull() && iconPixmap().isNull() )
381 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 );
383 painter->drawText( labelRect, Qt::TextWordWrap | titleAlignment(), text );
387 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 );
389 painter->drawText( labelRect, Qt::TextWordWrap | Qt::AlignVCenter, text );
392 painter->setPen( QPen( QApplication::palette().color( QPalette::Text ) ) );
394 if ( linkPointCount( Qt::TopEdge ) )
396 h = -( fm.height() * 1.2 );
397 h = h - componentSize.height() / 2.0 + 5;
398 pt = QPointF( -componentSize.width() / 2 + 25, h );
399 painter->drawText( pt, QObject::tr(
"In" ) );
401 if ( !mComponent->linksCollapsed( Qt::TopEdge ) )
403 for (
int idx = 0; idx < linkPointCount( Qt::TopEdge ); ++idx )
405 text = linkPointText( Qt::TopEdge, idx );
406 h = -( fm.height() * 1.2 ) * ( i + 1 );
407 h = h - componentSize.height() / 2.0 + 5;
408 pt = QPointF( -componentSize.width() / 2 + 33, h );
409 painter->drawText( pt, text );
414 if ( linkPointCount( Qt::BottomEdge ) )
416 h = fm.height() * 1.1;
417 h = h + componentSize.height() / 2.0;
418 pt = QPointF( -componentSize.width() / 2 + 25, h );
419 painter->drawText( pt, QObject::tr(
"Out" ) );
420 if ( !mComponent->linksCollapsed( Qt::BottomEdge ) )
422 for (
int idx = 0; idx < linkPointCount( Qt::BottomEdge ); ++idx )
424 text = linkPointText( Qt::BottomEdge, idx );
425 h = fm.height() * 1.2 * ( idx + 2 );
426 h = h + componentSize.height() / 2.0;
427 pt = QPointF( -componentSize.width() / 2 + 33, h );
428 painter->drawText( pt, text );
433 const QPixmap px = iconPixmap();
436 painter->drawPixmap( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), px );
440 const QPicture pic = iconPicture();
443 painter->drawPicture( QPointF( -( componentSize.width() / 2.0 ) + 3, -8 ), pic );
448QRectF QgsModelComponentGraphicItem::itemRect(
bool storedRect )
const
452 return QRectF( mComponent->position().x() - ( mComponent->size().width() ) / 2.0, mComponent->position().y() - ( mComponent->size().height() ) / 2.0, mComponent->size().width(), mComponent->size().height() );
455 return QRectF( -( itemSize().width() ) / 2.0, -( itemSize().height() ) / 2.0, itemSize().width(), itemSize().height() );
458QString QgsModelComponentGraphicItem::truncatedTextForItem(
const QString &text )
const
460 const QFontMetricsF fm( mFont );
461 double width = fm.boundingRect( text ).width();
462 if ( width < itemSize().width() - 25 - mButtonSize.width() )
466 t = t.left( t.length() - 3 ) + QChar( 0x2026 );
467 width = fm.boundingRect( t ).width();
468 while ( width > itemSize().width() - 25 - mButtonSize.width() )
470 if ( t.length() < 5 )
473 t = t.left( t.length() - 4 ) + QChar( 0x2026 );
474 width = fm.boundingRect( t ).width();
479Qt::PenStyle QgsModelComponentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
481 return Qt::SolidLine;
484Qt::Alignment QgsModelComponentGraphicItem::titleAlignment()
const
486 return Qt::AlignLeft;
489QPicture QgsModelComponentGraphicItem::iconPicture()
const
494QPixmap QgsModelComponentGraphicItem::iconPixmap()
const
499void QgsModelComponentGraphicItem::updateButtonPositions()
501 mEditButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN, itemSize().height() / 2.0 - mButtonSize.height() / 2.0 - BUTTON_MARGIN ) );
502 mDeleteButton->setPosition( QPointF( itemSize().width() / 2.0 - mButtonSize.width() / 2.0 - BUTTON_MARGIN, mButtonSize.height() / 2.0 - itemSize().height() / 2.0 + BUTTON_MARGIN ) );
504 if ( mExpandTopButton )
506 const QPointF pt = linkPoint( Qt::TopEdge, -1,
true );
507 mExpandTopButton->setPosition( QPointF( 0, pt.y() ) );
509 if ( mExpandBottomButton )
511 const QPointF pt = linkPoint( Qt::BottomEdge, -1,
false );
512 mExpandBottomButton->setPosition( QPointF( 0, pt.y() ) );
516 bool collapsed = mComponent->linksCollapsed( Qt::TopEdge );
517 for ( QgsModelDesignerSocketGraphicItem *socket : std::as_const( mInSockets ) )
519 const QPointF pt = linkPoint( Qt::TopEdge, socket->index(),
true );
520 socket->setPosition( pt );
521 socket->setVisible( !collapsed );
524 collapsed = mComponent->linksCollapsed( Qt::BottomEdge );
525 for ( QgsModelDesignerSocketGraphicItem *socket : std::as_const( mOutSockets ) )
527 const QPointF pt = linkPoint( Qt::BottomEdge, socket->index(),
false );
528 socket->setPosition( pt );
529 socket->setVisible( !collapsed );
533QSizeF QgsModelComponentGraphicItem::itemSize()
const
535 return !mTempSize.isValid() ? mComponent->size() : mTempSize;
538void QgsModelComponentGraphicItem::updateToolTip(
const QPointF &pos )
540 const bool prevHoverStatus = mIsHovering;
541 if ( itemRect().contains( pos ) )
543 setToolTip( mLabel );
548 setToolTip( QString() );
551 if ( mIsHovering != prevHoverStatus )
554 emit repaintArrows();
558void QgsModelComponentGraphicItem::fold( Qt::Edge edge,
bool folded )
560 emit aboutToChange( !folded ? tr(
"Expand Item" ) : tr(
"Collapse Item" ) );
561 mComponent->setLinksCollapsed( edge, folded );
565 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast<QgsProcessingModelChildAlgorithm *
>( mComponent.get() ) )
566 mModel->childAlgorithm( child->childId() ).setLinksCollapsed( edge, folded );
567 else if ( QgsProcessingModelParameter *param =
dynamic_cast<QgsProcessingModelParameter *
>( mComponent.get() ) )
568 mModel->parameterComponent( param->parameterName() ).setLinksCollapsed( edge, folded );
569 else if ( QgsProcessingModelOutput *output =
dynamic_cast<QgsProcessingModelOutput *
>( mComponent.get() ) )
570 mModel->childAlgorithm( output->childId() ).modelOutput( output->name() ).setLinksCollapsed( edge, folded );
573 updateButtonPositions();
575 prepareGeometryChange();
576 emit updateArrowPaths();
581QString QgsModelComponentGraphicItem::label()
const
586void QgsModelComponentGraphicItem::setLabel(
const QString &label )
592QgsModelComponentGraphicItem::State QgsModelComponentGraphicItem::state()
const
596 else if ( mIsHovering )
602int QgsModelComponentGraphicItem::linkPointCount( Qt::Edge )
const
607QString QgsModelComponentGraphicItem::linkPointText( Qt::Edge,
int )
const
612QPointF QgsModelComponentGraphicItem::linkPoint( Qt::Edge edge,
int index,
bool incoming )
const
618 if ( linkPointCount( Qt::BottomEdge ) )
621 if ( mComponent->linksCollapsed( Qt::BottomEdge ) )
625 const int pointIndex = !mComponent->linksCollapsed( Qt::BottomEdge ) ? index : -1;
626 const QString text = truncatedTextForItem( linkPointText( Qt::BottomEdge, index ) );
627 const QFontMetricsF fm( mFont );
628 const double w = fm.boundingRect( text ).width();
629 const double h = fm.height() * 1.2 * ( pointIndex + 1 ) + fm.height() / 2.0;
630 const double y = h + itemSize().height() / 2.0 + 5;
631 const double x = !mComponent->linksCollapsed( Qt::BottomEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10;
632 return QPointF( incoming ? -itemSize().width() / 2 + offsetX : x, y );
639 if ( linkPointCount( Qt::TopEdge ) )
642 int paramIndex = index;
643 if ( mComponent->linksCollapsed( Qt::TopEdge ) )
648 const QFontMetricsF fm( mFont );
649 const QString text = truncatedTextForItem( linkPointText( Qt::TopEdge, index ) );
650 const double w = fm.boundingRect( text ).width();
651 double h = -( fm.height() * 1.2 ) * ( paramIndex + 2 ) - fm.height() / 2.0 + 8;
652 h = h - itemSize().height() / 2.0;
653 return QPointF( incoming ? -itemSize().width() / 2 + offsetX : ( !mComponent->linksCollapsed( Qt::TopEdge ) ? ( -itemSize().width() / 2 + 33 + w + 5 ) : 10 ), h );
665QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint( QgsModelComponentGraphicItem *other, Qt::Edge &edge )
const
668 const QgsRectangle otherRect( other->itemRect().translated( other->pos() ) );
670 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
671 const double distLeft = otherRect.distance(
QgsPointXY( leftPoint ) );
673 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
674 const double distRight = otherRect.distance(
QgsPointXY( rightPoint ) );
676 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
677 const double distTop = otherRect.distance(
QgsPointXY( topPoint ) );
679 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
680 const double distBottom = otherRect.distance(
QgsPointXY( bottomPoint ) );
682 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
687 else if ( distRight <= distTop && distRight <= distBottom )
689 edge = Qt::RightEdge;
692 else if ( distBottom <= distTop )
694 edge = Qt::BottomEdge;
704QPointF QgsModelComponentGraphicItem::calculateAutomaticLinkPoint(
const QPointF &point, Qt::Edge &edge )
const
708 const QPointF leftPoint = pos() + QPointF( -itemSize().width() / 2.0, 0 );
709 const double distLeft = otherPt.distance(
QgsPointXY( leftPoint ) );
711 const QPointF rightPoint = pos() + QPointF( itemSize().width() / 2.0, 0 );
712 const double distRight = otherPt.distance(
QgsPointXY( rightPoint ) );
714 const QPointF topPoint = pos() + QPointF( 0, -itemSize().height() / 2.0 );
715 const double distTop = otherPt.distance(
QgsPointXY( topPoint ) );
717 const QPointF bottomPoint = pos() + QPointF( 0, itemSize().height() / 2.0 );
718 const double distBottom = otherPt.distance(
QgsPointXY( bottomPoint ) );
720 if ( distLeft <= distRight && distLeft <= distTop && distLeft <= distBottom )
725 else if ( distRight <= distTop && distRight <= distBottom )
727 edge = Qt::RightEdge;
730 else if ( distBottom <= distTop )
732 edge = Qt::BottomEdge;
742QgsModelDesignerSocketGraphicItem *QgsModelComponentGraphicItem::outSocketAt(
int index )
const
744 if ( index < 0 || index >= mOutSockets.size() )
748 return mOutSockets.at( index );
751QgsModelParameterGraphicItem::QgsModelParameterGraphicItem( QgsProcessingModelParameter *parameter, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
752 : QgsModelComponentGraphicItem( parameter, model, parent )
755 QPainter painter( &mPicture );
756 svg.render( &painter );
760 setLabel( paramDef->description() );
762 setLabel( QObject::tr(
"Error (%1)" ).arg( parameter->parameterName() ) );
765void QgsModelParameterGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
767 QMenu *popupmenu =
new QMenu( event->widget() );
768 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
769 connect( removeAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::deleteComponent );
770 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
771 connect( editAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComponent );
772 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
773 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
775 popupmenu->exec( event->screenPos() );
778QColor QgsModelParameterGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
780 QColor
c( 238, 242, 131 );
796QColor QgsModelParameterGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
801 return QColor( 116, 113, 68 );
804 return QColor( 234, 226, 118 );
809QColor QgsModelParameterGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
814QPicture QgsModelParameterGraphicItem::iconPicture()
const
819int QgsModelParameterGraphicItem::linkPointCount( Qt::Edge edge )
const
834QString QgsModelParameterGraphicItem::linkPointText( Qt::Edge,
int index )
const
842 if (
const QgsProcessingModelParameter *parameter =
dynamic_cast< const QgsProcessingModelParameter *
>( component() ) )
844 QString text = this->model()->parameterDefinition( parameter->parameterName() )->type();
845 return truncatedTextForItem( text );
852void QgsModelParameterGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
854 if ( QgsProcessingModelParameter *param =
dynamic_cast<QgsProcessingModelParameter *
>( component() ) )
856 model()->parameterComponent( param->parameterName() ).setPosition( pos );
857 model()->parameterComponent( param->parameterName() ).setSize( size );
861bool QgsModelParameterGraphicItem::canDeleteComponent()
863 if (
const QgsProcessingModelParameter *param =
dynamic_cast<const QgsProcessingModelParameter *
>( component() ) )
865 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
869 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
881void QgsModelParameterGraphicItem::deleteComponent()
883 if (
const QgsProcessingModelParameter *param =
dynamic_cast<const QgsProcessingModelParameter *
>( component() ) )
885 if ( model()->childAlgorithmsDependOnParameter( param->parameterName() ) )
887 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ), QObject::tr(
"Algorithms depend on the selected input.\n"
888 "Remove them before trying to remove it." ) );
890 else if ( model()->otherParametersDependOnParameter( param->parameterName() ) )
892 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove input" ), QObject::tr(
"Other inputs depend on the selected input.\n"
893 "Remove them before trying to remove it." ) );
897 emit aboutToChange( tr(
"Delete Input %1" ).arg( param->description() ) );
898 model()->removeModelParameter( param->parameterName() );
900 emit requestModelRepaint();
906QgsModelChildAlgorithmGraphicItem::QgsModelChildAlgorithmGraphicItem( QgsProcessingModelChildAlgorithm *child, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
907 : QgsModelComponentGraphicItem( child, model, parent )
909 if ( child->algorithm() && !child->algorithm()->svgIconPath().isEmpty() )
911 QSvgRenderer svg( child->algorithm()->svgIconPath() );
912 const QSizeF size = svg.defaultSize();
913 QPainter painter( &mPicture );
914 painter.scale( 16.0 / size.width(), 16.0 / size.width() );
915 svg.render( &painter );
918 else if ( child->algorithm() )
920 mPixmap = child->algorithm()->icon().pixmap( 15, 15 );
923 setLabel( child->description() );
926 mIsValid = model->validateChildAlgorithm( child->childId(), issues );
929void QgsModelChildAlgorithmGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
931 QMenu *popupmenu =
new QMenu( event->widget() );
935 QAction *runSelectedStepsAction = popupmenu->addAction( QObject::tr(
"Run Selected Steps…" ) );
937 connect( runSelectedStepsAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runSelected );
940 QAction *runFromHereAction = popupmenu->addAction( QObject::tr(
"Run from Here…" ) );
942 connect( runFromHereAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::runFromHere );
944 popupmenu->addSeparator();
946 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
947 connect( removeAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deleteComponent );
948 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
949 connect( editAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::editComponent );
950 QAction *editCommentAction = popupmenu->addAction( component()->comment()->description().isEmpty() ? QObject::tr(
"Add Comment…" ) : QObject::tr(
"Edit Comment…" ) );
951 connect( editCommentAction, &QAction::triggered,
this, &QgsModelParameterGraphicItem::editComment );
952 popupmenu->addSeparator();
954 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
956 if ( !child->isActive() )
958 QAction *activateAction = popupmenu->addAction( QObject::tr(
"Activate" ) );
959 connect( activateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::activateAlgorithm );
963 QAction *deactivateAction = popupmenu->addAction( QObject::tr(
"Deactivate" ) );
964 connect( deactivateAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm );
971 if ( !outputParams.isEmpty() )
973 popupmenu->addSeparator();
974 QAction *viewOutputLayersAction = popupmenu->addAction( QObject::tr(
"View Output Layers" ) );
976 connect( viewOutputLayersAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showPreviousResults );
978 switch ( mResults.executionStatus() )
982 viewOutputLayersAction->setEnabled(
false );
991 QAction *viewLogAction = popupmenu->addAction( QObject::tr(
"View Log…" ) );
992 connect( viewLogAction, &QAction::triggered,
this, &QgsModelChildAlgorithmGraphicItem::showLog );
994 switch ( mResults.executionStatus() )
997 viewLogAction->setEnabled(
false );
1006 popupmenu->exec( event->screenPos() );
1009QColor QgsModelChildAlgorithmGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1014 c = QColor( 255, 255, 255 );
1016 c = QColor( 208, 0, 0 );
1021 c =
c.darker( 110 );
1024 c =
c.darker( 105 );
1033QColor QgsModelChildAlgorithmGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1038 return mIsValid ? QColor( 50, 50, 50 ) : QColor( 80, 0, 0 );
1041 return mIsValid ? Qt::gray : QColor( 134, 0, 0 );
1046QColor QgsModelChildAlgorithmGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1048 return mIsValid ? ( qgis::down_cast<const QgsProcessingModelChildAlgorithm *>( component() )->isActive() ? Qt::black : Qt::gray ) : QColor( 255, 255, 255 );
1051QPixmap QgsModelChildAlgorithmGraphicItem::iconPixmap()
const
1056QPicture QgsModelChildAlgorithmGraphicItem::iconPicture()
const
1061int QgsModelChildAlgorithmGraphicItem::linkPointCount( Qt::Edge edge )
const
1063 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1065 if ( !child->algorithm() )
1070 case Qt::BottomEdge:
1071 return child->algorithm()->outputDefinitions().size();
1076 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1079 return params.size();
1090QString QgsModelChildAlgorithmGraphicItem::linkPointText( Qt::Edge edge,
int index )
const
1095 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1097 if ( !child->algorithm() )
1100 const QVariantMap inputs = mResults.inputs();
1101 const QVariantMap outputs = mResults.outputs();
1104 case Qt::BottomEdge:
1106 if ( index >= child->algorithm()->outputDefinitions().length() )
1110 tr(
"Cannot link output for child: %1" ).arg( child->algorithm()->name() ),
1118 if ( outputs.contains( output->
name() ) )
1120 title += QStringLiteral(
": %1" ).arg( outputs.value( output->
name() ).toString() );
1122 return truncatedTextForItem( title );
1129 return param->flags() & Qgis::ProcessingParameterFlag::Hidden || param->isDestination();
1133 if ( index >= params.length() )
1137 tr(
"Cannot link source for child: %1" ).arg( child->algorithm()->name() ),
1143 QString title = params.at( index )->description();
1144 if ( !inputs.value( params.at( index )->name() ).toString().isEmpty() )
1145 title += QStringLiteral(
": %1" ).arg( inputs.value( params.at( index )->name() ).toString() );
1146 return truncatedTextForItem( title );
1157void QgsModelChildAlgorithmGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1159 if ( QgsProcessingModelChildAlgorithm *child =
dynamic_cast<QgsProcessingModelChildAlgorithm *
>( component() ) )
1161 model()->childAlgorithm( child->childId() ).setPosition( pos );
1162 model()->childAlgorithm( child->childId() ).setSize( size );
1166bool QgsModelChildAlgorithmGraphicItem::canDeleteComponent()
1168 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1170 return model()->dependentChildAlgorithms( child->childId() ).empty();
1177 if ( mResults == results )
1182 emit updateArrowPaths();
1185void QgsModelChildAlgorithmGraphicItem::deleteComponent()
1187 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1189 emit aboutToChange( tr(
"Remove %1" ).arg( child->algorithm() ? child->algorithm()->displayName() : tr(
"Algorithm" ) ) );
1190 if ( !model()->removeChildAlgorithm( child->childId() ) )
1192 QMessageBox::warning(
nullptr, QObject::tr(
"Could not remove algorithm" ), QObject::tr(
"Other algorithms depend on the selected one.\n"
1193 "Remove them before trying to remove it." ) );
1198 emit requestModelRepaint();
1203void QgsModelChildAlgorithmGraphicItem::deactivateAlgorithm()
1205 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1207 model()->deactivateChildAlgorithm( child->childId() );
1208 emit requestModelRepaint();
1212void QgsModelChildAlgorithmGraphicItem::activateAlgorithm()
1214 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( component() ) )
1216 if ( model()->activateChildAlgorithm( child->childId() ) )
1218 emit requestModelRepaint();
1222 QMessageBox::warning(
nullptr, QObject::tr(
"Could not activate algorithm" ), QObject::tr(
"The selected algorithm depends on other currently non-active algorithms.\n"
1223 "Activate them them before trying to activate it.." ) );
1229QgsModelOutputGraphicItem::QgsModelOutputGraphicItem( QgsProcessingModelOutput *output, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1230 : QgsModelComponentGraphicItem( output, model, parent )
1233 QPainter painter( &mPicture );
1234 svg.render( &painter );
1236 setLabel( output->description() );
1239QColor QgsModelOutputGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1241 QColor
c( 172, 196, 114 );
1245 c =
c.darker( 110 );
1248 c =
c.darker( 105 );
1257QColor QgsModelOutputGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1262 return QColor( 42, 65, 42 );
1265 return QColor( 90, 140, 90 );
1270QColor QgsModelOutputGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1275QPicture QgsModelOutputGraphicItem::iconPicture()
const
1280void QgsModelOutputGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1282 if ( QgsProcessingModelOutput *output =
dynamic_cast<QgsProcessingModelOutput *
>( component() ) )
1284 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setPosition( pos );
1285 model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).setSize( size );
1289bool QgsModelOutputGraphicItem::canDeleteComponent()
1291 if (
dynamic_cast<const QgsProcessingModelOutput *
>( component() ) )
1298void QgsModelOutputGraphicItem::deleteComponent()
1300 if (
const QgsProcessingModelOutput *output =
dynamic_cast<const QgsProcessingModelOutput *
>( component() ) )
1302 emit aboutToChange( tr(
"Delete Output %1" ).arg( output->description() ) );
1303 model()->childAlgorithm( output->childId() ).removeModelOutput( output->name() );
1304 model()->updateDestinationParameters();
1306 emit requestModelRepaint();
1315QgsModelGroupBoxGraphicItem::QgsModelGroupBoxGraphicItem( QgsProcessingModelGroupBox *box, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1316 : QgsModelComponentGraphicItem( box, model, parent )
1318 setZValue( QgsModelGraphicsScene::ZValues::GroupBox );
1319 setLabel( box->description() );
1323 f.setPixelSize( 14 );
1327void QgsModelGroupBoxGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1329 QMenu *popupmenu =
new QMenu( event->widget() );
1330 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1331 connect( removeAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::deleteComponent );
1332 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1333 connect( editAction, &QAction::triggered,
this, &QgsModelGroupBoxGraphicItem::editComponent );
1334 popupmenu->exec( event->screenPos() );
1337QgsModelGroupBoxGraphicItem::~QgsModelGroupBoxGraphicItem() =
default;
1339QColor QgsModelGroupBoxGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1341 QColor
c( 230, 230, 230 );
1345 c =
c.darker( 110 );
1348 c =
c.darker( 105 );
1357QColor QgsModelGroupBoxGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1362 return QColor( 50, 50, 50 );
1365 return QColor( 150, 150, 150 );
1370QColor QgsModelGroupBoxGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1372 return QColor( 100, 100, 100 );
1375Qt::PenStyle QgsModelGroupBoxGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1380Qt::Alignment QgsModelGroupBoxGraphicItem::titleAlignment()
const
1382 return Qt::AlignHCenter;
1385void QgsModelGroupBoxGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1387 if ( QgsProcessingModelGroupBox *box =
dynamic_cast<QgsProcessingModelGroupBox *
>( component() ) )
1389 box->setPosition( pos );
1390 box->setSize( size );
1391 model()->addGroupBox( *box );
1395bool QgsModelGroupBoxGraphicItem::canDeleteComponent()
1397 if (
dynamic_cast<QgsProcessingModelGroupBox *
>( component() ) )
1404void QgsModelGroupBoxGraphicItem::deleteComponent()
1406 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast<const QgsProcessingModelGroupBox *
>( component() ) )
1408 emit aboutToChange( tr(
"Delete Group Box" ) );
1409 model()->removeGroupBox( box->uuid() );
1411 emit requestModelRepaint();
1415void QgsModelGroupBoxGraphicItem::editComponent()
1417 if (
const QgsProcessingModelGroupBox *box =
dynamic_cast<const QgsProcessingModelGroupBox *
>( component() ) )
1423 emit aboutToChange( tr(
"Edit Group Box" ) );
1424 model()->addGroupBox( dlg.groupBox() );
1426 emit requestModelRepaint();
1435QgsModelCommentGraphicItem::QgsModelCommentGraphicItem( QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem, QgsProcessingModelAlgorithm *model, QGraphicsItem *parent )
1436 : QgsModelComponentGraphicItem( comment, model, parent )
1437 , mParentComponent( parentItem->component()->clone() )
1438 , mParentItem( parentItem )
1440 setLabel( comment->description() );
1443 f.setPixelSize( 9 );
1447void QgsModelCommentGraphicItem::contextMenuEvent( QGraphicsSceneContextMenuEvent *event )
1449 QMenu *popupmenu =
new QMenu( event->widget() );
1450 QAction *removeAction = popupmenu->addAction( QObject::tr(
"Remove" ) );
1451 connect( removeAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::deleteComponent );
1452 QAction *editAction = popupmenu->addAction( QObject::tr(
"Edit…" ) );
1453 connect( editAction, &QAction::triggered,
this, &QgsModelCommentGraphicItem::editComponent );
1454 popupmenu->exec( event->screenPos() );
1457QgsModelCommentGraphicItem::~QgsModelCommentGraphicItem() =
default;
1459QColor QgsModelCommentGraphicItem::fillColor( QgsModelComponentGraphicItem::State state )
const
1461 QColor
c( 230, 230, 230 );
1465 c =
c.darker( 110 );
1468 c =
c.darker( 105 );
1477QColor QgsModelCommentGraphicItem::strokeColor( QgsModelComponentGraphicItem::State state )
const
1482 return QColor( 50, 50, 50 );
1485 return QColor( 150, 150, 150 );
1490QColor QgsModelCommentGraphicItem::textColor( QgsModelComponentGraphicItem::State )
const
1492 return QColor( 100, 100, 100 );
1495Qt::PenStyle QgsModelCommentGraphicItem::strokeStyle( QgsModelComponentGraphicItem::State )
const
1500void QgsModelCommentGraphicItem::updateStoredComponentPosition(
const QPointF &pos,
const QSizeF &size )
1502 if ( QgsProcessingModelComment *comment = modelComponent() )
1504 comment->setPosition( pos );
1505 comment->setSize( size );
1509bool QgsModelCommentGraphicItem::canDeleteComponent()
1511 if ( modelComponent() )
1518void QgsModelCommentGraphicItem::deleteComponent()
1520 if ( QgsProcessingModelComment *comment = modelComponent() )
1522 emit aboutToChange( tr(
"Delete Comment" ) );
1523 comment->setDescription( QString() );
1525 emit requestModelRepaint();
1529void QgsModelCommentGraphicItem::editComponent()
1533 mParentItem->editComment();
1537QgsProcessingModelComment *QgsModelCommentGraphicItem::modelComponent()
1539 if (
const QgsProcessingModelChildAlgorithm *child =
dynamic_cast<const QgsProcessingModelChildAlgorithm *
>( mParentComponent.get() ) )
1541 return model()->childAlgorithm( child->childId() ).comment();
1543 else if (
const QgsProcessingModelParameter *param =
dynamic_cast<const QgsProcessingModelParameter *
>( mParentComponent.get() ) )
1545 return model()->parameterComponent( param->parameterName() ).comment();
1547 else if (
const QgsProcessingModelOutput *output =
dynamic_cast<const QgsProcessingModelOutput *
>( mParentComponent.get() ) )
1549 return model()->childAlgorithm( output->childId() ).modelOutput( output->name() ).comment();
1554QgsModelComponentGraphicItem *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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
A widget which allows users to specify the properties of a model group box.
A mouse event which is the result of a user interaction with a QgsModelGraphicsView.
QPointF modelPoint() const
Returns the event point location in model coordinates.
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.