Nicer API for adding/removing items

Automatically create the corresponding undo commands, so that
plugins and scripts which add/delete items will be added to
the undo stack without any work required.
This commit is contained in:
Nyall Dawson 2017-10-04 20:55:46 +10:00
parent 4167724035
commit a66f2cb684
7 changed files with 49 additions and 19 deletions

View File

@ -369,6 +369,7 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
%Docstring
Removes an ``item`` from the layout. This should be called instead of the base class removeItem()
method.
The item will also be deleted.
%End
QDomElement writeXml( QDomDocument &document, const QgsReadWriteContext &context ) const;

View File

@ -21,6 +21,7 @@
#include "qgslayoutguidecollection.h"
#include "qgsreadwritecontext.h"
#include "qgsproject.h"
#include "qgslayoutitemundocommand.h"
QgsLayout::QgsLayout( QgsProject *project )
: mProject( project )
@ -360,19 +361,24 @@ QRectF QgsLayout::layoutBounds( bool ignorePages, double margin ) const
void QgsLayout::addLayoutItem( QgsLayoutItem *item )
{
addItem( item );
updateBounds();
mItemsModel->rebuildZList();
addLayoutItemPrivate( item );
QString undoText;
if ( QgsLayoutItemAbstractMetadata *metadata = QgsApplication::layoutItemRegistry()->itemMetadata( item->type() ) )
{
undoText = tr( "Created %1" ).arg( metadata->visibleName() );
}
else
{
undoText = tr( "Created item" );
}
mUndoStack->stack()->push( new QgsLayoutItemAddItemCommand( item, undoText ) );
}
void QgsLayout::removeLayoutItem( QgsLayoutItem *item )
{
mItemsModel->setItemRemoved( item );
removeItem( item );
#if 0 //TODO
emit itemRemoved( item );
#endif
item->deleteLater();
QgsLayoutItemDeleteUndoCommand *deleteCommand = new QgsLayoutItemDeleteUndoCommand( item, tr( "Deleted item" ) );
removeLayoutItemPrivate( item );
mUndoStack->stack()->push( deleteCommand );
}
QgsLayoutUndoStack *QgsLayout::undoStack()
@ -457,6 +463,23 @@ bool QgsLayout::readXmlLayoutSettings( const QDomElement &layoutElement, const Q
return true;
}
void QgsLayout::addLayoutItemPrivate( QgsLayoutItem *item )
{
addItem( item );
updateBounds();
mItemsModel->rebuildZList();
}
void QgsLayout::removeLayoutItemPrivate( QgsLayoutItem *item )
{
mItemsModel->setItemRemoved( item );
removeItem( item );
#if 0 //TODO
emit itemRemoved( item );
#endif
item->deleteLater();
}
void QgsLayout::updateZValues( const bool addUndoCommands )
{
int counter = mItemsModel->zOrderListSize();

View File

@ -417,6 +417,7 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
/**
* Removes an \a item from the layout. This should be called instead of the base class removeItem()
* method.
* The item will also be deleted.
*/
void removeLayoutItem( QgsLayoutItem *item );
@ -489,7 +490,19 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
//! Reads only the layout settings (not member settings like grid settings, etc) from XML
bool readXmlLayoutSettings( const QDomElement &layoutElement, const QDomDocument &document, const QgsReadWriteContext &context );
/**
* Adds a layout item to the layout, without adding the corresponding undo commands.
*/
void addLayoutItemPrivate( QgsLayoutItem *item );
/**
* Removes an item from the layout, without adding the corresponding undo commands.
*/
void removeLayoutItemPrivate( QgsLayoutItem *item );
friend class QgsLayoutItemAddItemCommand;
friend class QgsLayoutItemDeleteUndoCommand;
friend class QgsLayoutItemUndoCommand;
friend class QgsLayoutUndoCommand;
friend class QgsLayoutModel;
};

View File

@ -75,7 +75,7 @@ void QgsLayoutItemUndoCommand::restoreState( QDomDocument &stateDoc )
QgsLayoutItem *QgsLayoutItemUndoCommand::recreateItem( int itemType, QgsLayout *layout )
{
QgsLayoutItem *item = QgsApplication::layoutItemRegistry()->createItem( itemType, layout );
mLayout->addLayoutItem( item );
mLayout->addLayoutItemPrivate( item );
return item;
}
@ -116,7 +116,7 @@ void QgsLayoutItemDeleteUndoCommand::redo()
QgsLayoutItem *item = layout()->itemByUuid( itemUuid() );
Q_ASSERT_X( item, "QgsLayoutItemDeleteUndoCommand::redo", "could not find item to re-delete!" );
layout()->removeLayoutItem( item );
layout()->removeLayoutItemPrivate( item );
}
QgsLayoutItemAddItemCommand::QgsLayoutItemAddItemCommand( QgsLayoutItem *item, const QString &text, int id, QUndoCommand *parent )
@ -146,7 +146,7 @@ void QgsLayoutItemAddItemCommand::undo()
QgsLayoutItem *item = layout()->itemByUuid( itemUuid() );
if ( item )
{
layout()->removeLayoutItem( item );
layout()->removeLayoutItemPrivate( item );
}
}

View File

@ -585,9 +585,7 @@ void QgsLayoutView::deleteSelectedItems()
//delete selected items
for ( QgsLayoutItem *item : selectedItems )
{
QgsLayoutItemDeleteUndoCommand *deleteCommand = new QgsLayoutItemDeleteUndoCommand( item, QString() );
currentLayout()->removeLayoutItem( item );
currentLayout()->undoStack()->stack()->push( deleteCommand );
}
currentLayout()->undoStack()->endMacro();
currentLayout()->project()->setDirty( true );

View File

@ -26,7 +26,6 @@
#include "qgslayoutitemguiregistry.h"
#include "qgslayoutnewitempropertiesdialog.h"
#include "qgssettings.h"
#include "qgslayoutitemundocommand.h"
#include <QGraphicsRectItem>
#include <QPen>
#include <QBrush>
@ -119,7 +118,6 @@ void QgsLayoutViewToolAddItem::layoutReleaseEvent( QgsLayoutViewMouseEvent *even
settings.setValue( QStringLiteral( "LayoutDesigner/lastSizeUnit" ), static_cast< int >( item->sizeWithUnits().units() ) );
layout()->addLayoutItem( item );
layout()->undoStack()->stack()->push( new QgsLayoutItemAddItemCommand( item, tr( "Created %1" ).arg( QgsApplication::layoutItemRegistry()->itemMetadata( mItemType )->visibleName() ) ) );
layout()->setSelectedItem( item );
}

View File

@ -1372,7 +1372,6 @@ void TestQgsLayoutItem::undoRedo()
item->setFrameStrokeColor( QColor( 255, 100, 200 ) );
l.addLayoutItem( item );
l.undoStack()->stack()->push( new QgsLayoutItemAddItemCommand( item, QString() ) );
QVERIFY( pItem );
QVERIFY( l.items().contains( item ) );
QCOMPARE( l.itemByUuid( uuid ), item );
@ -1412,9 +1411,7 @@ void TestQgsLayoutItem::undoRedo()
QCOMPARE( item->frameStrokeColor().name(), QColor( 255, 100, 200 ).name() );
// delete item
QgsLayoutItemDeleteUndoCommand *deleteCommand = new QgsLayoutItemDeleteUndoCommand( item, QString() );
l.removeLayoutItem( item );
l.undoStack()->stack()->push( deleteCommand );
QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
QVERIFY( !pItem );