26 #include <QGraphicsSceneMouseEvent>
27 #include <QPushButton>
31 QgsModelGraphicsScene::QgsModelGraphicsScene( QObject *parent )
32 : QGraphicsScene( parent )
34 setItemIndexMethod( QGraphicsScene::NoIndex );
37 QgsProcessingModelAlgorithm *QgsModelGraphicsScene::model()
42 void QgsModelGraphicsScene::setModel( QgsProcessingModelAlgorithm *model )
47 void QgsModelGraphicsScene::setFlag( QgsModelGraphicsScene::Flag flag,
bool on )
55 void QgsModelGraphicsScene::mousePressEvent( QGraphicsSceneMouseEvent *event )
57 if ( event->button() != Qt::LeftButton )
59 QGraphicsScene::mousePressEvent( event );
62 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createParameterGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelParameter *param )
const
64 return new QgsModelParameterGraphicItem( param, model,
nullptr );
67 QgsModelChildAlgorithmGraphicItem *QgsModelGraphicsScene::createChildAlgGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelChildAlgorithm *child )
const
69 return new QgsModelChildAlgorithmGraphicItem( child, model,
nullptr );
72 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createOutputGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelOutput *output )
const
74 return new QgsModelOutputGraphicItem( output, model,
nullptr );
77 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createCommentGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem )
const
79 return new QgsModelCommentGraphicItem( comment, parentItem, model,
nullptr );
82 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createGroupBoxGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelGroupBox *box )
const
84 return new QgsModelGroupBoxGraphicItem( box, model,
nullptr );
87 void 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;
227 for (
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
229 QgsModelComponentGraphicItem *item = createOutputGraphicItem( model, outputIt.value().clone() );
231 connect( item, &QgsModelComponentGraphicItem::requestModelRepaint,
this, &QgsModelGraphicsScene::rebuildRequired );
232 connect( item, &QgsModelComponentGraphicItem::changed,
this, &QgsModelGraphicsScene::componentChanged );
233 connect( item, &QgsModelComponentGraphicItem::aboutToChange,
this, &QgsModelGraphicsScene::componentAboutToChange );
235 const QPointF pos = outputIt.value().position();
239 if ( it.value().algorithm() )
244 if ( childAlgOutput->name() == outputIt.value().childOutputName() )
254 outputItems.insert( outputIt.key(), item );
255 addItem(
new QgsModelArrowItem( mChildAlgorithmItems[it.value().childId()], Qt::BottomEdge, idx, QgsModelArrowItem::Marker::Circle, item, QgsModelArrowItem::Marker::Circle ) );
257 addCommentItemForComponent( model, outputIt.value(), item );
259 mOutputItems.insert( it.value().childId(), outputItems );
263 QList<QgsModelComponentGraphicItem *> QgsModelGraphicsScene::selectedComponentItems()
265 QList<QgsModelComponentGraphicItem *> componentItemList;
267 const QList<QGraphicsItem *> graphicsItemList = selectedItems();
268 for ( QGraphicsItem *item : graphicsItemList )
270 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
272 componentItemList.push_back( componentItem );
276 return componentItemList;
279 QgsModelComponentGraphicItem *QgsModelGraphicsScene::componentItemAt( QPointF position )
const
282 const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
284 for ( QGraphicsItem *graphicsItem : itemList )
286 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
288 return componentItem;
294 QgsModelComponentGraphicItem *QgsModelGraphicsScene::groupBoxItem(
const QString &uuid )
296 return mGroupBoxItems.value( uuid );
299 void QgsModelGraphicsScene::selectAll()
302 QgsModelComponentGraphicItem *focusedItem =
nullptr;
303 const QList<QGraphicsItem *> itemList = items();
304 for ( QGraphicsItem *graphicsItem : itemList )
306 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( graphicsItem ) )
308 componentItem->setSelected(
true );
310 focusedItem = componentItem;
313 emit selectedItemChanged( focusedItem );
316 void QgsModelGraphicsScene::deselectAll()
321 const QList<QGraphicsItem *> selectedItemList = selectedItems();
322 for ( QGraphicsItem *item : selectedItemList )
324 if ( QgsModelComponentGraphicItem *componentItem =
dynamic_cast<QgsModelComponentGraphicItem *
>( item ) )
326 componentItem->setSelected(
false );
329 emit selectedItemChanged(
nullptr );
332 void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
337 item->setSelected(
true );
339 emit selectedItemChanged( item );
342 void QgsModelGraphicsScene::setChildAlgorithmResults(
const QVariantMap &results )
344 mChildResults = results;
346 for (
auto it = mChildResults.constBegin(); it != mChildResults.constEnd(); ++it )
348 if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
350 item->setResults( it.value().toMap() );
355 void QgsModelGraphicsScene::setChildAlgorithmInputs(
const QVariantMap &inputs )
357 mChildInputs = inputs;
359 for (
auto it = mChildInputs.constBegin(); it != mChildInputs.constEnd(); ++it )
361 if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
363 item->setInputs( it.value().toMap() );
368 QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model,
const QVariant &value,
const QString &childId,
QgsProcessingContext &context )
const
370 QList<QgsModelGraphicsScene::LinkSource> res;
371 if ( value.type() == QVariant::List )
373 const QVariantList list = value.toList();
374 for (
const QVariant &v : list )
375 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
377 else if ( value.type() == QVariant::StringList )
379 const QStringList list = value.toStringList();
380 for (
const QString &v : list )
381 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
383 else if ( value.canConvert< QgsProcessingModelChildParameterSource >() )
385 const QgsProcessingModelChildParameterSource source = value.value< QgsProcessingModelChildParameterSource >();
386 switch ( source.source() )
388 case QgsProcessingModelChildParameterSource::ModelParameter:
391 l.item = mParameterItems.value( source.parameterName() );
395 case QgsProcessingModelChildParameterSource::ChildOutput:
397 if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
404 if ( output->name() == source.outputName() )
408 if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
411 l.item = mChildAlgorithmItems.value( source.outputChildId() );
412 l.edge = Qt::BottomEdge;
415 if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
417 QString short_message = tr(
"Check output links for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
418 QString long_message = tr(
"Cannot link output for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
419 QString title( tr(
"Algorithm link error" ) );
421 showWarning(
const_cast<QString &
>( short_message ),
const_cast<QString &
>( title ),
const_cast<QString &
>( long_message ) );
434 case QgsProcessingModelChildParameterSource::Expression:
436 const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, context );
438 const QSet<QString> vars = exp.referencedVariables();
439 for (
const QString &v : vars )
441 if ( variables.contains( v ) )
443 res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
449 case QgsProcessingModelChildParameterSource::StaticValue:
450 case QgsProcessingModelChildParameterSource::ExpressionText:
451 case QgsProcessingModelChildParameterSource::ModelOutput:
458 void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model,
const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
460 if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
463 QgsModelComponentGraphicItem *commentItem = createCommentGraphicItem( model, component.comment()->clone(), parentItem );
464 commentItem->setPos( component.comment()->position().x(), component.comment()->position().y() );
465 addItem( commentItem );
466 connect( commentItem, &QgsModelComponentGraphicItem::requestModelRepaint,
this, &QgsModelGraphicsScene::rebuildRequired );
467 connect( commentItem, &QgsModelComponentGraphicItem::changed,
this, &QgsModelGraphicsScene::componentChanged );
468 connect( commentItem, &QgsModelComponentGraphicItem::aboutToChange,
this, &QgsModelGraphicsScene::componentAboutToChange );
470 std::unique_ptr< QgsModelArrowItem > arrow = std::make_unique< QgsModelArrowItem >( parentItem, QgsModelArrowItem::Circle, commentItem, QgsModelArrowItem::Circle );
471 arrow->setPenStyle( Qt::DotLine );
472 addItem( arrow.release() );
480 void QgsModelGraphicsScene::setMessageBar(
QgsMessageBar *messageBar )
482 mMessageBar = messageBar;
485 void QgsModelGraphicsScene::showWarning(
const QString &shortMessage,
const QString &title,
const QString &longMessage,
Qgis::MessageLevel level )
const
487 QgsMessageBarItem *messageWidget = mMessageBar->createMessage( QString(), shortMessage );
488 QPushButton *detailsButton =
new QPushButton( tr(
"Details" ) );
489 connect( detailsButton, &QPushButton::clicked, detailsButton, [ = ]
496 messageWidget->layout()->addWidget( detailsButton );
497 mMessageBar->clearWidgets();
498 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 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.