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() );
 
  141    item->setResults( mChildResults.value( it.value().childId() ).toMap() );
 
  142    item->setInputs( mChildInputs.value( it.value().childId() ).toMap() );
 
  143    mChildAlgorithmItems.insert( it.value().childId(), item );
 
  144    connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  145    connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  146    connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  148    addCommentItemForComponent( model, it.value(), item );
 
  152  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  156    if ( !it.value().algorithm() )
 
  164        QList< QgsProcessingModelChildParameterSource > sources;
 
  165        if ( it.value().parameterSources().contains( parameter->name() ) )
 
  166          sources = it.value().parameterSources()[parameter->name()];
 
  167        for ( 
const QgsProcessingModelChildParameterSource &source : sources )
 
  169          const QList< LinkSource > sourceItems = linkSourcesForParameterValue( model, QVariant::fromValue( source ), it.value().childId(), context );
 
  170          for ( 
const LinkSource &link : sourceItems )
 
  174            QgsModelArrowItem *arrow = 
nullptr;
 
  175            if ( link.linkIndex == -1 )
 
  176              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 );
 
  178              arrow = 
new QgsModelArrowItem( link.item, link.edge, link.linkIndex, 
true, QgsModelArrowItem::Marker::Circle,
 
  179                                             mChildAlgorithmItems.value( it.value().childId() ),
 
  180                                             parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge,
 
  181                                             parameter->isDestination() ? bottomIdx : topIdx,
 
  183                                             QgsModelArrowItem::Marker::Circle );
 
  187        if ( parameter->isDestination() )
 
  193    const QList< QgsProcessingModelChildDependency > dependencies = it.value().dependencies();
 
  194    for ( 
const QgsProcessingModelChildDependency &depend : dependencies )
 
  196      if ( depend.conditionalBranch.isEmpty() || !model->childAlgorithm( depend.childId ).algorithm() )
 
  198        addItem( 
new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
 
  208          if ( output->name() == depend.conditionalBranch )
 
  216          addItem( 
new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), Qt::BottomEdge, i, QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
 
  222  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  224    const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
 
  225    QMap< QString, QgsModelComponentGraphicItem * > outputItems;
 
  229    QgsProcessingModelComponent *algItem = mChildAlgorithmItems[it.value().childId()]->component();
 
  230    const double outputOffsetX = algItem->size().width();
 
  231    double outputOffsetY = 1.5 * algItem->size().height();
 
  233    for ( 
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
 
  235      QgsModelComponentGraphicItem *item = createOutputGraphicItem( model, outputIt.value().clone() );
 
  237      connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  238      connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  239      connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  244      QPointF pos = outputIt.value().position();
 
  247        pos = algItem->position() + QPointF( outputOffsetX, outputOffsetY );
 
  248        outputOffsetY += 1.5 * outputIt.value().size().height();
 
  253      if ( it.value().algorithm() )
 
  258          if ( childAlgOutput->name() == outputIt.value().childOutputName() )
 
  268      item->component()->setPosition( pos );
 
  269      outputItems.insert( outputIt.key(), item );
 
  270      addItem( 
new QgsModelArrowItem( mChildAlgorithmItems[it.value().childId()], Qt::BottomEdge, idx, QgsModelArrowItem::Marker::Circle, item, QgsModelArrowItem::Marker::Circle ) );
 
  272      addCommentItemForComponent( model, outputIt.value(), item );
 
  274    mOutputItems.insert( it.value().childId(), outputItems );
 
  278QList<QgsModelComponentGraphicItem *> QgsModelGraphicsScene::selectedComponentItems()
 
  280  QList<QgsModelComponentGraphicItem *> componentItemList;
 
  282  const QList<QGraphicsItem *> graphicsItemList = selectedItems();
 
  283  for ( QGraphicsItem *item : graphicsItemList )
 
  285    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
 
  287      componentItemList.push_back( componentItem );
 
  291  return componentItemList;
 
  294QgsModelComponentGraphicItem *QgsModelGraphicsScene::componentItemAt( QPointF position )
 const 
  297  const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
 
  299  for ( QGraphicsItem *graphicsItem : itemList )
 
  301    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
 
  303      return componentItem;
 
  309QgsModelComponentGraphicItem *QgsModelGraphicsScene::groupBoxItem( 
const QString &uuid )
 
  311  return mGroupBoxItems.value( uuid );
 
  314void QgsModelGraphicsScene::selectAll()
 
  317  QgsModelComponentGraphicItem *focusedItem = 
nullptr;
 
  318  const QList<QGraphicsItem *> itemList = items();
 
  319  for ( QGraphicsItem *graphicsItem : itemList )
 
  321    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
 
  323      componentItem->setSelected( 
true );
 
  325        focusedItem = componentItem;
 
  328  emit selectedItemChanged( focusedItem );
 
  331void QgsModelGraphicsScene::deselectAll()
 
  336  const QList<QGraphicsItem *> selectedItemList = selectedItems();
 
  337  for ( QGraphicsItem *item : selectedItemList )
 
  339    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
 
  341      componentItem->setSelected( 
false );
 
  344  emit selectedItemChanged( 
nullptr );
 
  347void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
 
  352    item->setSelected( 
true );
 
  354  emit selectedItemChanged( item );
 
  357void QgsModelGraphicsScene::setChildAlgorithmResults( 
const QVariantMap &results )
 
  359  mChildResults = results;
 
  361  for ( 
auto it = mChildResults.constBegin(); it != mChildResults.constEnd(); ++it )
 
  363    if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
 
  365      item->setResults( it.value().toMap() );
 
  370void QgsModelGraphicsScene::setChildAlgorithmInputs( 
const QVariantMap &inputs )
 
  372  mChildInputs = inputs;
 
  374  for ( 
auto it = mChildInputs.constBegin(); it != mChildInputs.constEnd(); ++it )
 
  376    if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
 
  378      item->setInputs( it.value().toMap() );
 
  383QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model, 
const QVariant &value, 
const QString &childId, 
QgsProcessingContext &context )
 const 
  385  QList<QgsModelGraphicsScene::LinkSource> res;
 
  386  if ( value.type() == QVariant::List )
 
  388    const QVariantList list = value.toList();
 
  389    for ( 
const QVariant &v : list )
 
  390      res.append( linkSourcesForParameterValue( model, v, childId, context ) );
 
  392  else if ( value.type() == QVariant::StringList )
 
  394    const QStringList list = value.toStringList();
 
  395    for ( 
const QString &v : list )
 
  396      res.append( linkSourcesForParameterValue( model, v, childId, context ) );
 
  398  else if ( value.userType() == QMetaType::type( 
"QgsProcessingModelChildParameterSource" ) )
 
  400    const QgsProcessingModelChildParameterSource source = value.value< QgsProcessingModelChildParameterSource >();
 
  401    switch ( source.source() )
 
  403      case QgsProcessingModelChildParameterSource::ModelParameter:
 
  406        l.item = mParameterItems.value( source.parameterName() );
 
  410      case QgsProcessingModelChildParameterSource::ChildOutput:
 
  412        if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
 
  419          if ( output->name() == source.outputName() )
 
  423        if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
 
  426          l.item = mChildAlgorithmItems.value( source.outputChildId() );
 
  427          l.edge = Qt::BottomEdge;
 
  430          if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
 
  432            QString short_message = tr( 
"Check output links for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
 
  433            QString long_message = tr( 
"Cannot link output for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
 
  434            QString title( tr( 
"Algorithm link error" ) );
 
  436              showWarning( 
const_cast<QString &
>( short_message ), 
const_cast<QString &
>( title ), 
const_cast<QString &
>( long_message ) );
 
  449      case QgsProcessingModelChildParameterSource::Expression:
 
  451        const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, context );
 
  453        const QSet<QString> vars = exp.referencedVariables();
 
  454        for ( 
const QString &v : vars )
 
  456          if ( variables.contains( v ) )
 
  458            res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
 
  464      case QgsProcessingModelChildParameterSource::StaticValue:
 
  465      case QgsProcessingModelChildParameterSource::ExpressionText:
 
  466      case QgsProcessingModelChildParameterSource::ModelOutput:
 
  473void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model, 
const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
 
  475  if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
 
  478  QgsModelComponentGraphicItem *commentItem = createCommentGraphicItem( model, component.comment()->clone(), parentItem );
 
  479  commentItem->setPos( component.comment()->position().x(), component.comment()->position().y() );
 
  480  addItem( commentItem );
 
  481  connect( commentItem, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  482  connect( commentItem, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  483  connect( commentItem, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  485  std::unique_ptr< QgsModelArrowItem > arrow = std::make_unique< QgsModelArrowItem >( parentItem, QgsModelArrowItem::Circle, commentItem, QgsModelArrowItem::Circle );
 
  486  arrow->setPenStyle( Qt::DotLine );
 
  487  addItem( arrow.release() );
 
  495void QgsModelGraphicsScene::setMessageBar( 
QgsMessageBar *messageBar )
 
  497  mMessageBar = messageBar;
 
  500void QgsModelGraphicsScene::showWarning( 
const QString &shortMessage, 
const QString &title, 
const QString &longMessage, 
Qgis::MessageLevel level )
 const 
  503  QPushButton *detailsButton = 
new QPushButton( tr( 
"Details" ) );
 
  504  connect( detailsButton, &QPushButton::clicked, detailsButton, [ = ]
 
  511  messageWidget->layout()->addWidget( detailsButton );
 
  512  mMessageBar->clearWidgets();
 
  513  mMessageBar->pushWidget( messageWidget, level, 0 );
 
MessageLevel
Level for messages This will be used both for message log and message bar in application.
 
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.
 
Base class for the definition of processing outputs.
 
Base class for the definition of processing parameters.
 
@ FlagHidden
Parameter is hidden and should not be shown to users.
 
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.