diff --git a/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in b/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in index cc2d319119d..9c0cbe9fad6 100644 --- a/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in +++ b/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in @@ -520,6 +520,12 @@ Ownership of ``output`` is transferred to the item. virtual bool canDeleteComponent(); + + QgsModelComponentGraphicItem *parentComponentItem() const; +%Docstring +Returns the parent model component item. +%End + protected: virtual QColor fillColor( State state ) const; diff --git a/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp b/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp index adbd3b3f6a8..b57ce8c6f7c 100644 --- a/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp +++ b/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp @@ -1421,5 +1421,10 @@ QgsProcessingModelComment *QgsModelCommentGraphicItem::modelComponent() return nullptr; } +QgsModelComponentGraphicItem *QgsModelCommentGraphicItem::parentComponentItem() const +{ + return mParentItem; +} + ///@endcond diff --git a/src/gui/processing/models/qgsmodelcomponentgraphicitem.h b/src/gui/processing/models/qgsmodelcomponentgraphicitem.h index 434498344fa..6174b2afac4 100644 --- a/src/gui/processing/models/qgsmodelcomponentgraphicitem.h +++ b/src/gui/processing/models/qgsmodelcomponentgraphicitem.h @@ -568,6 +568,12 @@ class GUI_EXPORT QgsModelCommentGraphicItem : public QgsModelComponentGraphicIte ~QgsModelCommentGraphicItem() override; void contextMenuEvent( QGraphicsSceneContextMenuEvent *event ) override; bool canDeleteComponent() override; + + /** + * Returns the parent model component item. + */ + QgsModelComponentGraphicItem *parentComponentItem() const; + protected: QColor fillColor( State state ) const override; diff --git a/src/gui/processing/models/qgsmodelgraphicsview.cpp b/src/gui/processing/models/qgsmodelgraphicsview.cpp index 22da37e08d8..022a530c2d2 100644 --- a/src/gui/processing/models/qgsmodelgraphicsview.cpp +++ b/src/gui/processing/models/qgsmodelgraphicsview.cpp @@ -486,13 +486,42 @@ void QgsModelGraphicsView::copyItems( const QList paramComponents; QList< QVariant > groupBoxComponents; QList< QVariant > algComponents; + + QList< QgsModelComponentGraphicItem * > selectedCommentParents; + QList< QgsProcessingModelOutput > selectedOutputs; + QList< QgsProcessingModelOutput > selectedOutputsComments; for ( QgsModelComponentGraphicItem *item : items ) { - if ( QgsProcessingModelParameter *param = dynamic_cast< QgsProcessingModelParameter * >( item->component() ) ) + if ( const QgsModelCommentGraphicItem *commentItem = dynamic_cast< QgsModelCommentGraphicItem * >( item ) ) { + selectedCommentParents << commentItem->parentComponentItem(); + if ( const QgsModelOutputGraphicItem *outputItem = dynamic_cast< QgsModelOutputGraphicItem * >( commentItem->parentComponentItem() ) ) + { + selectedOutputsComments << *( static_cast< const QgsProcessingModelOutput *>( outputItem->component() ) ); + } + } + else if ( const QgsModelOutputGraphicItem *outputItem = dynamic_cast< QgsModelOutputGraphicItem * >( item ) ) + { + selectedOutputs << *( static_cast< const QgsProcessingModelOutput *>( outputItem->component() ) ); + } + } + + for ( QgsModelComponentGraphicItem *item : items ) + { + if ( const QgsProcessingModelParameter *param = dynamic_cast< QgsProcessingModelParameter * >( item->component() ) ) + { + QgsProcessingModelParameter component = *param; + + // was comment selected? + if ( !selectedCommentParents.contains( item ) ) + { + // no, so drop comment + component.comment()->setDescription( QString() ); + } + QVariantMap paramDef; - paramDef.insert( QStringLiteral( "component" ), param->toVariant() ); - const QgsProcessingParameterDefinition *def = modelScene()->model()->parameterDefinition( param->parameterName() ); + paramDef.insert( QStringLiteral( "component" ), component.toVariant() ); + const QgsProcessingParameterDefinition *def = modelScene()->model()->parameterDefinition( component.parameterName() ); paramDef.insert( QStringLiteral( "definition" ), def->toVariantMap() ); paramComponents << paramDef; @@ -501,9 +530,54 @@ void QgsModelGraphicsView::copyItems( const QListtoVariant(); } - else if ( QgsProcessingModelChildAlgorithm *alg = dynamic_cast< QgsProcessingModelChildAlgorithm * >( item->component() ) ) + else if ( const QgsProcessingModelChildAlgorithm *alg = dynamic_cast< QgsProcessingModelChildAlgorithm * >( item->component() ) ) { - algComponents << alg->toVariant(); + QgsProcessingModelChildAlgorithm childAlg = *alg; + + // was comment selected? + if ( !selectedCommentParents.contains( item ) ) + { + // no, so drop comment + childAlg.comment()->setDescription( QString() ); + } + + // don't copy outputs which weren't selected either + QMap clipboardOutputs; + const QMap existingOutputs = childAlg.modelOutputs(); + for ( auto it = existingOutputs.constBegin(); it != existingOutputs.constEnd(); ++ it ) + { + bool found = false; + for ( const QgsProcessingModelOutput &candidate : selectedOutputs ) + { + if ( candidate.childId() == childAlg.childId() && candidate.name() == it.value().name() && candidate.childOutputName() == it.value().childOutputName() ) + { + found = true; + break; + } + } + if ( found ) + { + // should we also copy the comment? + bool commentFound = false; + for ( const QgsProcessingModelOutput &candidate : selectedOutputsComments ) + { + if ( candidate.childId() == childAlg.childId() && candidate.name() == it.value().name() && candidate.childOutputName() == it.value().childOutputName() ) + { + commentFound = true; + break; + } + } + + QgsProcessingModelOutput output = it.value(); + if ( !commentFound ) + output.comment()->setDescription( QString() ); + + clipboardOutputs.insert( it.key(), output ); + } + } + childAlg.setModelOutputs( clipboardOutputs ); + + algComponents << childAlg.toVariant(); } } QVariantMap components;