17#include "moc_qgsmodelgraphicsscene.cpp" 
   27#include <QGraphicsSceneMouseEvent> 
   32QgsModelGraphicsScene::QgsModelGraphicsScene( QObject *parent )
 
   33  : QGraphicsScene( parent )
 
   35  setItemIndexMethod( QGraphicsScene::NoIndex );
 
   38QgsProcessingModelAlgorithm *QgsModelGraphicsScene::model()
 
   43void QgsModelGraphicsScene::setModel( QgsProcessingModelAlgorithm *model )
 
   48void QgsModelGraphicsScene::setFlag( QgsModelGraphicsScene::Flag flag, 
bool on )
 
   56void QgsModelGraphicsScene::mousePressEvent( QGraphicsSceneMouseEvent *event )
 
   58  if ( event->button() != Qt::LeftButton )
 
   60  QGraphicsScene::mousePressEvent( event );
 
   63QgsModelComponentGraphicItem *QgsModelGraphicsScene::createParameterGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelParameter *param )
 const 
   65  return new QgsModelParameterGraphicItem( param, model, 
nullptr );
 
   68QgsModelChildAlgorithmGraphicItem *QgsModelGraphicsScene::createChildAlgGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelChildAlgorithm *child )
 const 
   70  return new QgsModelChildAlgorithmGraphicItem( child, model, 
nullptr );
 
   73QgsModelComponentGraphicItem *QgsModelGraphicsScene::createOutputGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelOutput *output )
 const 
   75  return new QgsModelOutputGraphicItem( output, model, 
nullptr );
 
   78QgsModelComponentGraphicItem *QgsModelGraphicsScene::createCommentGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem )
 const 
   80  return new QgsModelCommentGraphicItem( comment, parentItem, model, 
nullptr );
 
   83QgsModelComponentGraphicItem *QgsModelGraphicsScene::createGroupBoxGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelGroupBox *box )
 const 
   85  return new QgsModelGroupBoxGraphicItem( box, model, 
nullptr );
 
   88void QgsModelGraphicsScene::createItems( QgsProcessingModelAlgorithm *model, 
QgsProcessingContext &context )
 
   91  const QList<QgsProcessingModelGroupBox> boxes = model->groupBoxes();
 
   92  mGroupBoxItems.clear();
 
   93  for ( 
const QgsProcessingModelGroupBox &box : boxes )
 
   95    QgsModelComponentGraphicItem *item = createGroupBoxGraphicItem( model, box.clone() );
 
   97    item->setPos( box.position().x(), box.position().y() );
 
   98    mGroupBoxItems.insert( box.uuid(), item );
 
   99    connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  100    connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  101    connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  105  const QMap<QString, QgsProcessingModelParameter> params = model->parameterComponents();
 
  106  for ( 
auto it = params.constBegin(); it != params.constEnd(); ++it )
 
  108    QgsModelComponentGraphicItem *item = createParameterGraphicItem( model, it.value().clone() );
 
  110    item->setPos( it.value().position().x(), it.value().position().y() );
 
  111    mParameterItems.insert( it.value().parameterName(), item );
 
  112    connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  113    connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  114    connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  116    addCommentItemForComponent( model, it.value(), item );
 
  120  for ( 
auto it = params.constBegin(); it != params.constEnd(); ++it )
 
  124    for ( 
const QString &otherName : parameterLinks )
 
  126      if ( mParameterItems.contains( it.key() ) && mParameterItems.contains( otherName ) )
 
  128        auto arrow = std::make_unique<QgsModelArrowItem>( mParameterItems.value( otherName ), QgsModelArrowItem::Marker::Circle, mParameterItems.value( it.key() ), QgsModelArrowItem::Marker::ArrowHead );
 
  129        arrow->setPenStyle( Qt::DotLine );
 
  130        addItem( arrow.release() );
 
  136  const QMap<QString, QgsProcessingModelChildAlgorithm> childAlgs = model->childAlgorithms();
 
  137  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  139    QgsModelChildAlgorithmGraphicItem *item = createChildAlgGraphicItem( model, it.value().clone() );
 
  141    item->setPos( it.value().position().x(), it.value().position().y() );
 
  143    const QString childId = it.value().childId();
 
  144    item->setResults( mLastResult.childResults().value( childId ) );
 
  145    mChildAlgorithmItems.insert( childId, item );
 
  146    connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  147    connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  148    connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  149    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] {
 
  154      emit showChildAlgorithmOutputs( childId );
 
  156    connect( item, &QgsModelChildAlgorithmGraphicItem::showLog, 
this, [
this, childId] {
 
  157      emit showChildAlgorithmLog( childId );
 
  160    addCommentItemForComponent( model, it.value(), item );
 
  164  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  168    if ( !it.value().algorithm() )
 
  176        QList<QgsProcessingModelChildParameterSource> sources;
 
  177        if ( it.value().parameterSources().contains( parameter->name() ) )
 
  178          sources = it.value().parameterSources()[parameter->name()];
 
  179        for ( 
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
 
  181          const QList<LinkSource> sourceItems = linkSourcesForParameterValue( model, QVariant::fromValue( source ), it.value().childId(), context );
 
  182          for ( 
const LinkSource &link : sourceItems )
 
  186            QgsModelArrowItem *arrow = 
nullptr;
 
  187            if ( link.linkIndex == -1 )
 
  189              arrow = 
new QgsModelArrowItem( link.item, QgsModelArrowItem::Marker::NoMarker, mChildAlgorithmItems.value( it.value().childId() ), parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge, parameter->isDestination() ? bottomIdx : topIdx, QgsModelArrowItem::Marker::Circle );
 
  193              arrow = 
new QgsModelArrowItem( link.item, link.edge, link.linkIndex, 
true, QgsModelArrowItem::Marker::NoMarker, mChildAlgorithmItems.value( it.value().childId() ), parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge, parameter->isDestination() ? bottomIdx : topIdx, true, QgsModelArrowItem::Marker::NoMarker );
 
  198        if ( parameter->isDestination() )
 
  204    const QList<QgsProcessingModelChildDependency> dependencies = it.value().dependencies();
 
  205    for ( 
const QgsProcessingModelChildDependency &depend : dependencies )
 
  207      if ( depend.conditionalBranch.isEmpty() || !model->childAlgorithm( depend.childId ).algorithm() )
 
  209        addItem( 
new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
 
  219          if ( output->name() == depend.conditionalBranch )
 
  227          addItem( 
new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), Qt::BottomEdge, i, QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
 
  233  for ( 
auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
 
  235    const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
 
  236    QMap<QString, QgsModelComponentGraphicItem *> outputItems;
 
  240    QgsProcessingModelComponent *algItem = mChildAlgorithmItems[it.value().childId()]->component();
 
  241    const double outputOffsetX = algItem->size().width();
 
  242    double outputOffsetY = 1.5 * algItem->size().height();
 
  244    for ( 
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
 
  246      QgsModelComponentGraphicItem *item = createOutputGraphicItem( model, outputIt.value().clone() );
 
  248      connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  249      connect( item, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  250      connect( item, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  255      QPointF pos = outputIt.value().position();
 
  258        pos = algItem->position() + QPointF( outputOffsetX, outputOffsetY );
 
  259        outputOffsetY += 1.5 * outputIt.value().size().height();
 
  264      if ( it.value().algorithm() )
 
  269          if ( childAlgOutput->name() == outputIt.value().childOutputName() )
 
  279      item->component()->setPosition( pos );
 
  280      outputItems.insert( outputIt.key(), item );
 
  281      addItem( 
new QgsModelArrowItem( mChildAlgorithmItems[it.value().childId()], Qt::BottomEdge, idx, QgsModelArrowItem::Marker::Circle, item, QgsModelArrowItem::Marker::Circle ) );
 
  283      addCommentItemForComponent( model, outputIt.value(), item );
 
  285    mOutputItems.insert( it.value().childId(), outputItems );
 
  289QList<QgsModelComponentGraphicItem *> QgsModelGraphicsScene::selectedComponentItems()
 
  291  QList<QgsModelComponentGraphicItem *> componentItemList;
 
  293  const QList<QGraphicsItem *> graphicsItemList = selectedItems();
 
  294  for ( QGraphicsItem *item : graphicsItemList )
 
  296    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
 
  298      componentItemList.push_back( componentItem );
 
  302  return componentItemList;
 
  305QgsModelComponentGraphicItem *QgsModelGraphicsScene::componentItemAt( QPointF position )
 const 
  308  const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
 
  310  for ( QGraphicsItem *graphicsItem : itemList )
 
  312    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
 
  314      return componentItem;
 
  320QgsModelComponentGraphicItem *QgsModelGraphicsScene::groupBoxItem( 
const QString &uuid )
 
  322  return mGroupBoxItems.value( uuid );
 
  325QgsModelChildAlgorithmGraphicItem *QgsModelGraphicsScene::childAlgorithmItem( 
const QString &childId )
 
  327  return mChildAlgorithmItems.value( childId );
 
  330QgsModelComponentGraphicItem *QgsModelGraphicsScene::parameterItem( 
const QString &name )
 
  332  return mParameterItems.value( name );
 
  335void QgsModelGraphicsScene::selectAll()
 
  338  QgsModelComponentGraphicItem *focusedItem = 
nullptr;
 
  339  const QList<QGraphicsItem *> itemList = items();
 
  340  for ( QGraphicsItem *graphicsItem : itemList )
 
  342    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
 
  344      componentItem->setSelected( 
true );
 
  346        focusedItem = componentItem;
 
  349  emit selectedItemChanged( focusedItem );
 
  352void QgsModelGraphicsScene::deselectAll()
 
  357  const QList<QGraphicsItem *> selectedItemList = selectedItems();
 
  358  for ( QGraphicsItem *item : selectedItemList )
 
  360    if ( QgsModelComponentGraphicItem *componentItem = 
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
 
  362      componentItem->setSelected( 
false );
 
  365  emit selectedItemChanged( 
nullptr );
 
  368void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
 
  373    item->setSelected( 
true );
 
  375  emit selectedItemChanged( item );
 
  380  mLastResult = result;
 
  383  for ( 
auto it = childResults.constBegin(); it != childResults.constEnd(); ++it )
 
  385    if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
 
  387      item->setResults( it.value() );
 
  392QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model, 
const QVariant &value, 
const QString &childId, 
QgsProcessingContext &context )
 const 
  394  QList<QgsModelGraphicsScene::LinkSource> res;
 
  395  if ( value.userType() == QMetaType::Type::QVariantList )
 
  397    const QVariantList list = value.toList();
 
  398    for ( 
const QVariant &v : list )
 
  399      res.append( linkSourcesForParameterValue( model, v, childId, context ) );
 
  401  else if ( value.userType() == QMetaType::Type::QStringList )
 
  403    const QStringList list = value.toStringList();
 
  404    for ( 
const QString &v : list )
 
  405      res.append( linkSourcesForParameterValue( model, v, childId, context ) );
 
  407  else if ( value.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() )
 
  409    const QgsProcessingModelChildParameterSource source = value.value<QgsProcessingModelChildParameterSource>();
 
  410    switch ( source.source() )
 
  415        l.item = mParameterItems.value( source.parameterName() );
 
  416        l.edge = Qt::BottomEdge;
 
  424        if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
 
  431          if ( output->name() == source.outputName() )
 
  435        if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
 
  438          l.item = mChildAlgorithmItems.value( source.outputChildId() );
 
  439          l.edge = Qt::BottomEdge;
 
  442          if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
 
  444            QString short_message = tr( 
"Check output links for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
 
  445            QString long_message = tr( 
"Cannot link output for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
 
  446            QString title( tr( 
"Algorithm link error" ) );
 
  448              showWarning( 
const_cast<QString &
>( short_message ), 
const_cast<QString &
>( title ), 
const_cast<QString &
>( long_message ) );
 
  463        const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, &context );
 
  465        const QSet<QString> vars = exp.referencedVariables();
 
  466        for ( 
const QString &v : vars )
 
  468          if ( variables.contains( v ) )
 
  470            res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
 
  485void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model, 
const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
 
  487  if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
 
  490  QgsModelComponentGraphicItem *commentItem = createCommentGraphicItem( model, component.comment()->clone(), parentItem );
 
  491  commentItem->setPos( component.comment()->position().x(), component.comment()->position().y() );
 
  492  addItem( commentItem );
 
  493  connect( commentItem, &QgsModelComponentGraphicItem::requestModelRepaint, 
this, &QgsModelGraphicsScene::rebuildRequired );
 
  494  connect( commentItem, &QgsModelComponentGraphicItem::changed, 
this, &QgsModelGraphicsScene::componentChanged );
 
  495  connect( commentItem, &QgsModelComponentGraphicItem::aboutToChange, 
this, &QgsModelGraphicsScene::componentAboutToChange );
 
  497  auto arrow = std::make_unique<QgsModelArrowItem>( parentItem, QgsModelArrowItem::Circle, commentItem, QgsModelArrowItem::Circle );
 
  498  arrow->setPenStyle( Qt::DotLine );
 
  499  addItem( arrow.release() );
 
  507void QgsModelGraphicsScene::setMessageBar( 
QgsMessageBar *messageBar )
 
  509  mMessageBar = messageBar;
 
  512void QgsModelGraphicsScene::showWarning( 
const QString &shortMessage, 
const QString &title, 
const QString &longMessage, 
Qgis::MessageLevel level )
 const 
  515  QPushButton *detailsButton = 
new QPushButton( tr( 
"Details" ) );
 
  516  connect( detailsButton, &QPushButton::clicked, detailsButton, [detailsButton, title, longMessage] {
 
  522  messageWidget->layout()->addWidget( detailsButton );
 
  523  mMessageBar->clearWidgets();
 
  524  mMessageBar->pushWidget( messageWidget, level, 0 );
 
  527void QgsModelGraphicsScene::requestRebuildRequired()
 
  529  emit rebuildRequired();
 
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.
 
Handles 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, 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 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.