After a undo/redo action occurs, select the affected items

This commit is contained in:
Nyall Dawson 2017-10-24 12:54:11 +10:00
parent 48a45b3bff
commit 72a1f77079
9 changed files with 137 additions and 6 deletions

View File

@ -10,7 +10,8 @@
class QgsLayoutUndoStack
class QgsLayoutUndoStack : QObject
{
%Docstring
An undo stack for QgsLayouts.
@ -86,6 +87,19 @@ class QgsLayoutUndoStack
:rtype: QUndoStack
%End
void notifyUndoRedoOccurred( QgsLayoutItem *item );
%Docstring
Notifies the stack that an undo or redo action occurred for a specified ``item``.
%End
signals:
void undoRedoOccurredForItems( const QSet< QString > itemUuids );
%Docstring
Emitted when an undo or redo action has occurred, which affected a
set of layout ``itemUuids``.
%End
private:
QgsLayoutUndoStack( const QgsLayoutUndoStack &other );
};

View File

@ -581,6 +581,7 @@ void QgsLayoutDesignerDialog::setCurrentLayout( QgsLayout *layout )
mLayoutToolbar->addAction( mUndoAction );
mLayoutToolbar->addAction( mRedoAction );
connect( mLayout->undoStack(), &QgsLayoutUndoStack::undoRedoOccurredForItems, this, &QgsLayoutDesignerDialog::undoRedoOccurredForItems );
connect( mActionClearGuides, &QAction::triggered, &mLayout->guides(), [ = ]
{
mLayout->guides().clear();
@ -620,6 +621,9 @@ void QgsLayoutDesignerDialog::setIconSizes( int size )
void QgsLayoutDesignerDialog::showItemOptions( QgsLayoutItem *item, bool bringPanelToFront )
{
if ( mBlockItemOptions )
return;
if ( !item )
{
delete mItemPropertiesStack->takeMainPanel();
@ -1073,6 +1077,27 @@ void QgsLayoutDesignerDialog::dockVisibilityChanged( bool visible )
}
}
void QgsLayoutDesignerDialog::undoRedoOccurredForItems( const QSet<QString> itemUuids )
{
mBlockItemOptions = true;
mLayout->deselectAll();
QgsLayoutItem *focusItem = nullptr;
for ( const QString &uuid : itemUuids )
{
QgsLayoutItem *item = mLayout->itemByUuid( uuid );
if ( !item )
continue;
item->setSelected( true );
focusItem = item;
}
mBlockItemOptions = false;
if ( focusItem )
showItemOptions( focusItem );
}
QgsLayoutView *QgsLayoutDesignerDialog::view()
{
return mView;

View File

@ -245,6 +245,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
void addPages();
void statusMessageReceived( const QString &message );
void dockVisibilityChanged( bool visible );
void undoRedoOccurredForItems( const QSet< QString > itemUuids );
private:
@ -312,6 +313,8 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
};
QMap< QString, PanelStatus > mPanelStatus;
bool mBlockItemOptions = false;
//! Save window state
void saveWindowState();

View File

@ -742,6 +742,7 @@ SET(QGIS_CORE_MOC_HDRS
layout/qgslayoutmodel.h
layout/qgslayoutpagecollection.h
layout/qgslayoutobject.h
layout/qgslayoutundostack.h
symbology/qgscptcityarchive.h
symbology/qgssvgcache.h
@ -1001,7 +1002,6 @@ SET(QGIS_CORE_HDRS
layout/qgslayoutsize.h
layout/qgslayoutsnapper.h
layout/qgslayoutundocommand.h
layout/qgslayoutundostack.h
layout/qgslayoututils.h
metadata/qgslayermetadata.h

View File

@ -682,7 +682,7 @@ QString QgsLayoutItemPicture::picturePath() const
return mSourcePath;
}
bool QgsLayoutItemPicture::writePropertiesToElement( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const
bool QgsLayoutItemPicture::writePropertiesToElement( QDomElement &elem, QDomDocument &, const QgsReadWriteContext &context ) const
{
QString imagePath = mSourcePath;

View File

@ -72,6 +72,7 @@ void QgsLayoutItemUndoCommand::restoreState( QDomDocument &stateDoc )
item->readXml( stateDoc.documentElement().firstChild().toElement(), stateDoc, QgsReadWriteContext() );
mLayout->project()->setDirty( true );
mLayout->undoStack()->notifyUndoRedoOccurred( item );
}
QgsLayoutItem *QgsLayoutItemUndoCommand::recreateItem( int itemType, QgsLayout *layout )

View File

@ -21,10 +21,11 @@
#include <QUndoStack>
QgsLayoutUndoStack::QgsLayoutUndoStack( QgsLayout *layout )
: mLayout( layout )
: QObject()
, mLayout( layout )
, mUndoStack( new QUndoStack( layout ) )
{
connect( mUndoStack.get(), &QUndoStack::indexChanged, this, &QgsLayoutUndoStack::indexChanged );
}
void QgsLayoutUndoStack::beginMacro( const QString &commandText )
@ -76,3 +77,17 @@ QUndoStack *QgsLayoutUndoStack::stack()
return mUndoStack.get();
}
void QgsLayoutUndoStack::notifyUndoRedoOccurred( QgsLayoutItem *item )
{
mUndoRedoOccurredItemUuids.insert( item->uuid() );
}
void QgsLayoutUndoStack::indexChanged()
{
if ( mUndoRedoOccurredItemUuids.empty() )
return;
emit undoRedoOccurredForItems( mUndoRedoOccurredItemUuids );
mUndoRedoOccurredItemUuids.clear();
}

View File

@ -21,6 +21,8 @@
#include "qgis.h"
#include "qgis_core.h"
#include "qgslayoutundocommand.h"
#include "qgslayoutitem.h"
#include <memory>
class QgsLayout;
@ -31,8 +33,10 @@ class QUndoStack;
* An undo stack for QgsLayouts.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsLayoutUndoStack
class CORE_EXPORT QgsLayoutUndoStack : public QObject
{
Q_OBJECT
public:
/**
@ -98,6 +102,23 @@ class CORE_EXPORT QgsLayoutUndoStack
*/
QUndoStack *stack();
/**
* Notifies the stack that an undo or redo action occurred for a specified \a item.
*/
void notifyUndoRedoOccurred( QgsLayoutItem *item );
signals:
/**
* Emitted when an undo or redo action has occurred, which affected a
* set of layout \a itemUuids.
*/
void undoRedoOccurredForItems( const QSet< QString > itemUuids );
private slots:
void indexChanged();
private:
QgsLayout *mLayout = nullptr;
@ -106,6 +127,8 @@ class CORE_EXPORT QgsLayoutUndoStack
std::vector< std::unique_ptr< QgsAbstractLayoutUndoCommand > > mActiveCommands;
QSet< QString > mUndoRedoOccurredItemUuids;
#ifdef SIP_RUN
QgsLayoutUndoStack( const QgsLayoutUndoStack &other );
#endif

View File

@ -41,6 +41,7 @@ class TestQgsLayout: public QObject
void addItem();
void layoutItems();
void layoutItemByUuid();
void undoRedoOccurred();
private:
QString mReport;
@ -419,6 +420,55 @@ void TestQgsLayout::layoutItemByUuid()
QCOMPARE( l.itemByUuid( map1->uuid() ), map1 );
}
void TestQgsLayout::undoRedoOccurred()
{
// test emitting undo/redo occurred signal
QgsProject proj;
QgsLayout l( &proj );
QSignalSpy spyOccurred( l.undoStack(), &QgsLayoutUndoStack::undoRedoOccurredForItems );
QgsLayoutItemShape *item = new QgsLayoutItemShape( &l );
l.addLayoutItem( item );
QCOMPARE( spyOccurred.count(), 0 );
//adds a new undo command
item->setId( "test" );
QCOMPARE( spyOccurred.count(), 0 );
QgsLayoutItemShape *item2 = new QgsLayoutItemShape( &l );
l.addLayoutItem( item2 );
item2->setId( "test2" );
QCOMPARE( spyOccurred.count(), 0 );
l.undoStack()->stack()->undo();
QCOMPARE( spyOccurred.count(), 1 );
QSet< QString > items = qvariant_cast< QSet< QString > >( spyOccurred.at( 0 ).at( 0 ) );
QCOMPARE( items, QSet< QString >() << item2->uuid() );
l.undoStack()->stack()->redo();
QCOMPARE( spyOccurred.count(), 2 );
items = qvariant_cast< QSet< QString> >( spyOccurred.at( 1 ).at( 0 ) );
QCOMPARE( items, QSet< QString >() << item2->uuid() );
// macro undo
l.undoStack()->beginMacro( QString() );
item->setId( "new id" );
item2->setId( "new id2" );
l.undoStack()->endMacro();
QCOMPARE( spyOccurred.count(), 2 );
l.undoStack()->stack()->undo();
QCOMPARE( spyOccurred.count(), 3 );
items = qvariant_cast< QSet< QString > >( spyOccurred.at( 2 ).at( 0 ) );
QCOMPARE( items, QSet< QString >() << item->uuid() << item2->uuid() );
l.undoStack()->stack()->redo();
QCOMPARE( spyOccurred.count(), 4 );
items = qvariant_cast< QSet< QString > >( spyOccurred.at( 3 ).at( 0 ) );
QCOMPARE( items, QSet< QString >() << item->uuid() << item2->uuid() );
}
QGSTEST_MAIN( TestQgsLayout )
#include "testqgslayout.moc"