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.