QGIS API Documentation 3.99.0-Master (c22de0620c0)
Loading...
Searching...
No Matches
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
17
18#include "qgsmessagebar.h"
19#include "qgsmessagebaritem.h"
20#include "qgsmessagelog.h"
21#include "qgsmessageviewer.h"
22#include "qgsmodelarrowitem.h"
24#include "qgsmodelgraphicitem.h"
28#include "qgsvectorlayer.h"
29
30#include <QGraphicsSceneMouseEvent>
31#include <QGraphicsTextItem>
32#include <QPushButton>
33#include <QString>
34
35#include "moc_qgsmodelgraphicsscene.cpp"
36
37using namespace Qt::StringLiterals;
38
40
41QgsModelGraphicsScene::QgsModelGraphicsScene( QObject *parent )
42 : QGraphicsScene( parent )
43{
44 setItemIndexMethod( QGraphicsScene::NoIndex );
45
46 connect( this, &QgsModelGraphicsScene::componentChanged, this, &QgsModelGraphicsScene::updateBounds );
47}
48
49QgsProcessingModelAlgorithm *QgsModelGraphicsScene::model()
50{
51 return mModel;
52}
53
54void QgsModelGraphicsScene::setModel( QgsProcessingModelAlgorithm *model )
55{
56 mModel = model;
57}
58
59void QgsModelGraphicsScene::setFlag( QgsModelGraphicsScene::Flag flag, bool on )
60{
61 if ( on )
62 mFlags |= flag;
63 else
64 mFlags &= ~flag;
65}
66
67void QgsModelGraphicsScene::mousePressEvent( QGraphicsSceneMouseEvent *event )
68{
69 if ( event->button() != Qt::LeftButton )
70 return;
71 QGraphicsScene::mousePressEvent( event );
72}
73
74void QgsModelGraphicsScene::updateBounds()
75{
76 //start with an empty rectangle
77 QRectF bounds;
78
79 //add all items
80 const QList<QGraphicsItem *> constItems = items();
81 for ( QGraphicsItem *item : constItems )
82 {
83 QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( item );
84 if ( componentItem )
85 bounds = bounds.united( componentItem->sceneBoundingRect() );
86 }
87
88 if ( bounds.isValid() )
89 {
90 bounds.adjust( -SCENE_COMPONENT_MARGIN, -SCENE_COMPONENT_MARGIN, SCENE_COMPONENT_MARGIN, SCENE_COMPONENT_MARGIN );
91 }
92
93 setSceneRect( bounds );
94}
95
96QgsModelComponentGraphicItem *QgsModelGraphicsScene::createParameterGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelParameter *param ) const
97{
98 return new QgsModelParameterGraphicItem( param, model, nullptr );
99}
100
101QgsModelChildAlgorithmGraphicItem *QgsModelGraphicsScene::createChildAlgGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelChildAlgorithm *child ) const
102{
103 return new QgsModelChildAlgorithmGraphicItem( child, model, nullptr );
104}
105
106QgsModelComponentGraphicItem *QgsModelGraphicsScene::createOutputGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelOutput *output ) const
107{
108 return new QgsModelOutputGraphicItem( output, model, nullptr );
109}
110
111QgsModelComponentGraphicItem *QgsModelGraphicsScene::createCommentGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelComment *comment, QgsModelComponentGraphicItem *parentItem ) const
112{
113 return new QgsModelCommentGraphicItem( comment, parentItem, model, nullptr );
114}
115
116QgsModelComponentGraphicItem *QgsModelGraphicsScene::createGroupBoxGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelGroupBox *box ) const
117{
118 return new QgsModelGroupBoxGraphicItem( box, model, nullptr );
119}
120
121void QgsModelGraphicsScene::createItems( QgsProcessingModelAlgorithm *model, QgsProcessingContext &context )
122{
123 // model group boxes
124 const QList<QgsProcessingModelGroupBox> boxes = model->groupBoxes();
125 mGroupBoxItems.clear();
126 for ( const QgsProcessingModelGroupBox &box : boxes )
127 {
128 QgsModelComponentGraphicItem *item = createGroupBoxGraphicItem( model, box.clone() );
129 addItem( item );
130 item->setPos( box.position().x(), box.position().y() );
131 mGroupBoxItems.insert( box.uuid(), item );
132 connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, this, &QgsModelGraphicsScene::rebuildRequired );
133 connect( item, &QgsModelComponentGraphicItem::changed, this, &QgsModelGraphicsScene::componentChanged );
134 connect( item, &QgsModelComponentGraphicItem::aboutToChange, this, &QgsModelGraphicsScene::componentAboutToChange );
135 }
136
137 // model input parameters
138 const QMap<QString, QgsProcessingModelParameter> params = model->parameterComponents();
139 for ( auto it = params.constBegin(); it != params.constEnd(); ++it )
140 {
141 QgsModelComponentGraphicItem *item = createParameterGraphicItem( model, it.value().clone() );
142 addItem( item );
143 item->setPos( it.value().position().x(), it.value().position().y() );
144 mParameterItems.insert( it.value().parameterName(), 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
149 addCommentItemForComponent( model, it.value(), item );
150 }
151
152 // input dependency arrows
153 for ( auto it = params.constBegin(); it != params.constEnd(); ++it )
154 {
155 const QgsProcessingParameterDefinition *parameterDef = model->parameterDefinition( it.key() );
156 const QStringList parameterLinks = parameterDef->dependsOnOtherParameters();
157 for ( const QString &otherName : parameterLinks )
158 {
159 if ( mParameterItems.contains( it.key() ) && mParameterItems.contains( otherName ) )
160 {
161 auto arrow = std::make_unique<QgsModelArrowItem>( mParameterItems.value( otherName ), QgsModelArrowItem::Marker::Circle, mParameterItems.value( it.key() ), QgsModelArrowItem::Marker::ArrowHead );
162 arrow->setPenStyle( Qt::DotLine );
163 addItem( arrow.release() );
164 }
165 }
166 }
167
168 // child algorithms
169 const QMap<QString, QgsProcessingModelChildAlgorithm> childAlgs = model->childAlgorithms();
170 for ( auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
171 {
172 QgsModelChildAlgorithmGraphicItem *item = createChildAlgGraphicItem( model, it.value().clone() );
173 addItem( item );
174 item->setPos( it.value().position().x(), it.value().position().y() );
175
176 const QString childId = it.value().childId();
177 item->setResults( mLastResult.childResults().value( childId ) );
178 mChildAlgorithmItems.insert( childId, item );
179 connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, this, &QgsModelGraphicsScene::rebuildRequired );
180 connect( item, &QgsModelComponentGraphicItem::changed, this, &QgsModelGraphicsScene::componentChanged );
181 connect( item, &QgsModelComponentGraphicItem::aboutToChange, this, &QgsModelGraphicsScene::componentAboutToChange );
182 connect( item, &QgsModelChildAlgorithmGraphicItem::runFromHere, this, [this, childId] {
183 emit runFromChild( childId );
184 } );
185 connect( item, &QgsModelChildAlgorithmGraphicItem::runSelected, this, &QgsModelGraphicsScene::runSelected );
186 connect( item, &QgsModelChildAlgorithmGraphicItem::showPreviousResults, this, [this, childId] {
187 emit showChildAlgorithmOutputs( childId );
188 } );
189 connect( item, &QgsModelChildAlgorithmGraphicItem::showLog, this, [this, childId] {
190 emit showChildAlgorithmLog( childId );
191 } );
192
193 addCommentItemForComponent( model, it.value(), item );
194 }
195
196 // arrows linking child algorithms
197 for ( auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
198 {
199 int topIdx = 0;
200 int bottomIdx = 0;
201 if ( !it.value().algorithm() )
202 continue;
203
204 const QgsProcessingParameterDefinitions parameters = it.value().algorithm()->parameterDefinitions();
205 for ( const QgsProcessingParameterDefinition *parameter : parameters )
206 {
207 if ( !( parameter->flags() & Qgis::ProcessingParameterFlag::Hidden ) )
208 {
209 QList<QgsProcessingModelChildParameterSource> sources;
210 if ( it.value().parameterSources().contains( parameter->name() ) )
211 sources = it.value().parameterSources()[parameter->name()];
212 for ( const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
213 {
214 const QList<LinkSource> sourceItems = linkSourcesForParameterValue( model, QVariant::fromValue( source ), it.value().childId(), context );
215 for ( const LinkSource &link : sourceItems )
216 {
217 if ( !link.item )
218 continue;
219 QgsModelArrowItem *arrow = nullptr;
220 if ( link.linkIndex == -1 )
221 {
222 arrow = new QgsModelArrowItem( link.item, QgsModelArrowItem::Marker::NoMarker, mChildAlgorithmItems.value( it.value().childId() ), parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge, parameter->isDestination() ? bottomIdx : topIdx, QgsModelArrowItem::Marker::Circle );
223 }
224 else
225 {
226 arrow = new QgsModelArrowItem( link.item, link.edge, link.linkIndex, true, QgsModelArrowItem::Marker::NoMarker, mChildAlgorithmItems.value( it.value().childId() ), parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge, parameter->isDestination() ? bottomIdx : topIdx, true, QgsModelArrowItem::Marker::NoMarker );
227 }
228 addItem( arrow );
229
230 if ( QgsModelChildAlgorithmGraphicItem *childAlgItem = mChildAlgorithmItems.value( it.value().childId() ) )
231 {
232 QString layerId = childAlgItem->results().inputs().value( parameter->name() ).toString();
233 addFeatureCountItemForArrow( arrow, layerId );
234 }
235 }
236 }
237 if ( parameter->isDestination() )
238 bottomIdx++;
239 else
240 topIdx++;
241 }
242 }
243 const QList<QgsProcessingModelChildDependency> dependencies = it.value().dependencies();
244 for ( const QgsProcessingModelChildDependency &depend : dependencies )
245 {
246 if ( depend.conditionalBranch.isEmpty() || !model->childAlgorithm( depend.childId ).algorithm() )
247 {
248 addItem( new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
249 }
250 else
251 {
252 // find branch link point
253 const QgsProcessingOutputDefinitions outputs = model->childAlgorithm( depend.childId ).algorithm()->outputDefinitions();
254 int i = 0;
255 bool found = false;
256 for ( const QgsProcessingOutputDefinition *output : outputs )
257 {
258 if ( output->name() == depend.conditionalBranch )
259 {
260 found = true;
261 break;
262 }
263 i++;
264 }
265 if ( found )
266 addItem( new QgsModelArrowItem( mChildAlgorithmItems.value( depend.childId ), Qt::BottomEdge, i, QgsModelArrowItem::Marker::Circle, mChildAlgorithmItems.value( it.value().childId() ), QgsModelArrowItem::Marker::ArrowHead ) );
267 }
268 }
269 }
270
271 // and finally the model outputs
272 for ( auto it = childAlgs.constBegin(); it != childAlgs.constEnd(); ++it )
273 {
274 const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
275 QMap<QString, QgsModelComponentGraphicItem *> outputItems;
276
277 // offsets from algorithm item needed to correctly place output items
278 // which does not have valid position assigned (https://github.com/qgis/QGIS/issues/48132)
279 QgsProcessingModelComponent *algItem = mChildAlgorithmItems[it.value().childId()]->component();
280 const double outputOffsetX = algItem->size().width();
281 double outputOffsetY = 1.5 * algItem->size().height();
282
283 for ( auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
284 {
285 QgsModelComponentGraphicItem *item = createOutputGraphicItem( model, outputIt.value().clone() );
286 addItem( item );
287 connect( item, &QgsModelComponentGraphicItem::requestModelRepaint, this, &QgsModelGraphicsScene::rebuildRequired );
288 connect( item, &QgsModelComponentGraphicItem::changed, this, &QgsModelGraphicsScene::componentChanged );
289 connect( item, &QgsModelComponentGraphicItem::aboutToChange, this, &QgsModelGraphicsScene::componentAboutToChange );
290
291 // if output added not at the same time as algorithm then it does not have
292 // valid position and will be placed at (0,0). We need to calculate better position.
293 // See https://github.com/qgis/QGIS/issues/48132.
294 QPointF pos = outputIt.value().position();
295 if ( pos.isNull() )
296 {
297 pos = algItem->position() + QPointF( outputOffsetX, outputOffsetY );
298 outputOffsetY += 1.5 * outputIt.value().size().height();
299 }
300 int idx = -1;
301 int i = 0;
302 // find the actual index of the linked output from the child algorithm it comes from
303 if ( it.value().algorithm() )
304 {
305 const QgsProcessingOutputDefinitions sourceChildAlgOutputs = it.value().algorithm()->outputDefinitions();
306 for ( const QgsProcessingOutputDefinition *childAlgOutput : sourceChildAlgOutputs )
307 {
308 if ( childAlgOutput->name() == outputIt.value().childOutputName() )
309 {
310 idx = i;
311 break;
312 }
313 i++;
314 }
315 }
316
317 item->setPos( pos );
318 item->component()->setPosition( pos );
319 outputItems.insert( outputIt.value().childOutputName(), item );
320 QgsModelArrowItem *arrow = new QgsModelArrowItem( mChildAlgorithmItems[it.value().childId()], Qt::BottomEdge, idx, QgsModelArrowItem::Marker::Circle, item, QgsModelArrowItem::Marker::Circle );
321 addItem( arrow );
322
323 if ( QgsModelChildAlgorithmGraphicItem *childItem = mChildAlgorithmItems.value( it.value().childId() ) )
324 {
325 QString layerId = childItem->results().outputs().value( outputIt.value().childOutputName() ).toString();
326 addFeatureCountItemForArrow( arrow, layerId );
327 }
328
329 addCommentItemForComponent( model, outputIt.value(), item );
330 }
331 mOutputItems.insert( it.value().childId(), outputItems );
332 }
333}
334
335QList<QgsModelComponentGraphicItem *> QgsModelGraphicsScene::selectedComponentItems()
336{
337 QList<QgsModelComponentGraphicItem *> componentItemList;
338
339 const QList<QGraphicsItem *> graphicsItemList = selectedItems();
340 for ( QGraphicsItem *item : graphicsItemList )
341 {
342 if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( item ) )
343 {
344 componentItemList.push_back( componentItem );
345 }
346 }
347
348 return componentItemList;
349}
350
351QgsModelComponentGraphicItem *QgsModelGraphicsScene::componentItemAt( QPointF position ) const
352{
353 //get a list of items which intersect the specified position, in descending z order
354 const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
355
356 for ( QGraphicsItem *graphicsItem : itemList )
357 {
358 if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( graphicsItem ) )
359 {
360 return componentItem;
361 }
362 }
363 return nullptr;
364}
365
366QgsModelComponentGraphicItem *QgsModelGraphicsScene::groupBoxItem( const QString &uuid )
367{
368 return mGroupBoxItems.value( uuid );
369}
370
371QgsModelChildAlgorithmGraphicItem *QgsModelGraphicsScene::childAlgorithmItem( const QString &childId )
372{
373 return mChildAlgorithmItems.value( childId );
374}
375
376QgsModelComponentGraphicItem *QgsModelGraphicsScene::parameterItem( const QString &name )
377{
378 return mParameterItems.value( name );
379}
380
381QgsModelComponentGraphicItem *QgsModelGraphicsScene::outputItem( const QString &childId, const QString &childOutputName )
382{
383 auto it = mOutputItems.constFind( childId );
384 if ( it == mOutputItems.constEnd() )
385 return nullptr;
386
387 auto outputIt = it->constFind( childOutputName );
388 if ( outputIt == it->constEnd() )
389 return nullptr;
390
391 return outputIt.value();
392}
393
394void QgsModelGraphicsScene::selectAll()
395{
396 //select all items in scene
397 QgsModelComponentGraphicItem *focusedItem = nullptr;
398 const QList<QGraphicsItem *> itemList = items();
399 for ( QGraphicsItem *graphicsItem : itemList )
400 {
401 if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( graphicsItem ) )
402 {
403 componentItem->setSelected( true );
404 if ( !focusedItem )
405 focusedItem = componentItem;
406 }
407 }
408 emit selectedItemChanged( focusedItem );
409}
410
411void QgsModelGraphicsScene::deselectAll()
412{
413 //we can't use QGraphicsScene::clearSelection, as that emits no signals
414 //and we don't know which items are being deselected
415 //instead, do the clear selection manually...
416 const QList<QGraphicsItem *> selectedItemList = selectedItems();
417 for ( QGraphicsItem *item : selectedItemList )
418 {
419 if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( item ) )
420 {
421 componentItem->setSelected( false );
422 }
423 }
424 emit selectedItemChanged( nullptr );
425}
426
427void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
428{
429 whileBlocking( this )->deselectAll();
430 if ( item )
431 {
432 item->setSelected( true );
433 }
434 emit selectedItemChanged( item );
435}
436
437void QgsModelGraphicsScene::setLastRunResult( const QgsProcessingModelResult &result, QgsProcessingContext &context )
438{
439 mLastResult = result;
440
441 const auto childResults = mLastResult.childResults();
442 for ( auto it = childResults.constBegin(); it != childResults.constEnd(); ++it )
443 {
444 if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
445 {
446 item->setResults( it.value() );
447 }
448 }
449
450 mLastResultCount.clear();
451 // Match inputs and outputs to corresponding layer and get feature counts if possible
452 for ( auto it = childResults.constBegin(); it != childResults.constEnd(); ++it )
453 {
454 QVariantMap inputs = childResults.value( it.key() ).inputs();
455 for ( auto inputIt = inputs.constBegin(); inputIt != inputs.constEnd(); inputIt++ )
456 {
457 if ( QgsMapLayer *resultMapLayer = QgsProcessingUtils::mapLayerFromString( inputs.value( inputIt.key() ).toString(), context, false ) )
458 {
459 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( resultMapLayer );
460 if ( vl && vl->featureCount() >= 0 )
461 {
462 mLastResultCount.insert( inputs.value( inputIt.key() ).toString(), vl->featureCount() );
463 }
464 }
465 }
466
467 QVariantMap outputs = childResults.value( it.key() ).outputs();
468 for ( auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); outputIt++ )
469 {
470 if ( QgsMapLayer *resultMapLayer = QgsProcessingUtils::mapLayerFromString( outputs.value( outputIt.key() ).toString(), context, false ) )
471 {
472 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( resultMapLayer );
473 if ( vl && vl->featureCount() >= 0 )
474 {
475 mLastResultCount.insert( outputs.value( outputIt.key() ).toString(), vl->featureCount() );
476 }
477 }
478 }
479 }
480
481 emit requestRebuildRequired();
482}
483
484QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model, const QVariant &value, const QString &childId, QgsProcessingContext &context ) const
485{
486 QList<QgsModelGraphicsScene::LinkSource> res;
487 if ( value.userType() == QMetaType::Type::QVariantList )
488 {
489 const QVariantList list = value.toList();
490 for ( const QVariant &v : list )
491 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
492 }
493 else if ( value.userType() == QMetaType::Type::QStringList )
494 {
495 const QStringList list = value.toStringList();
496 for ( const QString &v : list )
497 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
498 }
499 else if ( value.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() )
500 {
501 const QgsProcessingModelChildParameterSource source = value.value<QgsProcessingModelChildParameterSource>();
502 switch ( source.source() )
503 {
505 {
506 LinkSource l;
507 l.item = mParameterItems.value( source.parameterName() );
508 l.edge = Qt::BottomEdge;
509 l.linkIndex = 0;
510
511 res.append( l );
512 break;
513 }
515 {
516 if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
517 break;
518
519 const QgsProcessingOutputDefinitions outputs = model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions();
520 int i = 0;
521 for ( const QgsProcessingOutputDefinition *output : outputs )
522 {
523 if ( output->name() == source.outputName() )
524 break;
525 i++;
526 }
527 if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
528 {
529 LinkSource l;
530 l.item = mChildAlgorithmItems.value( source.outputChildId() );
531 l.edge = Qt::BottomEdge;
532
533 // do sanity check of linked index
534 if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
535 {
536 QString short_message = tr( "Check output links for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
537 QString long_message = tr( "Cannot link output for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
538 QString title( tr( "Algorithm link error" ) );
539 if ( messageBar() )
540 showWarning( const_cast<QString &>( short_message ), const_cast<QString &>( title ), const_cast<QString &>( long_message ) );
541 else
542 QgsMessageLog::logMessage( long_message, "QgsModelGraphicsScene", Qgis::MessageLevel::Warning, true );
543 break;
544 }
545
546 l.linkIndex = i;
547 res.append( l );
548 }
549
550 break;
551 }
552
554 {
555 const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, &context );
556 const QgsExpression exp( source.expression() );
557 const QSet<QString> vars = exp.referencedVariables();
558 for ( const QString &v : vars )
559 {
560 if ( variables.contains( v ) )
561 {
562 res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
563 }
564 }
565 break;
566 }
567
571 break;
572 }
573 }
574 return res;
575}
576
577void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model, const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
578{
579 if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
580 return;
581
582 QgsModelComponentGraphicItem *commentItem = createCommentGraphicItem( model, component.comment()->clone(), parentItem );
583 commentItem->setPos( component.comment()->position().x(), component.comment()->position().y() );
584 addItem( commentItem );
585 connect( commentItem, &QgsModelComponentGraphicItem::requestModelRepaint, this, &QgsModelGraphicsScene::rebuildRequired );
586 connect( commentItem, &QgsModelComponentGraphicItem::changed, this, &QgsModelGraphicsScene::componentChanged );
587 connect( commentItem, &QgsModelComponentGraphicItem::aboutToChange, this, &QgsModelGraphicsScene::componentAboutToChange );
588
589 auto arrow = std::make_unique<QgsModelArrowItem>( parentItem, QgsModelArrowItem::Circle, commentItem, QgsModelArrowItem::Circle );
590 arrow->setPenStyle( Qt::DotLine );
591 addItem( arrow.release() );
592}
593
594
595void QgsModelGraphicsScene::addFeatureCountItemForArrow( QgsModelArrowItem *arrow, const QString &layerId )
596{
597 if ( mFlags & FlagHideFeatureCount )
598 return;
599
600 if ( !mLastResultCount.contains( layerId ) )
601 {
602 return;
603 }
604
605 QString numberFeatureText = u"[%1]"_s.arg( mLastResultCount.value( layerId ) );
606 QgsModelDesignerFeatureCountGraphicItem *featureCount = new QgsModelDesignerFeatureCountGraphicItem( arrow, numberFeatureText );
607 addItem( featureCount );
608}
609
610
611QgsMessageBar *QgsModelGraphicsScene::messageBar() const
612{
613 return mMessageBar;
614}
615
616void QgsModelGraphicsScene::setMessageBar( QgsMessageBar *messageBar )
617{
618 mMessageBar = messageBar;
619}
620
621void QgsModelGraphicsScene::showWarning( const QString &shortMessage, const QString &title, const QString &longMessage, Qgis::MessageLevel level ) const
622{
623 QgsMessageBarItem *messageWidget = QgsMessageBar::createMessage( QString(), shortMessage );
624 QPushButton *detailsButton = new QPushButton( tr( "Details" ) );
625 connect( detailsButton, &QPushButton::clicked, detailsButton, [detailsButton, title, longMessage] {
626 QgsMessageViewer *dialog = new QgsMessageViewer( detailsButton );
627 dialog->setTitle( title );
628 dialog->setMessage( longMessage, Qgis::StringFormat::Html );
629 dialog->showMessage();
630 } );
631 messageWidget->layout()->addWidget( detailsButton );
632 mMessageBar->clearWidgets();
633 mMessageBar->pushWidget( messageWidget, level, 0 );
634}
635
636void QgsModelGraphicsScene::requestRebuildRequired()
637{
638 emit rebuildRequired();
639}
640
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:158
@ Warning
Warning message.
Definition qgis.h:160
@ Html
HTML message.
Definition qgis.h:175
@ ExpressionText
Parameter value is taken from a text with expressions, evaluated just before the algorithm runs.
Definition qgis.h:3938
@ ModelOutput
Parameter value is linked to an output parameter for the model.
Definition qgis.h:3939
@ ChildOutput
Parameter value is taken from an output generated by a child algorithm.
Definition qgis.h:3935
@ ModelParameter
Parameter value is taken from a parent model parameter.
Definition qgis.h:3934
@ StaticValue
Parameter value is a static value.
Definition qgis.h:3936
@ Expression
Parameter value is taken from an expression, evaluated just before the algorithm runs.
Definition qgis.h:3937
@ Hidden
Parameter is hidden and should not be shown to users.
Definition qgis.h:3850
Handles parsing and evaluation of expressions (formerly called "search strings").
Base class for all map layer types.
Definition qgsmaplayer.h:83
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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
A generic message view for displaying QGIS messages.
void setMessage(const QString &message, Qgis::StringFormat format) override
Sets message, it won't be displayed until.
void setTitle(const QString &title) override
Sets title for the messages.
void showMessage(bool blocking=true) override
display the message to the user and deletes itself
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.
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers=true, QgsProcessingUtils::LayerHint typeHint=QgsProcessingUtils::LayerHint::UnknownType, QgsProcessing::LayerOptionsFlags flags=QgsProcessing::LayerOptionsFlags())
Interprets a string as a map layer within the supplied context.
Represents a vector layer which manages a vector based dataset.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6854
QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions
List of processing parameters.
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.