QGIS API Documentation  3.21.0-Master (909859188c)
qgsmodelgraphicsscene.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmodelgraphicsscene.cpp
3  ----------------------------------
4  Date : March 2020
5  Copyright : (C) 2020 Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsmodelgraphicsscene.h"
17 #include "qgsprocessingmodelchildparametersource.h"
18 #include "qgsprocessingmodelalgorithm.h"
20 #include "qgsmodelarrowitem.h"
21 #include "qgsprocessingmodelgroupbox.h"
22 #include "qgsmessagebar.h"
23 #include "qgsmessagebaritem.h"
24 #include "qgsmessageviewer.h"
25 #include "qgsapplication.h"
26 #include <QGraphicsSceneMouseEvent>
27 #include <QPushButton>
28 
30 
31 QgsModelGraphicsScene::QgsModelGraphicsScene( QObject *parent )
32  : QGraphicsScene( parent )
33 {
34  setItemIndexMethod( QGraphicsScene::NoIndex );
35 }
36 
37 QgsProcessingModelAlgorithm *QgsModelGraphicsScene::model()
38 {
39  return mModel;
40 }
41 
42 void QgsModelGraphicsScene::setModel( QgsProcessingModelAlgorithm *model )
43 {
44  mModel = model;
45 }
46 
47 void QgsModelGraphicsScene::setFlag( QgsModelGraphicsScene::Flag flag, bool on )
48 {
49  if ( on )
50  mFlags |= flag;
51  else
52  mFlags &= ~flag;
53 }
54 
55 void QgsModelGraphicsScene::mousePressEvent( QGraphicsSceneMouseEvent *event )
56 {
57  if ( event->button() != Qt::LeftButton )
58  return;
59  QGraphicsScene::mousePressEvent( event );
60 }
61 
62 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createParameterGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelParameter *param ) const
63 {
64  return new QgsModelParameterGraphicItem( param, model, nullptr );
65 }
66 
67 QgsModelChildAlgorithmGraphicItem *QgsModelGraphicsScene::createChildAlgGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelChildAlgorithm *child ) const
68 {
69  return new QgsModelChildAlgorithmGraphicItem( child, model, nullptr );
70 }
71 
72 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createOutputGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelOutput *output ) const
73 {
74  return new QgsModelOutputGraphicItem( output, model, nullptr );
75 }
76 
77 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createCommentGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem ) const
78 {
79  return new QgsModelCommentGraphicItem( comment, parentItem, model, nullptr );
80 }
81 
82 QgsModelComponentGraphicItem *QgsModelGraphicsScene::createGroupBoxGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelGroupBox *box ) const
83 {
84  return new QgsModelGroupBoxGraphicItem( box, model, nullptr );
85 }
86 
87 void QgsModelGraphicsScene::createItems( QgsProcessingModelAlgorithm *model, QgsProcessingContext &context )
88 {
89  // model group boxes
90  const QList<QgsProcessingModelGroupBox> boxes = model->groupBoxes();
91  mGroupBoxItems.clear();
92  for ( const QgsProcessingModelGroupBox &box : boxes )
93  {
94  QgsModelComponentGraphicItem *item = createGroupBoxGraphicItem( model, box.clone() );
95  addItem( item );
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 );
101  }
102 
103  // model input parameters
104  const QMap<QString, QgsProcessingModelParameter> params = model->parameterComponents();
105  for ( auto it = params.constBegin(); it != params.constEnd(); ++it )
106  {
107  QgsModelComponentGraphicItem *item = createParameterGraphicItem( model, it.value().clone() );
108  addItem( item );
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 );
114 
115  addCommentItemForComponent( model, it.value(), item );
116  }
117 
118  // input dependency arrows
119  for ( auto it = params.constBegin(); it != params.constEnd(); ++it )
120  {
121  const QgsProcessingParameterDefinition *parameterDef = model->parameterDefinition( it.key() );
122  const QStringList parameterLinks = parameterDef->dependsOnOtherParameters();
123  for ( const QString &otherName : parameterLinks )
124  {
125  if ( mParameterItems.contains( it.key() ) && mParameterItems.contains( otherName ) )
126  {
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() );
130  }
131  }
132  }
133 
134  // child algorithms
135  const QMap<QString, QgsProcessingModelChildAlgorithm> childAlgs = model->childAlgorithms();
136  for ( auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
137  {
138  QgsModelChildAlgorithmGraphicItem *item = createChildAlgGraphicItem( model, it.value().clone() );
139  addItem( item );
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 );
147 
148  addCommentItemForComponent( model, it.value(), item );
149  }
150 
151  // arrows linking child algorithms
152  for ( auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
153  {
154  int topIdx = 0;
155  int bottomIdx = 0;
156  if ( !it.value().algorithm() )
157  continue;
158 
159  const QgsProcessingParameterDefinitions parameters = it.value().algorithm()->parameterDefinitions();
160  for ( const QgsProcessingParameterDefinition *parameter : parameters )
161  {
162  if ( !( parameter->flags() & QgsProcessingParameterDefinition::FlagHidden ) )
163  {
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 )
168  {
169  const QList< LinkSource > sourceItems = linkSourcesForParameterValue( model, QVariant::fromValue( source ), it.value().childId(), context );
170  for ( const LinkSource &link : sourceItems )
171  {
172  if ( !link.item )
173  continue;
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 );
177  else
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,
182  true,
183  QgsModelArrowItem::Marker::Circle );
184  addItem( arrow );
185  }
186  }
187  if ( parameter->isDestination() )
188  bottomIdx++;
189  else
190  topIdx++;
191  }
192  }
193  const QList< QgsProcessingModelChildDependency > dependencies = it.value().dependencies();
194  for ( const QgsProcessingModelChildDependency &depend : dependencies )
195  {
196  if ( depend.conditionalBranch.isEmpty() || !model->childAlgorithm( depend.childId ).algorithm() )
197  {
198  addItem( new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
199  }
200  else
201  {
202  // find branch link point
203  const QgsProcessingOutputDefinitions outputs = model->childAlgorithm( depend.childId ).algorithm()->outputDefinitions();
204  int i = 0;
205  bool found = false;
206  for ( const QgsProcessingOutputDefinition *output : outputs )
207  {
208  if ( output->name() == depend.conditionalBranch )
209  {
210  found = true;
211  break;
212  }
213  i++;
214  }
215  if ( found )
216  addItem( new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), Qt::BottomEdge, i, QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
217  }
218  }
219  }
220 
221  // and finally the model outputs
222  for ( auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
223  {
224  const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
225  QMap< QString, QgsModelComponentGraphicItem * > outputItems;
226 
227  for ( auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
228  {
229  QgsModelComponentGraphicItem *item = createOutputGraphicItem( model, outputIt.value().clone() );
230  addItem( item );
231  connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, this, &QgsModelGraphicsScene::rebuildRequired );
232  connect( item, &QgsModelComponentGraphicItem::changed, this, &QgsModelGraphicsScene::componentChanged );
233  connect( item, &QgsModelComponentGraphicItem::aboutToChange, this, &QgsModelGraphicsScene::componentAboutToChange );
234 
235  const QPointF pos = outputIt.value().position();
236  int idx = -1;
237  int i = 0;
238  // find the actual index of the linked output from the child algorithm it comes from
239  if ( it.value().algorithm() )
240  {
241  const QgsProcessingOutputDefinitions sourceChildAlgOutputs = it.value().algorithm()->outputDefinitions();
242  for ( const QgsProcessingOutputDefinition *childAlgOutput : sourceChildAlgOutputs )
243  {
244  if ( childAlgOutput->name() == outputIt.value().childOutputName() )
245  {
246  idx = i;
247  break;
248  }
249  i++;
250  }
251  }
252 
253  item->setPos( pos );
254  outputItems.insert( outputIt.key(), item );
255  addItem( new QgsModelArrowItem( mChildAlgorithmItems[it.value().childId()], Qt::BottomEdge, idx, QgsModelArrowItem::Marker::Circle, item, QgsModelArrowItem::Marker::Circle ) );
256 
257  addCommentItemForComponent( model, outputIt.value(), item );
258  }
259  mOutputItems.insert( it.value().childId(), outputItems );
260  }
261 }
262 
263 QList<QgsModelComponentGraphicItem *> QgsModelGraphicsScene::selectedComponentItems()
264 {
265  QList<QgsModelComponentGraphicItem *> componentItemList;
266 
267  const QList<QGraphicsItem *> graphicsItemList = selectedItems();
268  for ( QGraphicsItem *item : graphicsItemList )
269  {
270  if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( item ) )
271  {
272  componentItemList.push_back( componentItem );
273  }
274  }
275 
276  return componentItemList;
277 }
278 
279 QgsModelComponentGraphicItem *QgsModelGraphicsScene::componentItemAt( QPointF position ) const
280 {
281  //get a list of items which intersect the specified position, in descending z order
282  const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
283 
284  for ( QGraphicsItem *graphicsItem : itemList )
285  {
286  if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( graphicsItem ) )
287  {
288  return componentItem;
289  }
290  }
291  return nullptr;
292 }
293 
294 QgsModelComponentGraphicItem *QgsModelGraphicsScene::groupBoxItem( const QString &uuid )
295 {
296  return mGroupBoxItems.value( uuid );
297 }
298 
299 void QgsModelGraphicsScene::selectAll()
300 {
301  //select all items in scene
302  QgsModelComponentGraphicItem *focusedItem = nullptr;
303  const QList<QGraphicsItem *> itemList = items();
304  for ( QGraphicsItem *graphicsItem : itemList )
305  {
306  if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( graphicsItem ) )
307  {
308  componentItem->setSelected( true );
309  if ( !focusedItem )
310  focusedItem = componentItem;
311  }
312  }
313  emit selectedItemChanged( focusedItem );
314 }
315 
316 void QgsModelGraphicsScene::deselectAll()
317 {
318  //we can't use QGraphicsScene::clearSelection, as that emits no signals
319  //and we don't know which items are being deselected
320  //instead, do the clear selection manually...
321  const QList<QGraphicsItem *> selectedItemList = selectedItems();
322  for ( QGraphicsItem *item : selectedItemList )
323  {
324  if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( item ) )
325  {
326  componentItem->setSelected( false );
327  }
328  }
329  emit selectedItemChanged( nullptr );
330 }
331 
332 void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
333 {
334  whileBlocking( this )->deselectAll();
335  if ( item )
336  {
337  item->setSelected( true );
338  }
339  emit selectedItemChanged( item );
340 }
341 
342 void QgsModelGraphicsScene::setChildAlgorithmResults( const QVariantMap &results )
343 {
344  mChildResults = results;
345 
346  for ( auto it = mChildResults.constBegin(); it != mChildResults.constEnd(); ++it )
347  {
348  if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
349  {
350  item->setResults( it.value().toMap() );
351  }
352  }
353 }
354 
355 void QgsModelGraphicsScene::setChildAlgorithmInputs( const QVariantMap &inputs )
356 {
357  mChildInputs = inputs;
358 
359  for ( auto it = mChildInputs.constBegin(); it != mChildInputs.constEnd(); ++it )
360  {
361  if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
362  {
363  item->setInputs( it.value().toMap() );
364  }
365  }
366 }
367 
368 QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model, const QVariant &value, const QString &childId, QgsProcessingContext &context ) const
369 {
370  QList<QgsModelGraphicsScene::LinkSource> res;
371  if ( value.type() == QVariant::List )
372  {
373  const QVariantList list = value.toList();
374  for ( const QVariant &v : list )
375  res.append( linkSourcesForParameterValue( model, v, childId, context ) );
376  }
377  else if ( value.type() == QVariant::StringList )
378  {
379  const QStringList list = value.toStringList();
380  for ( const QString &v : list )
381  res.append( linkSourcesForParameterValue( model, v, childId, context ) );
382  }
383  else if ( value.canConvert< QgsProcessingModelChildParameterSource >() )
384  {
385  const QgsProcessingModelChildParameterSource source = value.value< QgsProcessingModelChildParameterSource >();
386  switch ( source.source() )
387  {
388  case QgsProcessingModelChildParameterSource::ModelParameter:
389  {
390  LinkSource l;
391  l.item = mParameterItems.value( source.parameterName() );
392  res.append( l );
393  break;
394  }
395  case QgsProcessingModelChildParameterSource::ChildOutput:
396  {
397  if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
398  break;
399 
400  const QgsProcessingOutputDefinitions outputs = model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions();
401  int i = 0;
402  for ( const QgsProcessingOutputDefinition *output : outputs )
403  {
404  if ( output->name() == source.outputName() )
405  break;
406  i++;
407  }
408  if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
409  {
410  LinkSource l;
411  l.item = mChildAlgorithmItems.value( source.outputChildId() );
412  l.edge = Qt::BottomEdge;
413 
414  // do sanity check of linked index
415  if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
416  {
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" ) );
420  if ( messageBar() )
421  showWarning( const_cast<QString &>( short_message ), const_cast<QString &>( title ), const_cast<QString &>( long_message ) );
422  else
423  QgsMessageLog::logMessage( long_message, "QgsModelGraphicsScene", Qgis::MessageLevel::Warning, true );
424  break;
425  }
426 
427  l.linkIndex = i;
428  res.append( l );
429  }
430 
431  break;
432  }
433 
434  case QgsProcessingModelChildParameterSource::Expression:
435  {
436  const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, context );
437  const QgsExpression exp( source.expression() );
438  const QSet<QString> vars = exp.referencedVariables();
439  for ( const QString &v : vars )
440  {
441  if ( variables.contains( v ) )
442  {
443  res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
444  }
445  }
446  break;
447  }
448 
449  case QgsProcessingModelChildParameterSource::StaticValue:
450  case QgsProcessingModelChildParameterSource::ExpressionText:
451  case QgsProcessingModelChildParameterSource::ModelOutput:
452  break;
453  }
454  }
455  return res;
456 }
457 
458 void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model, const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
459 {
460  if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
461  return;
462 
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 );
469 
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() );
473 }
474 
475 QgsMessageBar *QgsModelGraphicsScene::messageBar() const
476 {
477  return mMessageBar;
478 }
479 
480 void QgsModelGraphicsScene::setMessageBar( QgsMessageBar *messageBar )
481 {
482  mMessageBar = messageBar;
483 }
484 
485 void QgsModelGraphicsScene::showWarning( const QString &shortMessage, const QString &title, const QString &longMessage, Qgis::MessageLevel level ) const
486 {
487  QgsMessageBarItem *messageWidget = mMessageBar->createMessage( QString(), shortMessage );
488  QPushButton *detailsButton = new QPushButton( tr( "Details" ) );
489  connect( detailsButton, &QPushButton::clicked, detailsButton, [ = ]
490  {
491  QgsMessageViewer *dialog = new QgsMessageViewer( detailsButton );
492  dialog->setTitle( title );
493  dialog->setMessage( longMessage, QgsMessageOutput::MessageHtml );
494  dialog->showMessage();
495  } );
496  messageWidget->layout()->addWidget( detailsButton );
497  mMessageBar->clearWidgets();
498  mMessageBar->pushWidget( messageWidget, level, 0 );
499 }
500 
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:106
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.
Definition: qgsmessagebar.h:61
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.
Definition: qgis.h:1047
QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions
List of processing parameters.
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.