Skip to content

Commit d2fcf11

Browse files
committed
[layouts] Add context menu entries for "copy" and "delete" item to
items list panel right click menu Refs #11581
1 parent c3e8401 commit d2fcf11

File tree

5 files changed

+97
-9
lines changed

5 files changed

+97
-9
lines changed

python/gui/layout/qgslayoutview.sip

+15
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,14 @@ class QgsLayoutView: QGraphicsView
195195
void copySelectedItems( ClipboardOperation operation );
196196
%Docstring
197197
Cuts or copies the selected items, respecting the specified ``operation``.
198+
.. seealso:: copyItems()
199+
.. seealso:: pasteItems()
200+
%End
201+
202+
void copyItems( const QList< QgsLayoutItem * > &items, ClipboardOperation operation );
203+
%Docstring
204+
Cuts or copies the a list of ``items``, respecting the specified ``operation``.
205+
.. seealso:: copySelectedItems()
198206
.. seealso:: pasteItems()
199207
%End
200208

@@ -356,6 +364,13 @@ class QgsLayoutView: QGraphicsView
356364
void deleteSelectedItems();
357365
%Docstring
358366
Deletes all selected items.
367+
.. seealso:: deleteItems()
368+
%End
369+
370+
void deleteItems( const QList< QgsLayoutItem * > &items );
371+
%Docstring
372+
Delete the specified ``items``.
373+
.. seealso:: deleteSelectedItems()
359374
%End
360375

361376
void groupSelectedItems();

src/app/layout/qgslayoutitemslistview.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
#include "qgslayout.h"
1818
#include "qgslayoutmodel.h"
1919
#include "qgslayoutdesignerdialog.h"
20+
#include "qgslayoutview.h"
2021
#include <QHeaderView>
22+
#include <QMouseEvent>
2123

2224
QgsLayoutItemsListView::QgsLayoutItemsListView( QWidget *parent, QgsLayoutDesignerDialog *designer )
2325
: QTreeView( parent )
@@ -58,6 +60,20 @@ void QgsLayoutItemsListView::showContextMenu( QPoint point )
5860

5961
QMenu *menu = new QMenu( this );
6062

