[layout] Add context menu entries for cutting/copying, and pasting items

Fixes #1830
This commit is contained in:
Nyall Dawson 2017-12-01 14:22:55 +10:00
parent b03ce047db
commit feec186fbf
6 changed files with 83 additions and 4 deletions

View File

@ -205,9 +205,17 @@ class QgsLayoutView: QGraphicsView
A list of pasted items is returned.
.. seealso:: copySelectedItems()
.. seealso:: hasItemsInClipboard()
:rtype: list of QgsLayoutItem
%End
bool hasItemsInClipboard() const;
%Docstring
Returns true if the current clipboard contains layout items.
.. seealso:: pasteItems()
:rtype: bool
%End
QPointF deltaForKeyEvent( QKeyEvent *event );
%Docstring
Returns the delta (in layout coordinates) by which to move items

View File

@ -76,6 +76,30 @@ QMenu *QgsLayoutAppMenuProvider::createContextMenu( QWidget *parent, QgsLayout *
if ( addedGroupAction )
menu->addSeparator();
QAction *copyAction = new QAction( tr( "Copy" ), menu );
connect( copyAction, &QAction::triggered, this, [this]()
{
mDesigner->view()->copySelectedItems( QgsLayoutView::ClipboardCopy );
} );
menu->addAction( copyAction );
QAction *cutAction = new QAction( tr( "Cut" ), menu );
connect( cutAction, &QAction::triggered, this, [this]()
{
mDesigner->view()->copySelectedItems( QgsLayoutView::ClipboardCut );
} );
menu->addAction( cutAction );
menu->addSeparator();
}
else if ( mDesigner->view()->hasItemsInClipboard() )
{
QAction *pasteAction = new QAction( tr( "Paste" ), menu );
connect( pasteAction, &QAction::triggered, this, [this]()
{
mDesigner->paste();
} );
menu->addAction( pasteAction );
menu->addSeparator();
}
// is a page under the mouse?

View File

@ -216,6 +216,18 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
*/
void refreshLayout();
/**
* Pastes items from the clipboard to the current layout.
* \see pasteInPlace()
*/
void paste();
/**
* Pastes item (in place) from the clipboard to the current layout.
* \see paste()
*/
void pasteInPlace();
signals:
/**
@ -247,9 +259,6 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
void dockVisibilityChanged( bool visible );
void undoRedoOccurredForItems( const QSet< QString > itemUuids );
void paste();
void pasteInPlace();
private:
static bool sInitializedRegistry;

View File

@ -365,6 +365,19 @@ QList< QgsLayoutItem * > QgsLayoutView::pasteItems( QgsLayoutView::PasteMode mod
return pastedItems;
}
bool QgsLayoutView::hasItemsInClipboard() const
{
QDomDocument doc;
QClipboard *clipboard = QApplication::clipboard();
if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral( "text/xml" ) ) ) )
{
QDomElement docElem = doc.documentElement();
if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
return true;
}
return false;
}
QPointF QgsLayoutView::deltaForKeyEvent( QKeyEvent *event )
{
// increment used for cursor key item movement

View File

@ -235,9 +235,16 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
* A list of pasted items is returned.
*
* \see copySelectedItems()
* \see hasItemsInClipboard()
*/
QList< QgsLayoutItem * > pasteItems( PasteMode mode );
/**
* Returns true if the current clipboard contains layout items.
* \see pasteItems()
*/
bool hasItemsInClipboard() const;
/**
* Returns the delta (in layout coordinates) by which to move items
* for the given key \a event.

View File

@ -23,8 +23,9 @@ from qgis.core import (QgsProject,
QgsLayoutSize,
QgsLayoutAligner)
from qgis.gui import QgsLayoutView
from qgis.PyQt.QtCore import QRectF
from qgis.PyQt.QtCore import QRectF, QMimeData, QByteArray
from qgis.PyQt.QtGui import QTransform
from qgis.PyQt.QtWidgets import QApplication
from qgis.PyQt.QtTest import QSignalSpy
from qgis.testing import start_app, unittest
@ -639,6 +640,12 @@ class TestQgsLayoutView(unittest.TestCase):
p = QgsProject()
l = QgsLayout(p)
# clear clipboard
mime_data = QMimeData()
mime_data.setData("text/xml", QByteArray())
clipboard = QApplication.clipboard()
clipboard.setMimeData(mime_data)
# add an item
item1 = QgsLayoutItemLabel(l)
item1.setText('label 1')
@ -651,8 +658,11 @@ class TestQgsLayoutView(unittest.TestCase):
view = QgsLayoutView()
view.setCurrentLayout(l)
self.assertFalse(view.hasItemsInClipboard())
view.copySelectedItems(QgsLayoutView.ClipboardCopy)
self.assertTrue(view.hasItemsInClipboard())
pasted = view.pasteItems(QgsLayoutView.PasteModeCursor)
self.assertEqual(len(pasted), 2)
self.assertIn(pasted[0], l.items())
@ -664,6 +674,12 @@ class TestQgsLayoutView(unittest.TestCase):
p = QgsProject()
l = QgsLayout(p)
# clear clipboard
mime_data = QMimeData()
mime_data.setData("text/xml", QByteArray())
clipboard = QApplication.clipboard()
clipboard.setMimeData(mime_data)
# add an item
item1 = QgsLayoutItemLabel(l)
item1.setText('label 1')
@ -676,9 +692,11 @@ class TestQgsLayoutView(unittest.TestCase):
view = QgsLayoutView()
view.setCurrentLayout(l)
self.assertFalse(view.hasItemsInClipboard())
len_before = len(l.items())
view.copySelectedItems(QgsLayoutView.ClipboardCut)
self.assertTrue(view.hasItemsInClipboard())
self.assertEqual(len(l.items()), len_before - 2)
pasted = view.pasteItems(QgsLayoutView.PasteModeCursor)