mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[layouts] Fix multiframe items (tables, html) cannot be pasted
Fixes #10456, #17882
This commit is contained in:
parent
cbe6416278
commit
7a2ab1cc7c
@ -180,8 +180,33 @@ which deferred z-order updates.
|
||||
Returns the layout item with matching ``uuid`` unique identifier, or a None
|
||||
if a matching item could not be found.
|
||||
|
||||
If ``includeTemplateUuids`` is true, then item's :py:func:`QgsLayoutItem.templateUuid()`
|
||||
will also be tested when trying to match the uuid.
|
||||
If ``includeTemplateUuids`` is true, then item's template UUID
|
||||
will also be tested when trying to match the uuid. This may differ from the item's UUID
|
||||
for items which have been added to an existing layout from a template. In this case
|
||||
the template UUID returns the original item UUID at the time the template was created,
|
||||
vs the item's uuid() which returns the current instance of the item's unique identifier.
|
||||
Note that template UUIDs are only available while a layout is being restored from XML.
|
||||
|
||||
.. seealso:: :py:func:`itemByTemplateUuid`
|
||||
|
||||
.. seealso:: :py:func:`multiFrameByUuid`
|
||||
|
||||
.. seealso:: :py:func:`itemById`
|
||||
%End
|
||||
|
||||
QgsLayoutItem *itemByTemplateUuid( const QString &uuid ) const;
|
||||
%Docstring
|
||||
Returns the layout item with matching template ``uuid`` unique identifier, or a None
|
||||
if a matching item could not be found. Unlike itemByUuid(), this method ONLY checks
|
||||
template UUIDs for a match.
|
||||
|
||||
Template UUIDs are valid only for items which have been added to an existing layout from a template. In this case
|
||||
the template UUID is the original item UUID at the time the template was created,
|
||||
vs the item's uuid() which returns the current instance of the item's unique identifier.
|
||||
|
||||
Note that template UUIDs are only available while a layout is being restored from XML.
|
||||
|
||||
.. seealso:: :py:func:`itemByUuid`
|
||||
|
||||
.. seealso:: :py:func:`multiFrameByUuid`
|
||||
|
||||
@ -203,7 +228,11 @@ Returns the layout multiframe with matching ``uuid`` unique identifier, or a Non
|
||||
if a matching multiframe could not be found.
|
||||
|
||||
If ``includeTemplateUuids`` is true, then the multiframe's :py:func:`QgsLayoutMultiFrame.templateUuid()`
|
||||
will also be tested when trying to match the uuid.
|
||||
will also be tested when trying to match the uuid. Template UUIDs are valid only for items
|
||||
which have been added to an existing layout from a template. In this case
|
||||
the template UUID is the original item UUID at the time the template was created,
|
||||
vs the item's uuid() which returns the current instance of the item's unique identifier.
|
||||
Note that template UUIDs are only available while a layout is being restored from XML.
|
||||
|
||||
.. seealso:: :py:func:`itemByUuid`
|
||||
%End
|
||||
|
@ -217,18 +217,6 @@ upon creation.
|
||||
.. seealso:: :py:func:`id`
|
||||
|
||||
.. seealso:: :py:func:`setId`
|
||||
|
||||
.. seealso:: :py:func:`templateUuid`
|
||||
%End
|
||||
|
||||
QString templateUuid() const;
|
||||
%Docstring
|
||||
Returns the item's original identification string. This may differ from the item's uuid()
|
||||
for items which have been added to an existing layout from a template. In this case
|
||||
templateUuid() returns the original item UUID at the time the template was created,
|
||||
while uuid() returns the current instance of the item's unique identifier.
|
||||
|
||||
.. seealso:: :py:func:`uuid`
|
||||
%End
|
||||
|
||||
QString id() const;
|
||||
|
@ -95,18 +95,6 @@ upon creation.
|
||||
.. note::
|
||||
|
||||
There is no corresponding setter for the uuid - it's created automatically.
|
||||
|
||||
.. seealso:: :py:func:`templateUuid`
|
||||
%End
|
||||
|
||||
QString templateUuid() const;
|
||||
%Docstring
|
||||
Returns the multiframe's original identification string. This may differ from the multiframes's uuid()
|
||||
for multiframes which have been added to an existing layout from a template. In this case
|
||||
templateUuid() returns the original UUID at the time the template was created,
|
||||
while uuid() returns the current instance of the multiframes's unique identifier.
|
||||
|
||||
.. seealso:: :py:func:`uuid`
|
||||
%End
|
||||
|
||||
virtual QSizeF totalSize() const = 0;
|
||||
|
@ -238,7 +238,20 @@ QgsLayoutItem *QgsLayout::itemByUuid( const QString &uuid, bool includeTemplateU
|
||||
{
|
||||
if ( item->uuid() == uuid )
|
||||
return item;
|
||||
else if ( includeTemplateUuids && item->templateUuid() == uuid )
|
||||
else if ( includeTemplateUuids && item->mTemplateUuid == uuid )
|
||||
return item;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QgsLayoutItem *QgsLayout::itemByTemplateUuid( const QString &uuid ) const
|
||||
{
|
||||
QList<QgsLayoutItem *> itemList;
|
||||
layoutItems( itemList );
|
||||
for ( QgsLayoutItem *item : qgis::as_const( itemList ) )
|
||||
{
|
||||
if ( item->mTemplateUuid == uuid )
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -265,7 +278,7 @@ QgsLayoutMultiFrame *QgsLayout::multiFrameByUuid( const QString &uuid, bool incl
|
||||
{
|
||||
if ( mf->uuid() == uuid )
|
||||
return mf;
|
||||
else if ( includeTemplateUuids && mf->templateUuid() == uuid )
|
||||
else if ( includeTemplateUuids && mf->mTemplateUuid == uuid )
|
||||
return mf;
|
||||
}
|
||||
|
||||
@ -1040,6 +1053,15 @@ QList< QgsLayoutItem * > QgsLayout::addItemsFromXml( const QDomElement &parentEl
|
||||
mf->finalizeRestoreFromXml();
|
||||
}
|
||||
|
||||
for ( QgsLayoutItem *item : qgis::as_const( newItems ) )
|
||||
{
|
||||
item->mTemplateUuid.clear();
|
||||
}
|
||||
for ( QgsLayoutMultiFrame *mf : qgis::as_const( newMultiFrames ) )
|
||||
{
|
||||
mf->mTemplateUuid.clear();
|
||||
}
|
||||
|
||||
//Since this function adds items in an order which isn't the z-order, and each item is added to end of
|
||||
//z order list in turn, it will now be inconsistent with the actual order of items in the scene.
|
||||
//Make sure z order list matches the actual order of items in the scene.
|
||||
|
@ -247,14 +247,36 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
|
||||
* Returns the layout item with matching \a uuid unique identifier, or a nullptr
|
||||
* if a matching item could not be found.
|
||||
*
|
||||
* If \a includeTemplateUuids is true, then item's QgsLayoutItem::templateUuid()
|
||||
* will also be tested when trying to match the uuid.
|
||||
* If \a includeTemplateUuids is true, then item's template UUID
|
||||
* will also be tested when trying to match the uuid. This may differ from the item's UUID
|
||||
* for items which have been added to an existing layout from a template. In this case
|
||||
* the template UUID returns the original item UUID at the time the template was created,
|
||||
* vs the item's uuid() which returns the current instance of the item's unique identifier.
|
||||
* Note that template UUIDs are only available while a layout is being restored from XML.
|
||||
*
|
||||
* \see itemByTemplateUuid()
|
||||
* \see multiFrameByUuid()
|
||||
* \see itemById()
|
||||
*/
|
||||
QgsLayoutItem *itemByUuid( const QString &uuid, bool includeTemplateUuids = false ) const;
|
||||
|
||||
/**
|
||||
* Returns the layout item with matching template \a uuid unique identifier, or a nullptr
|
||||
* if a matching item could not be found. Unlike itemByUuid(), this method ONLY checks
|
||||
* template UUIDs for a match.
|
||||
*
|
||||
* Template UUIDs are valid only for items which have been added to an existing layout from a template. In this case
|
||||
* the template UUID is the original item UUID at the time the template was created,
|
||||
* vs the item's uuid() which returns the current instance of the item's unique identifier.
|
||||
*
|
||||
* Note that template UUIDs are only available while a layout is being restored from XML.
|
||||
*
|
||||
* \see itemByUuid()
|
||||
* \see multiFrameByUuid()
|
||||
* \see itemById()
|
||||
*/
|
||||
QgsLayoutItem *itemByTemplateUuid( const QString &uuid ) const;
|
||||
|
||||
/**
|
||||
* Returns a layout item given its \a id.
|
||||
* Since item IDs are not necessarely unique, this function returns the first matching
|
||||
@ -268,7 +290,11 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
|
||||
* if a matching multiframe could not be found.
|
||||
*
|
||||
* If \a includeTemplateUuids is true, then the multiframe's QgsLayoutMultiFrame::templateUuid()
|
||||
* will also be tested when trying to match the uuid.
|
||||
* will also be tested when trying to match the uuid. Template UUIDs are valid only for items
|
||||
* which have been added to an existing layout from a template. In this case
|
||||
* the template UUID is the original item UUID at the time the template was created,
|
||||
* vs the item's uuid() which returns the current instance of the item's unique identifier.
|
||||
* Note that template UUIDs are only available while a layout is being restored from XML.
|
||||
*
|
||||
* \see itemByUuid()
|
||||
*/
|
||||
|
@ -243,19 +243,9 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
|
||||
* \note There is no corresponding setter for the uuid - it's created automatically.
|
||||
* \see id()
|
||||
* \see setId()
|
||||
* \see templateUuid()
|
||||
*/
|
||||
virtual QString uuid() const { return mUuid; }
|
||||
|
||||
/**
|
||||
* Returns the item's original identification string. This may differ from the item's uuid()
|
||||
* for items which have been added to an existing layout from a template. In this case
|
||||
* templateUuid() returns the original item UUID at the time the template was created,
|
||||
* while uuid() returns the current instance of the item's unique identifier.
|
||||
* \see uuid()
|
||||
*/
|
||||
QString templateUuid() const { return mTemplateUuid; }
|
||||
|
||||
/**
|
||||
* Returns the item's ID name. This is not necessarily unique, and duplicate ID names may exist
|
||||
* for a layout.
|
||||
@ -1083,6 +1073,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
|
||||
|
||||
friend class TestQgsLayoutItem;
|
||||
friend class TestQgsLayoutView;
|
||||
friend class QgsLayout;
|
||||
friend class QgsLayoutItemGroup;
|
||||
friend class QgsCompositionConverter;
|
||||
};
|
||||
|
@ -303,9 +303,24 @@ void QgsLayoutMultiFrame::finalizeRestoreFromXml()
|
||||
{
|
||||
for ( int i = 0; i < mFrameUuids.count(); ++i )
|
||||
{
|
||||
const QString uuid = mFrameUuids.at( i ).isEmpty() ? mFrameTemplateUuids.at( i ) : mFrameUuids.at( i );
|
||||
QgsLayoutItem *item = mLayout->itemByUuid( uuid, true );
|
||||
if ( QgsLayoutFrame *frame = qobject_cast< QgsLayoutFrame * >( item ) )
|
||||
QgsLayoutFrame *frame = nullptr;
|
||||
const QString uuid = mFrameUuids.at( i );
|
||||
if ( !uuid.isEmpty() )
|
||||
{
|
||||
QgsLayoutItem *item = mLayout->itemByUuid( uuid, true );
|
||||
frame = qobject_cast< QgsLayoutFrame * >( item );
|
||||
}
|
||||
if ( !frame )
|
||||
{
|
||||
const QString templateUuid = mFrameTemplateUuids.at( i );
|
||||
if ( !templateUuid.isEmpty() )
|
||||
{
|
||||
QgsLayoutItem *item = mLayout->itemByTemplateUuid( templateUuid );
|
||||
frame = qobject_cast< QgsLayoutFrame * >( item );
|
||||
}
|
||||
}
|
||||
|
||||
if ( frame )
|
||||
{
|
||||
addFrame( frame );
|
||||
}
|
||||
|
@ -128,19 +128,9 @@ class CORE_EXPORT QgsLayoutMultiFrame: public QgsLayoutObject, public QgsLayoutU
|
||||
* Returns the multiframe identification string. This is a unique random string set for the multiframe
|
||||
* upon creation.
|
||||
* \note There is no corresponding setter for the uuid - it's created automatically.
|
||||
* \see templateUuid()
|
||||
*/
|
||||
QString uuid() const { return mUuid; }
|
||||
|
||||
/**
|
||||
* Returns the multiframe's original identification string. This may differ from the multiframes's uuid()
|
||||
* for multiframes which have been added to an existing layout from a template. In this case
|
||||
* templateUuid() returns the original UUID at the time the template was created,
|
||||
* while uuid() returns the current instance of the multiframes's unique identifier.
|
||||
* \see uuid()
|
||||
*/
|
||||
QString templateUuid() const { return mTemplateUuid; }
|
||||
|
||||
/**
|
||||
* Returns the total size of the multiframe's content, in layout units.
|
||||
*/
|
||||
@ -447,6 +437,7 @@ class CORE_EXPORT QgsLayoutMultiFrame: public QgsLayoutObject, public QgsLayoutU
|
||||
QString mUuid;
|
||||
QString mTemplateUuid;
|
||||
friend class QgsLayoutFrame;
|
||||
friend class QgsLayout;
|
||||
};
|
||||
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include "qgslayoutview.h"
|
||||
#include "qgslayout.h"
|
||||
#include "qgslayoutframe.h"
|
||||
#include "qgslayoutmultiframe.h"
|
||||
#include "qgslayoutviewtool.h"
|
||||
#include "qgslayoutviewmouseevent.h"
|
||||
#include "qgslayoutviewtooltemporarykeypan.h"
|
||||
@ -149,7 +151,6 @@ void QgsLayoutView::setTool( QgsLayoutViewTool *tool )
|
||||
tool->activate();
|
||||
mTool = tool;
|
||||
connect( mTool, &QgsLayoutViewTool::itemFocused, this, &QgsLayoutView::itemFocused );
|
||||
|
||||
emit toolSet( mTool );
|
||||
}
|
||||
|
||||
@ -320,6 +321,9 @@ void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutVie
|
||||
QDomElement documentElement = doc.createElement( QStringLiteral( "LayoutItemClipboard" ) );
|
||||
if ( operation == ClipboardCut )
|
||||
currentLayout()->undoStack()->beginMacro( tr( "Cut Items" ) );
|
||||
|
||||
QSet< QgsLayoutMultiFrame * > copiedMultiFrames;
|
||||
|
||||
for ( QgsLayoutItem *item : items )
|
||||
{
|
||||
// copy every child from a group
|
||||
@ -331,6 +335,15 @@ void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutVie
|
||||
groupedItem->writeXml( documentElement, doc, context );
|
||||
}
|
||||
}
|
||||
else if ( QgsLayoutFrame *frame = qobject_cast<QgsLayoutFrame *>( item ) )
|
||||
{
|
||||
// copy multiframe too
|
||||
if ( !copiedMultiFrames.contains( frame->multiFrame() ) )
|
||||
{
|
||||
frame->multiFrame()->writeXml( documentElement, doc, context );
|
||||
copiedMultiFrames.insert( frame->multiFrame() );
|
||||
}
|
||||
}
|
||||
item->writeXml( documentElement, doc, context );
|
||||
if ( operation == ClipboardCut )
|
||||
currentLayout()->removeLayoutItem( item );
|
||||
@ -352,6 +365,24 @@ void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutVie
|
||||
itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
|
||||
}
|
||||
}
|
||||
QDomNodeList multiFrameNodes = doc.elementsByTagName( QStringLiteral( "LayoutMultiFrame" ) );
|
||||
for ( int i = 0; i < multiFrameNodes.count(); ++i )
|
||||
{
|
||||
QDomNode multiFrameNode = multiFrameNodes.at( i );
|
||||
if ( multiFrameNode.isElement() )
|
||||
{
|
||||
multiFrameNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
|
||||
QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( QStringLiteral( "childFrame" ) );
|
||||
for ( int j = 0; j < frameNodes.count(); ++j )
|
||||
{
|
||||
QDomNode itemNode = frameNodes.at( j );
|
||||
if ( itemNode.isElement() )
|
||||
{
|
||||
itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData( QStringLiteral( "text/xml" ), doc.toByteArray() );
|
||||
|
@ -292,22 +292,16 @@ class TestQgsLayout(unittest.TestCase):
|
||||
|
||||
# double check that new items have a unique uid
|
||||
self.assertNotIn(new_items[0].uuid(), uuids)
|
||||
self.assertIn(new_items[0].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[0].uuid())
|
||||
self.assertNotIn(new_items[1].uuid(), uuids)
|
||||
self.assertIn(new_items[1].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[1].uuid())
|
||||
self.assertNotIn(new_items[2].uuid(), uuids)
|
||||
self.assertIn(new_items[2].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[2].uuid())
|
||||
self.assertNotIn(new_items[3].uuid(), uuids)
|
||||
self.assertIn(new_items[3].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[3].uuid())
|
||||
|
||||
self.assertNotIn(multiframes[0].uuid(), [multiframe1.uuid(), multiframe2.uuid()])
|
||||
self.assertIn(multiframes[0].templateUuid(), [multiframe1.uuid(), multiframe2.uuid()])
|
||||
self.assertNotIn(multiframes[1].uuid(), [multiframe1.uuid(), multiframe2.uuid()])
|
||||
self.assertIn(multiframes[1].templateUuid(), [multiframe1.uuid(), multiframe2.uuid()])
|
||||
new_multiframe1 = [i for i in multiframes if i.html() == 'mf1'][0]
|
||||
self.assertEqual(new_multiframe1.layout(), l2)
|
||||
new_multiframe2 = [i for i in multiframes if i.html() == 'mf2'][0]
|
||||
@ -344,22 +338,16 @@ class TestQgsLayout(unittest.TestCase):
|
||||
self.assertTrue(new_items2[2] in l2.items())
|
||||
self.assertTrue(new_items2[3] in l2.items())
|
||||
self.assertNotIn(new_items2[0].uuid(), uuids)
|
||||
self.assertIn(new_items2[0].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[0].uuid())
|
||||
self.assertNotIn(new_items2[1].uuid(), uuids)
|
||||
self.assertIn(new_items2[1].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[1].uuid())
|
||||
self.assertNotIn(new_items2[2].uuid(), uuids)
|
||||
self.assertIn(new_items2[2].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[2].uuid())
|
||||
self.assertNotIn(new_items2[3].uuid(), uuids)
|
||||
self.assertIn(new_items2[3].templateUuid(), original_uuids)
|
||||
uuids.add(new_items[3].uuid())
|
||||
|
||||
self.assertNotIn(multiframes2[0].uuid(), [multiframe1.uuid(), multiframe2.uuid(), new_multiframe1.uuid(), new_multiframe2.uuid()])
|
||||
self.assertIn(multiframes2[0].templateUuid(), [multiframe1.uuid(), multiframe2.uuid()])
|
||||
self.assertNotIn(multiframes2[1].uuid(), [multiframe1.uuid(), multiframe2.uuid(), new_multiframe1.uuid(), new_multiframe2.uuid()])
|
||||
self.assertIn(multiframes2[1].templateUuid(), [multiframe1.uuid(), multiframe2.uuid()])
|
||||
|
||||
new_multiframe1b = [i for i in multiframes2 if i.html() == 'mf1'][0]
|
||||
self.assertEqual(new_multiframe1b.layout(), l2)
|
||||
@ -387,21 +375,8 @@ class TestQgsLayout(unittest.TestCase):
|
||||
self.assertTrue(new_items3[1] in l2.items())
|
||||
self.assertTrue(new_items3[2] in l2.items())
|
||||
self.assertTrue(new_items3[3] in l2.items())
|
||||
self.assertIn(new_items3[0].templateUuid(), original_uuids)
|
||||
self.assertIn(new_items3[1].templateUuid(), original_uuids)
|
||||
self.assertIn(new_items3[2].templateUuid(), original_uuids)
|
||||
self.assertIn(new_items3[3].templateUuid(), original_uuids)
|
||||
new_multiframe1 = [i for i in new_multiframes if i.html() == 'mf1'][0]
|
||||
self.assertEqual(new_multiframe1.templateUuid(), multiframe1.uuid())
|
||||
new_multiframe2 = [i for i in new_multiframes if i.html() == 'mf2'][0]
|
||||
self.assertEqual(new_multiframe2.templateUuid(), multiframe2.uuid())
|
||||
|
||||
self.assertEqual(l2.itemByUuid(new_items3[0].templateUuid(), True), new_items3[0])
|
||||
self.assertEqual(l2.itemByUuid(new_items3[1].templateUuid(), True), new_items3[1])
|
||||
self.assertEqual(l2.itemByUuid(new_items3[2].templateUuid(), True), new_items3[2])
|
||||
self.assertEqual(l2.itemByUuid(new_items3[3].templateUuid(), True), new_items3[3])
|
||||
self.assertEqual(l2.multiFrameByUuid(new_multiframe1.templateUuid(), True), new_multiframe1)
|
||||
self.assertEqual(l2.multiFrameByUuid(new_multiframe2.templateUuid(), True), new_multiframe2)
|
||||
|
||||
new_frame1 = sip.cast([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame1'][0], QgsLayoutFrame)
|
||||
new_frame2 = sip.cast([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame2'][0], QgsLayoutFrame)
|
||||
|
@ -19,6 +19,9 @@ from qgis.core import (QgsProject,
|
||||
QgsUnitTypes,
|
||||
QgsLayoutItemPicture,
|
||||
QgsLayoutItemLabel,
|
||||
QgsLayoutItemHtml,
|
||||
QgsLayoutItemRegistry,
|
||||
QgsLayoutFrame,
|
||||
QgsLayoutPoint,
|
||||
QgsLayoutSize,
|
||||
QgsLayoutAligner)
|
||||
@ -686,6 +689,30 @@ class TestQgsLayoutView(unittest.TestCase):
|
||||
l.addLayoutItem(item2)
|
||||
item2.setSelected(True)
|
||||
|
||||
# multiframes
|
||||
multiframe1 = QgsLayoutItemHtml(l)
|
||||
multiframe1.setHtml('mf1')
|
||||
l.addMultiFrame(multiframe1)
|
||||
frame1 = QgsLayoutFrame(l, multiframe1)
|
||||
frame1.setId('frame1a')
|
||||
multiframe1.addFrame(frame1)
|
||||
frame1b = QgsLayoutFrame(l, multiframe1)
|
||||
frame1b.setId('frame1b')
|
||||
multiframe1.addFrame(frame1b) # not selected
|
||||
frame1c = QgsLayoutFrame(l, multiframe1)
|
||||
frame1c.setId('frame1b')
|
||||
multiframe1.addFrame(frame1c) # not selected
|
||||
|
||||
multiframe2 = QgsLayoutItemHtml(l)
|
||||
multiframe2.setHtml('mf2')
|
||||
l.addMultiFrame(multiframe2)
|
||||
frame2 = QgsLayoutFrame(l, multiframe2)
|
||||
frame2.setId('frame2')
|
||||
multiframe2.addFrame(frame2)
|
||||
|
||||
frame1.setSelected(True)
|
||||
frame2.setSelected(True)
|
||||
|
||||
view = QgsLayoutView()
|
||||
view.setCurrentLayout(l)
|
||||
self.assertFalse(view.hasItemsInClipboard())
|
||||
@ -694,11 +721,30 @@ class TestQgsLayoutView(unittest.TestCase):
|
||||
self.assertTrue(view.hasItemsInClipboard())
|
||||
|
||||
pasted = view.pasteItems(QgsLayoutView.PasteModeCursor)
|
||||
self.assertEqual(len(pasted), 2)
|
||||
self.assertEqual(len(pasted), 4)
|
||||
|
||||
new_multiframes = [m for m in l.multiFrames() if m not in [multiframe1, multiframe2]]
|
||||
self.assertEqual(len(new_multiframes), 2)
|
||||
|
||||
self.assertIn(pasted[0], l.items())
|
||||
self.assertIn(pasted[1], l.items())
|
||||
self.assertIn(sip.cast(pasted[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))
|
||||
self.assertIn(sip.cast(pasted[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))
|
||||
labels = [p for p in pasted if p.type() == QgsLayoutItemRegistry.LayoutLabel]
|
||||
self.assertIn(sip.cast(labels[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))
|
||||
self.assertIn(sip.cast(labels[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2'))
|
||||
frames = [p for p in pasted if p.type() == QgsLayoutItemRegistry.LayoutFrame]
|
||||
pasted_frame1 = sip.cast(frames[0], QgsLayoutFrame)
|
||||
pasted_frame2 = sip.cast(frames[1], QgsLayoutFrame)
|
||||
self.assertIn(pasted_frame1.multiFrame(), new_multiframes)
|
||||
self.assertIn(new_multiframes[0].frames()[0].uuid(), (pasted_frame1.uuid(), pasted_frame2.uuid()))
|
||||
self.assertIn(pasted_frame2.multiFrame(), new_multiframes)
|
||||
self.assertIn(new_multiframes[1].frames()[0].uuid(), (pasted_frame1.uuid(), pasted_frame2.uuid()))
|
||||
|
||||
self.assertEqual(frame1.multiFrame(), multiframe1)
|
||||
self.assertCountEqual(multiframe1.frames(), [frame1, frame1b, frame1c])
|
||||
self.assertEqual(frame1b.multiFrame(), multiframe1)
|
||||
self.assertEqual(frame1c.multiFrame(), multiframe1)
|
||||
self.assertEqual(frame2.multiFrame(), multiframe2)
|
||||
self.assertCountEqual(multiframe2.frames(), [frame2])
|
||||
|
||||
# copy specific item
|
||||
view.copyItems([item2], QgsLayoutView.ClipboardCopy)
|
||||
|
Loading…
x
Reference in New Issue
Block a user