Skip to content

Commit

Permalink
[layouts] Add context menu entries for "copy" and "delete" item to
Browse files Browse the repository at this point in the history
items list panel right click menu

Refs #11581
  • Loading branch information
nyalldawson committed Dec 6, 2017
1 parent c3e8401 commit d2fcf11
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 9 deletions.
15 changes: 15 additions & 0 deletions python/gui/layout/qgslayoutview.sip
Expand Up @@ -195,6 +195,14 @@ class QgsLayoutView: QGraphicsView
void copySelectedItems( ClipboardOperation operation );
%Docstring
Cuts or copies the selected items, respecting the specified ``operation``.
.. seealso:: copyItems()
.. seealso:: pasteItems()
%End

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

Expand Down Expand Up @@ -356,6 +364,13 @@ class QgsLayoutView: QGraphicsView
void deleteSelectedItems();
%Docstring
Deletes all selected items.
.. seealso:: deleteItems()
%End

void deleteItems( const QList< QgsLayoutItem * > &items );
%Docstring
Delete the specified ``items``.
.. seealso:: deleteSelectedItems()
%End

void groupSelectedItems();
Expand Down
16 changes: 16 additions & 0 deletions src/app/layout/qgslayoutitemslistview.cpp
Expand Up @@ -17,7 +17,9 @@
#include "qgslayout.h"
#include "qgslayoutmodel.h"
#include "qgslayoutdesignerdialog.h"
#include "qgslayoutview.h"
#include <QHeaderView>
#include <QMouseEvent>

QgsLayoutItemsListView::QgsLayoutItemsListView( QWidget *parent, QgsLayoutDesignerDialog *designer )
: QTreeView( parent )
Expand Down Expand Up @@ -58,6 +60,20 @@ void QgsLayoutItemsListView::showContextMenu( QPoint point )

QMenu *menu = new QMenu( this );

QAction *copyAction = new QAction( tr( "Copy Item" ), menu );
connect( copyAction, &QAction::triggered, this, [this, item]()
{
mDesigner->view()->copyItems( QList< QgsLayoutItem * >() << item, QgsLayoutView::ClipboardCopy );
} );
menu->addAction( copyAction );
QAction *deleteAction = new QAction( tr( "Delete Item" ), menu );
connect( deleteAction, &QAction::triggered, this, [this, item]()
{
mDesigner->view()->deleteItems( QList< QgsLayoutItem * >() << item );
} );
menu->addAction( deleteAction );
menu->addSeparator();

QAction *itemPropertiesAction = new QAction( tr( "Item Properties…" ), menu );
connect( itemPropertiesAction, &QAction::triggered, this, [this, item]()
{
Expand Down
20 changes: 11 additions & 9 deletions src/gui/layout/qgslayoutview.cpp
Expand Up @@ -282,13 +282,17 @@ void QgsLayoutView::resizeSelectedItems( QgsLayoutAligner::Resize resize )

void QgsLayoutView::copySelectedItems( QgsLayoutView::ClipboardOperation operation )
{
const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
copyItems( currentLayout()->selectedLayoutItems(), operation );
}

void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutView::ClipboardOperation operation )
{
QgsReadWriteContext context;
QDomDocument doc;
QDomElement documentElement = doc.createElement( QStringLiteral( "LayoutItemClipboard" ) );
if ( operation == ClipboardCut )
currentLayout()->undoStack()->beginMacro( tr( "Cut Items" ) );
for ( QgsLayoutItem *item : selectedItems )
for ( QgsLayoutItem *item : items )
{
// copy every child from a group
if ( QgsLayoutItemGroup *itemGroup = qobject_cast<QgsLayoutItemGroup *>( item ) )
Expand Down Expand Up @@ -710,16 +714,14 @@ void QgsLayoutView::unlockAllItems()

void QgsLayoutView::deleteSelectedItems()
{
if ( !currentLayout() )
{
return;
}

const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
deleteItems( currentLayout()->selectedLayoutItems() );
}

void QgsLayoutView::deleteItems( const QList<QgsLayoutItem *> &items )
{
currentLayout()->undoStack()->beginMacro( tr( "Delete Items" ) );
//delete selected items
for ( QgsLayoutItem *item : selectedItems )
for ( QgsLayoutItem *item : items )
{
currentLayout()->removeLayoutItem( item );
}
Expand Down
15 changes: 15 additions & 0 deletions src/gui/layout/qgslayoutview.h
Expand Up @@ -225,10 +225,18 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView

/**
* Cuts or copies the selected items, respecting the specified \a operation.
* \see copyItems()
* \see pasteItems()
*/
void copySelectedItems( ClipboardOperation operation );

/**
* Cuts or copies the a list of \a items, respecting the specified \a operation.
* \see copySelectedItems()
* \see pasteItems()
*/
void copyItems( const QList< QgsLayoutItem * > &items, ClipboardOperation operation );

/**
* Pastes items from clipboard, using the specified \a mode.
*
Expand Down Expand Up @@ -396,9 +404,16 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView

/**
* Deletes all selected items.
* \see deleteItems()
*/
void deleteSelectedItems();

/**
* Delete the specified \a items.
* \see deleteSelectedItems()
*/
void deleteItems( const QList< QgsLayoutItem * > &items );

/**
* Groups all selected items.
* \see ungroupSelectedItems()
Expand Down
40 changes: 40 additions & 0 deletions tests/src/python/test_qgslayoutview.py
Expand Up @@ -636,6 +636,36 @@ def testResize(self):
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(19, 19, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.8, QgsUnitTypes.LayoutCentimeters))

def testDeleteItems(self):
p = QgsProject()
l = QgsLayout(p)

# add some items
item1 = QgsLayoutItemLabel(l)
item1.setText('label 1')
l.addLayoutItem(item1)
item2 = QgsLayoutItemLabel(l)
item2.setText('label 2')
l.addLayoutItem(item2)
item3 = QgsLayoutItemLabel(l)
item3.setText('label 2')
l.addLayoutItem(item3)

view = QgsLayoutView()
view.setCurrentLayout(l)
count_before = len(l.items())
view.deleteSelectedItems()
self.assertEqual(len(l.items()), count_before)

item2.setSelected(True)
view.deleteSelectedItems()
self.assertEqual(len(l.items()), count_before - 1)
self.assertIn(item1, l.items())
self.assertIn(item3, l.items())
view.deleteItems([item3])
self.assertEqual(len(l.items()), count_before - 2)
self.assertIn(item1, l.items())

def testCopyPaste(self):
p = QgsProject()
l = QgsLayout(p)
Expand Down Expand Up @@ -670,6 +700,16 @@ def testCopyPaste(self):
self.assertIn(sip.cast(pasted[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))
self.assertIn(sip.cast(pasted[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))

# copy specific item
view.copyItems([item2], QgsLayoutView.ClipboardCopy)
l2 = QgsLayout(p)
view2 = QgsLayoutView()
view2.setCurrentLayout(l2)
pasted = view2.pasteItems(QgsLayoutView.PasteModeCursor)
self.assertEqual(len(pasted), 1)
self.assertIn(pasted[0], l2.items())
self.assertEqual(sip.cast(pasted[0], QgsLayoutItemLabel).text(), 'label 2')

def testCutPaste(self):
p = QgsProject()
l = QgsLayout(p)
Expand Down

0 comments on commit d2fcf11

Please sign in to comment.