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.