26#include <QGraphicsSceneMouseEvent> 
   31QgsModelGraphicsScene::QgsModelGraphicsScene( QObject *parent )
 
   32  : QGraphicsScene( parent )
 
   34  setItemIndexMethod( QGraphicsScene::NoIndex );
 
   37QgsProcessingModelAlgorithm *QgsModelGraphicsScene::model()
 
   42void QgsModelGraphicsScene::setModel( QgsProcessingModelAlgorithm *model )
 
   47void QgsModelGraphicsScene::setFlag( QgsModelGraphicsScene::Flag flag, 
bool on )
 
   55void QgsModelGraphicsScene::mousePressEvent( QGraphicsSceneMouseEvent *event )
 
   57  if ( event->button() != Qt::LeftButton )
 
   59  QGraphicsScene::mousePressEvent( event );
 
   62QgsModelComponentGraphicItem *QgsModelGraphicsScene::createParameterGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelParameter *param )
 const 
   64  return new QgsModelParameterGraphicItem( param, model, 
nullptr );
 
   67QgsModelChildAlgorithmGraphicItem *QgsModelGraphicsScene::createChildAlgGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelChildAlgorithm *child )
 const 
   69  return new QgsModelChildAlgorithmGraphicItem( child, model, 
nullptr );
 
   72QgsModelComponentGraphicItem *QgsModelGraphicsScene::createOutputGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelOutput *output )
 const 
   74  return new QgsModelOutputGraphicItem( output, model, 
nullptr );
 
   77QgsModelComponentGraphicItem *QgsModelGraphicsScene::createCommentGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem )
 const 
   79  return new QgsModelCommentGraphicItem( comment, parentItem, model, 
nullptr );
 
   82QgsModelComponentGraphicItem *QgsModelGraphicsScene::createGroupBoxGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelGroupBox *box )
 const 
   84  return new QgsModelGroupBoxGraphicItem( box, model, 
nullptr );
 
   87void QgsModelGraphicsScene::createItems( QgsProcessingModelAlgorithm *model, 
QgsProcessingContext &context )
 
   90  const QList<QgsProcessingModelGroupBox> boxes = model->groupBoxes();
 
   91  mGroupBoxItems.clear();
 
   92  for ( 
const QgsProcessingModelGroupBox &box : boxes )
 
   94    QgsModelComponentGraphicItem *item = createGroupBoxGraphicItem( model, box.clone() );
 
   96    item->setPos( box.position().x(), box.position().y() );
 
   97    mGroupBoxItems.insert( box.uuid(), item );
 
   98    connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
   99    connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  100    connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  104  const QMap<QString, QgsProcessingModelParameter> params = model->parameterComponents();
 
  105  for ( 
auto it = params.constBegin(); it != params.constEnd(); ++it )
 
  107    QgsModelComponentGraphicItem *item = createParameterGraphicItem( model, it.value().clone() );
 
  109    item->setPos( it.value().position().x(), it.value().position().y() );
 
  110    mParameterItems.insert( it.value().parameterName(), item );
 
  111    connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  112    connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  113    connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  115    addCommentItemForComponent( model, it.value(), item );
 
  119  for ( 
auto it = params.constBegin(); it != params.constEnd(); ++it )
 
  123    for ( 
const QString &otherName : parameterLinks )
 
  125      if ( mParameterItems.contains( it.key() ) && mParameterItems.contains( otherName ) )
 
  127        std::unique_ptr< QgsModelArrowItem > arrow = std::make_unique< QgsModelArrowItem >( mParameterItems.value( otherName ), QgsModelArrowItem::Marker::Circle, mParameterItems.value( it.key() ), QgsModelArrowItem::Marker::ArrowHead );
 
  128        arrow->setPenStyle( Qt::DotLine );
 
  129        addItem( arrow.release() );
 
  135  const QMap<QString, QgsProcessingModelChildAlgorithm> childAlgs = model->childAlgorithms();
 
  136  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  138    QgsModelChildAlgorithmGraphicItem *item = createChildAlgGraphicItem( model, it.value().clone() );
 
  140    item->setPos( it.value().position().x(), it.value().position().y() );
 
  142    const QString childId = it.value().childId();
 
  143    item->setResults( mLastResult.childResults().value( childId ) );
 
  144    mChildAlgorithmItems.insert( childId, item );
 
  145    connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  146    connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  147    connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  148    connect( item, &QgsModelChildAlgorithmGraphicItem::runFromHere, 
this, [
this, childId]
 
  150      emit runFromChild( childId );
 
  152    connect( item, &QgsModelChildAlgorithmGraphicItem::runSelected, 
this, &QgsModelGraphicsScene::runSelected );
 
  153    connect( item, &QgsModelChildAlgorithmGraphicItem::showPreviousResults, 
this, [
this, childId]
 
  155      emit showChildAlgorithmOutputs( childId );
 
  157    connect( item, &QgsModelChildAlgorithmGraphicItem::showLog, 
this, [
this, childId]
 
  159      emit showChildAlgorithmLog( childId );
 
  162    addCommentItemForComponent( model, it.value(), item );
 
  166  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  170    if ( !it.value().algorithm() )
 
  178        QList< QgsProcessingModelChildParameterSource > sources;
 
  179        if ( it.value().parameterSources().contains( parameter->name() ) )
 
  180          sources = it.value().parameterSources()[parameter->name()];
 
  181        for ( 
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
 
  183          const QList< LinkSource > sourceItems = linkSourcesForParameterValue( model, QVariant::fromValue( source ), it.value().childId(), context );
 
  184          for ( 
const LinkSource &link : sourceItems )
 
  188            QgsModelArrowItem *arrow = 
nullptr;
 
  189            if ( link.linkIndex == -1 )
 
  190              arrow = 
new QgsModelArrowItem( link.item, QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge, parameter->isDestination() ? bottomIdx : topIdx, QgsModelArrowItem::Marker::Circle );
 
  192              arrow = 
new QgsModelArrowItem( link.item, link.edge, link.linkIndex, 
true, QgsModelArrowItem::Marker::Circle,
 
  193                                             mChildAlgorithmItems.value( it.value().childId() ),
 
  194                                             parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge,
 
  195                                             parameter->isDestination() ? bottomIdx : topIdx,
 
  197                                             QgsModelArrowItem::Marker::Circle );
 
  201        if ( parameter->isDestination() )
 
  207    const QList< QgsProcessingModelChildDependency > dependencies = it.value().dependencies();
 
  208    for ( 
const QgsProcessingModelChildDependency &depend : dependencies )
 
  210      if ( depend.conditionalBranch.isEmpty() || !model->childAlgorithm( depend.childId ).algorithm() )
 
  212        addItem( 
new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
 
  222          if ( output->name() == depend.conditionalBranch )
 
  230          addItem( 
new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), Qt::BottomEdge, i, QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
 
  236  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  238    const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
 
  239    QMap< QString, QgsModelComponentGraphicItem * > outputItems;
 
  243    QgsProcessingModelComponent *algItem = mChildAlgorithmItems[it.value().childId()]->component();
 
  244    const double outputOffsetX = algItem->size().width();
 
  245    double outputOffsetY = 1.5 * algItem->size().height();
 
  247    for ( 
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
 
  249      QgsModelComponentGraphicItem *item = createOutputGraphicItem( model, outputIt.value().clone() );
 
  251      connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  252      connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  253      connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  258      QPointF pos = outputIt.value().position();
 
  261        pos = algItem->position() + QPointF( outputOffsetX, outputOffsetY );
 
  262        outputOffsetY += 1.5 * outputIt.value().size().height();
 
  267      if ( it.value().algorithm() )
 
  272          if ( childAlgOutput->name() == outputIt.value().childOutputName() )
 
  282      item->component()->setPosition( pos );
 
  283      outputItems.insert( outputIt.key(), item );
 
  284      addItem( 
new QgsModelArrowItem( mChildAlgorithmItems[it.value().childId()], Qt::BottomEdge, idx, QgsModelArrowItem::Marker::Circle, item, QgsModelArrowItem::Marker::Circle ) );
 
  286      addCommentItemForComponent( model, outputIt.value(), item );
 
  288    mOutputItems.insert( it.value().childId(), outputItems );
 
  292QList<QgsModelComponentGraphicItem *> QgsModelGraphicsScene::selectedComponentItems()
 
  294  QList<QgsModelComponentGraphicItem *> componentItemList;
 
  296  const QList<QGraphicsItem *> graphicsItemList = selectedItems();
 
  297  for ( QGraphicsItem *item : graphicsItemList )
 
  299    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
 
  301      componentItemList.push_back( componentItem );
 
  305  return componentItemList;
 
  308QgsModelComponentGraphicItem *QgsModelGraphicsScene::componentItemAt( QPointF position )
 const 
  311  const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
 
  313  for ( QGraphicsItem *graphicsItem : itemList )
 
  315    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
 
  317      return componentItem;
 
  323QgsModelComponentGraphicItem *QgsModelGraphicsScene::groupBoxItem( 
const QString &uuid )
 
  325  return mGroupBoxItems.value( uuid );
 
  328void QgsModelGraphicsScene::selectAll()
 
  331  QgsModelComponentGraphicItem *focusedItem = 
nullptr;
 
  332  const QList<QGraphicsItem *> itemList = items();
 
  333  for ( QGraphicsItem *graphicsItem : itemList )
 
  335    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
 
  337      componentItem->setSelected( 
true );
 
  339        focusedItem = componentItem;
 
  342  emit selectedItemChanged( focusedItem );
 
  345void QgsModelGraphicsScene::deselectAll()
 
  350  const QList<QGraphicsItem *> selectedItemList = selectedItems();
 
  351  for ( QGraphicsItem *item : selectedItemList )
 
  353    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
 
  355      componentItem->setSelected( 
false );
 
  358  emit selectedItemChanged( 
nullptr );
 
  361void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
 
  366    item->setSelected( 
true );
 
  368  emit selectedItemChanged( item );
 
  373  mLastResult = result;
 
  376  for ( 
auto it = childResults.constBegin(); it != childResults.constEnd(); ++it )
 
  378    if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
 
  380      item->setResults( it.value() );
 
  385QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model, 
const QVariant &value, 
const QString &childId, 
QgsProcessingContext &context )
 const 
  387  QList<QgsModelGraphicsScene::LinkSource> res;
 
  388  if ( value.userType() == QMetaType::Type::QVariantList )
 
  390    const QVariantList list = value.toList();
 
  391    for ( 
const QVariant &v : list )
 
  392      res.append( linkSourcesForParameterValue( model, v, childId, context ) );
 
  394  else if ( value.userType() == QMetaType::Type::QStringList )
 
  396    const QStringList list = value.toStringList();
 
  397    for ( 
const QString &v : list )
 
  398      res.append( linkSourcesForParameterValue( model, v, childId, context ) );
 
  400  else if ( value.userType() == QMetaType::type( 
"QgsProcessingModelChildParameterSource" ) )
 
  402    const QgsProcessingModelChildParameterSource source = value.value< QgsProcessingModelChildParameterSource >();
 
  403    switch ( source.source() )
 
  408        l.item = mParameterItems.value( source.parameterName() );
 
  414        if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
 
  421          if ( output->name() == source.outputName() )
 
  425        if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
 
  428          l.item = mChildAlgorithmItems.value( source.outputChildId() );
 
  429          l.edge = Qt::BottomEdge;
 
  432          if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
 
  434            QString short_message = tr( 
"Check output links for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
 
  435            QString long_message = tr( 
"Cannot link output for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
 
  436            QString title( tr( 
"Algorithm link error" ) );
 
  438              showWarning( 
const_cast<QString &
>( short_message ), 
const_cast<QString &
>( title ), 
const_cast<QString &
>( long_message ) );
 
  453        const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, &context );
 
  455        const QSet<QString> vars = exp.referencedVariables();
 
  456        for ( 
const QString &v : vars )
 
  458          if ( variables.contains( v ) )
 
  460            res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
 
  475void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model, 
const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
 
  477  if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
 
  480  QgsModelComponentGraphicItem *commentItem = createCommentGraphicItem( model, component.comment()->clone(), parentItem );
 
  481  commentItem->setPos( component.comment()->position().x(), component.comment()->position().y() );
 
  482  addItem( commentItem );
 
  483  connect( commentItem, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  484  connect( commentItem, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  485  connect( commentItem, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  487  std::unique_ptr< QgsModelArrowItem > arrow = std::make_unique< QgsModelArrowItem >( parentItem, QgsModelArrowItem::Circle, commentItem, QgsModelArrowItem::Circle );
 
  488  arrow->setPenStyle( Qt::DotLine );
 
  489  addItem( arrow.release() );
 
  497void QgsModelGraphicsScene::setMessageBar( 
QgsMessageBar *messageBar )
 
  499  mMessageBar = messageBar;
 
  502void QgsModelGraphicsScene::showWarning( 
const QString &shortMessage, 
const QString &title, 
const QString &longMessage, 
Qgis::MessageLevel level )
 const 
  505  QPushButton *detailsButton = 
new QPushButton( tr( 
"Details" ) );
 
  506  connect( detailsButton, &QPushButton::clicked, detailsButton, [ = ]
 
  513  messageWidget->layout()->addWidget( detailsButton );
 
  514  mMessageBar->clearWidgets();
 
  515  mMessageBar->pushWidget( messageWidget, level, 0 );
 
MessageLevel
Level for messages This will be used both for message log and message bar in application.
 
@ Warning
Warning message.
 
@ ExpressionText
Parameter value is taken from a text with expressions, evaluated just before the algorithm runs.
 
@ ModelOutput
Parameter value is linked to an output parameter for the model.
 
@ ChildOutput
Parameter value is taken from an output generated by a child algorithm.
 
@ ModelParameter
Parameter value is taken from a parent model parameter.
 
@ StaticValue
Parameter value is a static value.
 
@ Expression
Parameter value is taken from an expression, evaluated just before the algorithm runs.
 
@ Hidden
Parameter is hidden and should not be shown to users.
 
Class for parsing and evaluation of expressions (formerly called "search strings").
 
Represents an item shown within a QgsMessageBar widget.
 
A bar for displaying non-blocking messages to the user.
 
static QgsMessageBarItem * createMessage(const QString &text, QWidget *parent=nullptr)
Creates message bar item widget containing a message text to be displayed on the bar.
 
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 generic message view for displaying QGIS messages.
 
void setTitle(const QString &title) override
Sets title for the messages.
 
void setMessage(const QString &message, MessageType msgType) override
Sets message, it won't be displayed until.
 
void showMessage(bool blocking=true) override
display the message to the user and deletes itself
 
QgsProcessingOutputDefinitions outputDefinitions() const
Returns an ordered list of output definitions utilized by the algorithm.
 
Contains information about the context in which a processing algorithm is executed.
 
Encapsulates the results of running a Processing model.
 
QMap< QString, QgsProcessingModelChildAlgorithmResult > childResults() const
Returns the map of child algorithm results.
 
Base class for the definition of processing outputs.
 
Base class for the definition of processing parameters.
 
virtual QStringList dependsOnOtherParameters() const
Returns a list of other parameter names on which this parameter is dependent (e.g.
 
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
 
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
 
QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions
List of processing parameters.
 
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.