Skip to content

Commit

Permalink
[FEATURE][processing] Allow copying/cut/paste of model components
Browse files Browse the repository at this point in the history
This commit allows users to copy and paste model components, both
within the same model and between different models
  • Loading branch information
nyalldawson committed Apr 14, 2020
1 parent 058a2b8 commit 47f96e2
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 5 deletions.
Expand Up @@ -38,7 +38,7 @@ Saves this group box to a QVariant.
.. seealso:: :py:func:`loadVariant`
%End

bool loadVariant( const QVariantMap &map );
bool loadVariant( const QVariantMap &map, bool ignoreUuid = false );
%Docstring
Loads this group box from a QVariantMap.

Expand Down
Expand Up @@ -51,6 +51,10 @@ QGraphicsScene subclass representing the model designer.
Constructor for QgsModelGraphicsScene with the specified ``parent`` object.
%End

QgsProcessingModelAlgorithm *model();

void setModel( QgsProcessingModelAlgorithm *model );

void setFlags( QgsModelGraphicsScene::Flags flags );
%Docstring
Sets the combination of ``flags`` controlling how the scene is rendered and behaves.
Expand Down
Expand Up @@ -80,6 +80,47 @@ Starts a macro command, containing a group of interactions in the view.
Ends a macro command, containing a group of interactions in the view.
%End


enum ClipboardOperation
{
ClipboardCut,
ClipboardCopy,
};

void copySelectedItems( ClipboardOperation operation );
%Docstring
Cuts or copies the selected items, respecting the specified ``operation``.

.. seealso:: :py:func:`copyItems`

.. seealso:: :py:func:`pasteItems`
%End

void copyItems( const QList< QgsModelComponentGraphicItem * > &items, ClipboardOperation operation );
%Docstring
Cuts or copies the a list of ``items``, respecting the specified ``operation``.

.. seealso:: :py:func:`copySelectedItems`

.. seealso:: :py:func:`pasteItems`
%End

enum PasteMode
{
PasteModeCursor,
PasteModeCenter,
PasteModeInPlace,
};

void pasteItems( PasteMode mode );
%Docstring
Pastes items from clipboard, using the specified ``mode``.

.. seealso:: :py:func:`copySelectedItems`

.. seealso:: :py:func:`hasItemsInClipboard`
%End

public slots:

void snapSelected();
Expand Down Expand Up @@ -120,6 +161,21 @@ Emitted when a macro command containing a group of interactions is started in th
void macroCommandEnded();
%Docstring
Emitted when a macro command containing a group of interactions in the view has ended.
%End

void beginCommand( const QString &text );
%Docstring
Emitted when an undo command is started in the view.
%End

void endCommand();
%Docstring
Emitted when an undo command in the view has ended.
%End

void deleteSelectedItems();
%Docstring
Emitted when the selected items should be deleted;
%End

};
Expand Down
5 changes: 3 additions & 2 deletions src/core/processing/models/qgsprocessingmodelgroupbox.cpp
Expand Up @@ -39,10 +39,11 @@ QVariant QgsProcessingModelGroupBox::toVariant() const
return map;
}

