QGIS API Documentation 3.99.0-Master (357b655ed83)
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.key(), 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
381void QgsModelGraphicsScene::selectAll()
382{
383 //select all items in scene
384 QgsModelComponentGraphicItem *focusedItem = nullptr;
385 const QList<QGraphicsItem *> itemList = items();
386 for ( QGraphicsItem *graphicsItem : itemList )
387 {
388 if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( graphicsItem ) )
389 {
390 componentItem->setSelected( true );
391 if ( !focusedItem )
392 focusedItem = componentItem;
393 }
394 }
395 emit selectedItemChanged( focusedItem );
396}
397
398void QgsModelGraphicsScene::deselectAll()
399{
400 //we can't use QGraphicsScene::clearSelection, as that emits no signals
401 //and we don't know which items are being deselected
402 //instead, do the clear selection manually...
403 const QList<QGraphicsItem *> selectedItemList = selectedItems();
404 for ( QGraphicsItem *item : selectedItemList )
405 {
406 if ( QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( item ) )
407 {
408 componentItem->setSelected( false );
409 }
410 }
411 emit selectedItemChanged( nullptr );
412}
413
414void QgsModelGraphicsScene::setSelectedItem( QgsModelComponentGraphicItem *item )
415{
416 whileBlocking( this )->deselectAll();
417 if ( item )
418 {
419 item->setSelected( true );
420 }
421 emit selectedItemChanged( item );
422}
423
424void QgsModelGraphicsScene::setLastRunResult( const QgsProcessingModelResult &result, QgsProcessingContext &context )
425{
426 mLastResult = result;
427
428 const auto childResults = mLastResult.childResults();
429 for ( auto it = childResults.constBegin(); it != childResults.constEnd(); ++it )
430 {
431 if ( QgsModelChildAlgorithmGraphicItem *item = mChildAlgorithmItems.value( it.key() ) )
432 {
433 item->setResults( it.value() );
434 }
435 }
436
437 mLastResultCount.clear();
438 // Match inputs and outputs to corresponding layer and get feature counts if possible
439 for ( auto it = childResults.constBegin(); it != childResults.constEnd(); ++it )
440 {
441 QVariantMap inputs = childResults.value( it.key() ).inputs();
442 for ( auto inputIt = inputs.constBegin(); inputIt != inputs.constEnd(); inputIt++ )
443 {
444 if ( QgsMapLayer *resultMapLayer = QgsProcessingUtils::mapLayerFromString( inputs.value( inputIt.key() ).toString(), context, false ) )
445 {
446 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( resultMapLayer );
447 if ( vl && vl->featureCount() >= 0 )
448 {
449 mLastResultCount.insert( inputs.value( inputIt.key() ).toString(), vl->featureCount() );
450 }
451 }
452 }
453
454 QVariantMap outputs = childResults.value( it.key() ).outputs();
455 for ( auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); outputIt++ )
456 {
457 if ( QgsMapLayer *resultMapLayer = QgsProcessingUtils::mapLayerFromString( outputs.value( outputIt.key() ).toString(), context, false ) )
458 {
459 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( resultMapLayer );
460 if ( vl && vl->featureCount() >= 0 )
461 {
462 mLastResultCount.insert( outputs.value( outputIt.key() ).toString(), vl->featureCount() );
463 }
464 }
465 }
466 }
467
468 emit requestRebuildRequired();
469}
470
471QList<QgsModelGraphicsScene::LinkSource> QgsModelGraphicsScene::linkSourcesForParameterValue( QgsProcessingModelAlgorithm *model, const QVariant &value, const QString &childId, QgsProcessingContext &context ) const
472{
473 QList<QgsModelGraphicsScene::LinkSource> res;
474 if ( value.userType() == QMetaType::Type::QVariantList )
475 {
476 const QVariantList list = value.toList();
477 for ( const QVariant &v : list )
478 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
479 }
480 else if ( value.userType() == QMetaType::Type::QStringList )
481 {
482 const QStringList list = value.toStringList();
483 for ( const QString &v : list )
484 res.append( linkSourcesForParameterValue( model, v, childId, context ) );
485 }
486 else if ( value.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() )
487 {
488 const QgsProcessingModelChildParameterSource source = value.value<QgsProcessingModelChildParameterSource>();
489 switch ( source.source() )
490 {
492 {
493 LinkSource l;
494 l.item = mParameterItems.value( source.parameterName() );
495 l.edge = Qt::BottomEdge;
496 l.linkIndex = 0;
497
498 res.append( l );
499 break;
500 }
502 {
503 if ( !model->childAlgorithm( source.outputChildId() ).algorithm() )
504 break;
505
506 const QgsProcessingOutputDefinitions outputs = model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions();
507 int i = 0;
508 for ( const QgsProcessingOutputDefinition *output : outputs )
509 {
510 if ( output->name() == source.outputName() )
511 break;
512 i++;
513 }
514 if ( mChildAlgorithmItems.contains( source.outputChildId() ) )
515 {
516 LinkSource l;
517 l.item = mChildAlgorithmItems.value( source.outputChildId() );
518 l.edge = Qt::BottomEdge;
519
520 // do sanity check of linked index
521 if ( i >= model->childAlgorithm( source.outputChildId() ).algorithm()->outputDefinitions().length() )
522 {
523 QString short_message = tr( "Check output links for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
524 QString long_message = tr( "Cannot link output for alg: %1" ).arg( model->childAlgorithm( source.outputChildId() ).algorithm()->name() );
525 QString title( tr( "Algorithm link error" ) );
526 if ( messageBar() )
527 showWarning( const_cast<QString &>( short_message ), const_cast<QString &>( title ), const_cast<QString &>( long_message ) );
528 else
529 QgsMessageLog::logMessage( long_message, "QgsModelGraphicsScene", Qgis::MessageLevel::Warning, true );
530 break;
531 }
532
533 l.linkIndex = i;
534 res.append( l );
535 }
536
537 break;
538 }
539
541 {
542 const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model->variablesForChildAlgorithm( childId, &context );
543 const QgsExpression exp( source.expression() );
544 const QSet<QString> vars = exp.referencedVariables();
545 for ( const QString &v : vars )
546 {
547 if ( variables.contains( v ) )
548 {
549 res.append( linkSourcesForParameterValue( model, QVariant::fromValue( variables.value( v ).source ), childId, context ) );
550 }
551 }
552 break;
553 }
554
558 break;
559 }
560 }
561 return res;
562}
563
564void QgsModelGraphicsScene::addCommentItemForComponent( QgsProcessingModelAlgorithm *model, const QgsProcessingModelComponent &component, QgsModelComponentGraphicItem *parentItem )
565{
566 if ( mFlags & FlagHideComments || !component.comment() || component.comment()->description().isEmpty() )
567 return;
568
569 QgsModelComponentGraphicItem *commentItem = createCommentGraphicItem( model, component.comment()->clone(), parentItem );
570 commentItem->setPos( component.comment()->position().x(), component.comment()->position().y() );
571 addItem( commentItem );
572 connect( commentItem, &QgsModelComponentGraphicItem::requestModelRepaint, this, &QgsModelGraphicsScene::rebuildRequired );
573 connect( commentItem, &QgsModelComponentGraphicItem::changed, this, &QgsModelGraphicsScene::componentChanged );
574 connect( commentItem, &QgsModelComponentGraphicItem::aboutToChange, this, &QgsModelGraphicsScene::componentAboutToChange );
575
576 auto arrow = std::make_unique<QgsModelArrowItem>( parentItem, QgsModelArrowItem::Circle, commentItem, QgsModelArrowItem::Circle );
577 arrow->setPenStyle( Qt::DotLine );
578 addItem( arrow.release() );
579}
580
581
582void QgsModelGraphicsScene::addFeatureCountItemForArrow( QgsModelArrowItem *arrow, const QString &layerId )
583{
584 if ( mFlags & FlagHideFeatureCount )
585 return;
586
587 if ( !mLastResultCount.contains( layerId ) )
588 {
589 return;
590 }
591
592 QString numberFeatureText = u"[%1]"_s.arg( mLastResultCount.value( layerId ) );
593 QgsModelDesignerFeatureCountGraphicItem *featureCount = new QgsModelDesignerFeatureCountGraphicItem( arrow, numberFeatureText );
594 addItem( featureCount );
595}
596
597
598QgsMessageBar *QgsModelGraphicsScene::messageBar() const
599{
600 return mMessageBar;
601}
602
603void QgsModelGraphicsScene::setMessageBar( QgsMessageBar *messageBar )
604{
605 mMessageBar = messageBar;
606}
607
608void QgsModelGraphicsScene::showWarning( const QString &shortMessage, const QString &title, const QString &longMessage, Qgis::MessageLevel level ) const
609{
610 QgsMessageBarItem *messageWidget = QgsMessageBar::createMessage( QString(), shortMessage );
611 QPushButton *detailsButton = new QPushButton( tr( "Details" ) );
612 connect( detailsButton, &QPushButton::clicked, detailsButton, [detailsButton, title, longMessage] {
613 QgsMessageViewer *dialog = new QgsMessageViewer( detailsButton );
614 dialog->setTitle( title );
615 dialog->setMessage( longMessage, QgsMessageOutput::MessageHtml );
616 dialog->showMessage();
617 } );
618 messageWidget->layout()->addWidget( detailsButton );
619 mMessageBar->clearWidgets();
620 mMessageBar->pushWidget( messageWidget, level, 0 );
621}
622
623void QgsModelGraphicsScene::requestRebuildRequired()
624{
625 emit rebuildRequired();
626}
627
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:159
@ Warning
Warning message.
Definition qgis.h:161
@ ExpressionText
Parameter value is taken from a text with expressions, evaluated just before the algorithm runs.
Definition qgis.h:3923
@ ModelOutput
Parameter value is linked to an output parameter for the model.
Definition qgis.h:3924
@ ChildOutput
Parameter value is taken from an output generated by a child algorithm.
Definition qgis.h:3920
@ ModelParameter
Parameter value is taken from a parent model parameter.
Definition qgis.h:3919
@ StaticValue
Parameter value is a static value.
Definition qgis.h:3921
@ Expression
Parameter value is taken from an expression, evaluated just before the algorithm runs.
Definition qgis.h:3922
@ Hidden
Parameter is hidden and should not be shown to users.
Definition qgis.h:3835
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())
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
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:6839
QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions
List of processing parameters.
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.