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 outputItems.insert( outputIt.key(), item );
269 addItem(
new QgsModelArrowItem( mChildAlgorithmItems[it.value().childId()], Qt::BottomEdge, idx, QgsModelArrowItem::Marker::Circle, item, QgsModelArrowItem::Marker::Circle ) );
271 addCommentItemForComponent( model, outputIt.value(), item );
273 mOutputItems.insert( it.value().childId(), outputItems );
277QList<QgsModelComponentGraphicItem *> QgsModelGraphicsScene::selectedComponentItems()
279 QList<QgsModelComponentGraphicItem *> componentItemList;
281 const QList<QGraphicsItem *> graphicsItemList = selectedItems();
282 for ( QGraphicsItem *item : graphicsItemList )
284 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
286 componentItemList.push_back( componentItem );
290 return componentItemList;
293QgsModelComponentGraphicItem *QgsModelGraphicsScene::componentItemAt( QPointF position )
const
296 const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
298 for ( QGraphicsItem *graphicsItem : itemList )
300 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
302 return componentItem;
308QgsModelComponentGraphicItem *QgsModelGraphicsScene::groupBoxItem(
const QString &uuid )
310 return mGroupBoxItems.value( uuid );
313void QgsModelGraphicsScene::selectAll()
316 QgsModelComponentGraphicItem *focusedItem =
nullptr;
317 const QList<QGraphicsItem *> itemList = items();
318 for ( QGraphicsItem *graphicsItem : itemList )
320 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
322 componentItem->setSelected(
true );
324 focusedItem = componentItem;
327 emit selectedItemChanged( focusedItem );
330void QgsModelGraphicsScene::deselectAll()
335 const QList<QGraphicsItem *> selectedItemList = selectedItems();
336 for ( QGraphicsItem *item : selectedItemList )
338 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
340 componentItem->setSelected(
false );
343 emit selectedItemChanged(
nullptr );
346void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
351 item->setSelected(
true );
353 emit selectedItemChanged( item );
356void QgsModelGraphicsScene::setChildAlgorithmResults(
const QVariantMap &results )
358 mChildResults = results;
360 for (
auto it = mChildResults.constBegin(); it != mChildResults.constEnd(); ++it )
362 if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
364 item->setResults( it.value().toMap() );
369void QgsModelGraphicsScene::setChildAlgorithmInputs(
const QVariantMap &inputs )
371 mChildInputs = inputs;
373 for (
auto it = mChildInputs.constBegin(); it != mChildInputs.constEnd(); ++it )
375 if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
377 item->setInputs( it.value().toMap() );
382QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model,
const QVariant &value,
const QString &childId,
QgsProcessingContext &context )
const
384 QList<QgsModelGraphicsScene::LinkSource> res;
385 if ( value.type() == QVariant::List )
387 const QVariantList list = value.toList();
388 for (
const QVariant &v : list )
389 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
391 else if ( value.type() == QVariant::StringList )
393 const QStringList list = value.toStringList();
394 for (
const QString &v : list )
395 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
397 else if ( value.userType() == QMetaType::type(
"QgsProcessingModelChildParameterSource" ) )
399 const QgsProcessingModelChildParameterSource source = value.value< QgsProcessingModelChildParameterSource >();
400 switch ( source.source() )
402 case QgsProcessingModelChildParameterSource::ModelParameter:
405 l.item = mParameterItems.value( source.parameterName() );
409 case QgsProcessingModelChildParameterSource::ChildOutput:
411 if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
418 if ( output->name() == source.outputName() )
422 if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
425 l.item = mChildAlgorithmItems.value( source.outputChildId() );
426 l.edge = Qt::BottomEdge;
429 if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
431 QString short_message = tr(
"Check output links for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
432 QString long_message = tr(
"Cannot link output for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
433 QString title( tr(
"Algorithm link error" ) );
435 showWarning(
const_cast<QString &
>( short_message ),
const_cast<QString &
>( title ),
const_cast<QString &
>( long_message ) );
448 case QgsProcessingModelChildParameterSource::Expression:
450 const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, context );
452 const QSet<QString> vars = exp.referencedVariables();
453 for (
const QString &v : vars )
455 if ( variables.contains( v ) )
457 res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
463 case QgsProcessingModelChildParameterSource::StaticValue:
464 case QgsProcessingModelChildParameterSource::ExpressionText:
465 case QgsProcessingModelChildParameterSource::ModelOutput:
472void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model,
const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
474 if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
477 QgsModelComponentGraphicItem *commentItem = createCommentGraphicItem( model, component.comment()->clone(), parentItem );
478 commentItem->setPos( component.comment()->position().x(), component.comment()->position().y() );
479 addItem( commentItem );
480 connect( commentItem, &QgsModelComponentGraphicItem::requestModelRepaint,
this, &QgsModelGraphicsScene::rebuildRequired );
481 connect( commentItem, &QgsModelComponentGraphicItem::changed,
this, &QgsModelGraphicsScene::componentChanged );
482 connect( commentItem, &QgsModelComponentGraphicItem::aboutToChange,
this, &QgsModelGraphicsScene::componentAboutToChange );
484 std::unique_ptr< QgsModelArrowItem > arrow = std::make_unique< QgsModelArrowItem >( parentItem, QgsModelArrowItem::Circle, commentItem, QgsModelArrowItem::Circle );
485 arrow->setPenStyle( Qt::DotLine );
486 addItem( arrow.release() );
494void QgsModelGraphicsScene::setMessageBar(
QgsMessageBar *messageBar )
496 mMessageBar = messageBar;
499void QgsModelGraphicsScene::showWarning(
const QString &shortMessage,
const QString &title,
const QString &longMessage,
Qgis::MessageLevel level )
const
502 QPushButton *detailsButton =
new QPushButton( tr(
"Details" ) );
503 connect( detailsButton, &QPushButton::clicked, detailsButton, [ = ]
510 messageWidget->layout()->addWidget( detailsButton );
511 mMessageBar->clearWidgets();
512 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.