63+
QAction *copyAction = new QAction( tr( "Copy Item" ), menu );
64+
connect( copyAction, &QAction::triggered, this, [this, item]()
65+
{
66+
mDesigner->view()->copyItems( QList< QgsLayoutItem * >() << item, QgsLayoutView::ClipboardCopy );
67+
} );
68+
menu->addAction( copyAction );
69+
QAction *deleteAction = new QAction( tr( "Delete Item" ), menu );
70+
connect( deleteAction, &QAction::triggered, this, [this, item]()
71+
{
72+
mDesigner->view()->deleteItems( QList< QgsLayoutItem * >() << item );
73+
} );
74+
menu->addAction( deleteAction );
75+
menu->addSeparator();
76+
6177
QAction *itemPropertiesAction = new QAction( tr( "Item Properties…" ), menu );
6278
connect( itemPropertiesAction, &QAction::triggered, this, [this, item]()
6379
{

src/gui/layout/qgslayoutview.cpp

+11-9
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,17 @@ void QgsLayoutView::resizeSelectedItems( QgsLayoutAligner::Resize resize )
282282

283283
void QgsLayoutView::copySelectedItems( QgsLayoutView::ClipboardOperation operation )
284284
{
285-
const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
285+
copyItems( currentLayout()->selectedLayoutItems(), operation );
286+
}
287+
288+
void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutView::ClipboardOperation operation )
289+
{
286290
QgsReadWriteContext context;
287291
QDomDocument doc;
288292
QDomElement documentElement = doc.createElement( QStringLiteral( "LayoutItemClipboard" ) );
289293
if ( operation == ClipboardCut )
290294
currentLayout()->undoStack()->beginMacro( tr( "Cut Items" ) );
291-
for ( QgsLayoutItem *item : selectedItems )
295+
for ( QgsLayoutItem *item : items )
292296
{
293297
// copy every child from a group
294298
if ( QgsLayoutItemGroup *itemGroup = qobject_cast<QgsLayoutItemGroup *>( item ) )
@@ -710,16 +714,14 @@ void QgsLayoutView::unlockAllItems()
710714

711715
void QgsLayoutView::deleteSelectedItems()
712716
{
713-
if ( !currentLayout() )
714-
{
715-
return;
716-
}
717-
718-
const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
717+
deleteItems( currentLayout()->selectedLayoutItems() );
718+
}
719719

720+
void QgsLayoutView::deleteItems( const QList<QgsLayoutItem *> &items )
721+
{
720722
currentLayout()->undoStack()->beginMacro( tr( "Delete Items" ) );
721723
//delete selected items
722-
for ( QgsLayoutItem *item : selectedItems )
724+
for ( QgsLayoutItem *item : items )
723725
{
724726
currentLayout()->removeLayoutItem( item );
725727
}

src/gui/layout/qgslayoutview.h

+15
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,18 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
225225

226226
/**
227227
* Cuts or copies the selected items, respecting the specified \a operation.
228+
* \see copyItems()
228229
* \see pasteItems()
229230
*/
230231
void copySelectedItems( ClipboardOperation operation );
231232

233+
/**
234+
* Cuts or copies the a list of \a items, respecting the specified \a operation.
235+
* \see copySelectedItems()
236+
* \see pasteItems()
237+
*/
238+
void copyItems( const QList< QgsLayoutItem * > &items, ClipboardOperation operation );
239+
232240
/**
233241
* Pastes items from clipboard, using the specified \a mode.
234242
*
@@ -396,9 +404,16 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
396404

397405
/**
398406
* Deletes all selected items.
407+
* \see deleteItems()
399408
*/
400409
void deleteSelectedItems();
401410

411+
/**
412+
* Delete the specified \a items.
413+
* \see deleteSelectedItems()
414+
*/
415+
void deleteItems( const QList< QgsLayoutItem * > &items );
416+
402417
/**
403418
* Groups all selected items.
404419
* \see ungroupSelectedItems()

tests/src/python/test_qgslayoutview.py

+40
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,36 @@ def testResize(self):
636636
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(19, 19, QgsUnitTypes.LayoutMillimeters))
637637
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.8, QgsUnitTypes.LayoutCentimeters))
638638

639+
def testDeleteItems(self):
640+
p = QgsProject()
641+
l = QgsLayout(p)
642+
643+
# add some items
644+
item1 = QgsLayoutItemLabel(l)
645+
item1.setText('label 1')
646+
l.addLayoutItem(item1)
647+
item2 = QgsLayoutItemLabel(l)
648+
item2.setText('label 2')
649+
l.addLayoutItem(item2)
650+
item3 = QgsLayoutItemLabel(l)
651+
item3.setText('label 2')
652+
l.addLayoutItem(item3)
653+
654+
view = QgsLayoutView()
655+
view.setCurrentLayout(l)
656+
count_before = len(l.items())
657+
view.deleteSelectedItems()
658+
self.assertEqual(len(l.items()), count_before)
659+
660+
item2.setSelected(True)
661+
view.deleteSelectedItems()
662+
self.assertEqual(len(l.items()), count_before - 1)
663+
self.assertIn(item1, l.items())
664+
self.assertIn(item3, l.items())
665+
view.deleteItems([item3])
666+
self.assertEqual(len(l.items()), count_before - 2)
667+
self.assertIn(item1, l.items())
668+
639669
def testCopyPaste(self):
640670
p = QgsProject()
641671
l = QgsLayout(p)
@@ -670,6 +700,16 @@ def testCopyPaste(self):
670700
self.assertIn(sip.cast(pasted[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))
671701
self.assertIn(sip.cast(pasted[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))
672702

703+
# copy specific item
704+
view.copyItems([item2], QgsLayoutView.ClipboardCopy)
705+
l2 = QgsLayout(p)
706+
view2 = QgsLayoutView()
707+
view2.setCurrentLayout(l2)
708+
pasted = view2.pasteItems(QgsLayoutView.PasteModeCursor)
709+
self.assertEqual(len(pasted), 1)
710+
self.assertIn(pasted[0], l2.items())
711+
self.assertEqual(sip.cast(pasted[0], QgsLayoutItemLabel).text(), 'label 2')
712+
673713
def testCutPaste(self):
674714
p = QgsProject()
675715
l = QgsLayout(p)

0 commit comments

Comments
 (0)