bool QgsProcessingModelGroupBox::loadVariant( const QVariantMap &map )
bool QgsProcessingModelGroupBox::loadVariant( const QVariantMap &map, bool ignoreUuid )
{
restoreCommonProperties( map );
mUuid = map.value( QStringLiteral( "uuid" ) ).toString();
if ( !ignoreUuid )
mUuid = map.value( QStringLiteral( "uuid" ) ).toString();
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/models/qgsprocessingmodelgroupbox.h
Expand Up @@ -51,7 +51,7 @@ class CORE_EXPORT QgsProcessingModelGroupBox : public QgsProcessingModelComponen
* Loads this group box from a QVariantMap.
* \see toVariant()
*/
bool loadVariant( const QVariantMap &map );
bool loadVariant( const QVariantMap &map, bool ignoreUuid = false );

/**
* Returns the unique ID associated with this group box.
Expand Down
46 changes: 46 additions & 0 deletions src/gui/processing/models/qgsmodeldesignerdialog.cpp
Expand Up @@ -166,6 +166,39 @@ QgsModelDesignerDialog::QgsModelDesignerDialog( QWidget *parent, Qt::WindowFlags
mMenuView->insertMenu( mActionZoomIn, mGroupMenu );
connect( mGroupMenu, &QMenu::aboutToShow, this, &QgsModelDesignerDialog::populateZoomToMenu );

//cut/copy/paste actions. Note these are not included in the ui file
//as ui files have no support for QKeySequence shortcuts
mActionCut = new QAction( tr( "Cu&t" ), this );
mActionCut->setShortcuts( QKeySequence::Cut );
mActionCut->setStatusTip( tr( "Cut" ) );
mActionCut->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditCut.svg" ) ) );
connect( mActionCut, &QAction::triggered, this, [ = ]
{
mView->copySelectedItems( QgsModelGraphicsView::ClipboardCut );
} );

mActionCopy = new QAction( tr( "&Copy" ), this );
mActionCopy->setShortcuts( QKeySequence::Copy );
mActionCopy->setStatusTip( tr( "Copy" ) );
mActionCopy->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditCopy.svg" ) ) );
connect( mActionCopy, &QAction::triggered, this, [ = ]
{
mView->copySelectedItems( QgsModelGraphicsView::ClipboardCopy );
} );

mActionPaste = new QAction( tr( "&Paste" ), this );
mActionPaste->setShortcuts( QKeySequence::Paste );
mActionPaste->setStatusTip( tr( "Paste" ) );
mActionPaste->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditPaste.svg" ) ) );
connect( mActionPaste, &QAction::triggered, this, [ = ]
{
mView->pasteItems( QgsModelGraphicsView::PasteModeCursor );
} );
mMenuEdit->insertAction( mActionDeleteComponents, mActionCut );
mMenuEdit->insertAction( mActionDeleteComponents, mActionCopy );
mMenuEdit->insertAction( mActionDeleteComponents, mActionPaste );
mMenuEdit->insertSeparator( mActionDeleteComponents );

QgsProcessingToolboxProxyModel::Filters filters = QgsProcessingToolboxProxyModel::FilterModeler;
if ( settings.value( QStringLiteral( "Processing/Configuration/SHOW_ALGORITHMS_KNOWN_ISSUES" ), false ).toBool() )
{
Expand Down Expand Up @@ -272,6 +305,18 @@ QgsModelDesignerDialog::QgsModelDesignerDialog( QWidget *parent, Qt::WindowFlags
mUndoStack->endMacro();
mIgnoreUndoStackChanges--;
} );
connect( mView, &QgsModelGraphicsView::beginCommand, this, [ = ]( const QString & text )
{
beginUndoCommand( text );
} );
connect( mView, &QgsModelGraphicsView::endCommand, this, [ = ]
{
endUndoCommand();
} );
connect( mView, &QgsModelGraphicsView::deleteSelectedItems, this, [ = ]
{
deleteSelected();
} );

connect( mActionAddGroupBox, &QAction::triggered, this, [ = ]
{
Expand Down Expand Up @@ -372,6 +417,7 @@ void QgsModelDesignerDialog::setModelScene( QgsModelGraphicsScene *scene )
mScene = scene;
mScene->setParent( this );
mScene->setChildAlgorithmResults( mChildResults );
mScene->setModel( mModel.get() );

mView->setModelScene( mScene );

Expand Down
3 changes: 3 additions & 0 deletions src/gui/processing/models/qgsmodeldesignerdialog.h
Expand Up @@ -170,6 +170,9 @@ class GUI_EXPORT QgsModelDesignerDialog : public QMainWindow, public Ui::QgsMode

QMenu *mGroupMenu = nullptr;

QAction *mActionCut = nullptr;
QAction *mActionCopy = nullptr;
QAction *mActionPaste = nullptr;
int mBlockUndoCommands = 0;
int mIgnoreUndoStackChanges = 0;

Expand Down
12 changes: 12 additions & 0 deletions src/gui/processing/models/qgsmodelgraphicsscene.cpp
Expand Up @@ -29,6 +29,16 @@ QgsModelGraphicsScene::QgsModelGraphicsScene( QObject *parent )
setItemIndexMethod( QGraphicsScene::NoIndex );
}

QgsProcessingModelAlgorithm *QgsModelGraphicsScene::model()
{
return mModel;
}

void QgsModelGraphicsScene::setModel( QgsProcessingModelAlgorithm *model )
{
mModel = model;
}

void QgsModelGraphicsScene::setFlag( QgsModelGraphicsScene::Flag flag, bool on )
{
if ( on )
Expand Down Expand Up @@ -154,6 +164,8 @@ void QgsModelGraphicsScene::createItems( QgsProcessingModelAlgorithm *model, Qgs
const QList< LinkSource > sourceItems = linkSourcesForParameterValue( model, QVariant::fromValue( source ), it.value().childId(), context );
for ( const LinkSource &link : sourceItems )
{
if ( !link.item )
continue;
QgsModelArrowItem *arrow = nullptr;
if ( link.linkIndex == -1 )
arrow = new QgsModelArrowItem( link.item, mChildAlgorithmItems.value( it.value().childId() ), parameter->isDestination() ? Qt::BottomEdge : Qt::TopEdge, parameter->isDestination() ? bottomIdx : topIdx );
Expand Down
6 changes: 6 additions & 0 deletions src/gui/processing/models/qgsmodelgraphicsscene.h
Expand Up @@ -70,6 +70,10 @@ class GUI_EXPORT QgsModelGraphicsScene : public QGraphicsScene
*/
QgsModelGraphicsScene( QObject *parent SIP_TRANSFERTHIS = nullptr );

QgsProcessingModelAlgorithm *model();

void setModel( QgsProcessingModelAlgorithm *model );

/**
* Sets the combination of \a flags controlling how the scene is rendered and behaves.
* \see setFlag()
Expand Down Expand Up @@ -210,6 +214,8 @@ class GUI_EXPORT QgsModelGraphicsScene : public QGraphicsScene

Flags mFlags = nullptr;

QgsProcessingModelAlgorithm *mModel = nullptr;

QMap< QString, QgsModelComponentGraphicItem * > mParameterItems;
QMap< QString, QgsModelChildAlgorithmGraphicItem * > mChildAlgorithmItems;
QMap< QString, QMap< QString, QgsModelComponentGraphicItem * > > mOutputItems;
Expand Down

0 comments on commit 47f96e2

Please sign in to comment.