Skip to content

Commit 30eab10

Browse files
committed
Fix handling of overlapping item commands
1 parent 8fb2c3c commit 30eab10

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

src/core/layout/qgslayoutundostack.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,27 +44,31 @@ void QgsLayoutUndoStack::beginCommand( QgsLayoutUndoObjectInterface *object, con
4444
return;
4545
}
4646

47-
mActiveCommand.reset( object->createCommand( commandText, id, nullptr ) );
48-
mActiveCommand->saveBeforeState();
47+
mActiveCommands.emplace_back( std::unique_ptr< QgsAbstractLayoutUndoCommand >( object->createCommand( commandText, id, nullptr ) ) );
48+
mActiveCommands.back()->saveBeforeState();
4949
}
5050

5151
void QgsLayoutUndoStack::endCommand()
5252
{
53-
if ( !mActiveCommand )
53+
if ( mActiveCommands.empty() )
5454
return;
5555

56-
mActiveCommand->saveAfterState();
57-
if ( mActiveCommand->containsChange() ) //protect against empty commands
56+
mActiveCommands.back()->saveAfterState();
57+
if ( mActiveCommands.back()->containsChange() ) //protect against empty commands
5858
{
59-
mUndoStack->push( mActiveCommand.release() );
59+
mUndoStack->push( mActiveCommands.back().release() );
60+
mActiveCommands.pop_back();
6061

6162
mLayout->project()->setDirty( true );
6263
}
6364
}
6465

6566
void QgsLayoutUndoStack::cancelCommand()
6667
{
67-
mActiveCommand.reset();
68+
if ( mActiveCommands.empty() )
69+
return;
70+
71+
mActiveCommands.pop_back();
6872
}
6973

7074
QUndoStack *QgsLayoutUndoStack::stack()

src/core/layout/qgslayoutundostack.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class CORE_EXPORT QgsLayoutUndoStack
104104

105105
std::unique_ptr< QUndoStack > mUndoStack;
106106

107-
std::unique_ptr< QgsAbstractLayoutUndoCommand > mActiveCommand;
107+
std::vector< std::unique_ptr< QgsAbstractLayoutUndoCommand > > mActiveCommands;
108108

109109
#ifdef SIP_RUN
110110
QgsLayoutUndoStack( const QgsLayoutUndoStack &other );

tests/src/core/testqgslayoutitem.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class TestQgsLayoutItem: public QObject
149149
void writeReadXmlProperties();
150150
void undoRedo();
151151
void multiItemUndo();
152+
void overlappingUndo();
152153

153154
private:
154155

@@ -1481,6 +1482,36 @@ void TestQgsLayoutItem::multiItemUndo()
14811482
QCOMPARE( item->positionWithUnits(), QgsLayoutPoint( 10, 10 ) );
14821483
}
14831484

1485+
void TestQgsLayoutItem::overlappingUndo()
1486+
{
1487+
QgsProject proj;
1488+
QgsLayout l( &proj );
1489+
1490+
QgsLayoutItemRectangularShape *item = new QgsLayoutItemRectangularShape( &l );
1491+
l.addLayoutItem( item );
1492+
item->attemptMove( QgsLayoutPoint( 10, 10 ) );
1493+
QgsLayoutItemRectangularShape *item2 = new QgsLayoutItemRectangularShape( &l );
1494+
l.addLayoutItem( item2 );
1495+
item2->attemptMove( QgsLayoutPoint( 20, 20 ) );
1496+
1497+
//commands overlap
1498+
l.undoStack()->beginCommand( item, tr( "Item moved" ), QgsLayoutItem::UndoIncrementalMove );
1499+
item->attemptMove( QgsLayoutPoint( 1, 1 ) );
1500+
l.undoStack()->beginCommand( item2, tr( "Item moved" ), QgsLayoutItem::UndoIncrementalMove );
1501+
item2->attemptMove( QgsLayoutPoint( 21, 21 ) );
1502+
l.undoStack()->endCommand();
1503+
l.undoStack()->endCommand();
1504+
1505+
// undo should remove item move
1506+
l.undoStack()->stack()->undo();
1507+
QCOMPARE( item2->positionWithUnits(), QgsLayoutPoint( 21, 21 ) );
1508+
QCOMPARE( item->positionWithUnits(), QgsLayoutPoint( 10, 10 ) );
1509+
l.undoStack()->stack()->undo();
1510+
QCOMPARE( item2->positionWithUnits(), QgsLayoutPoint( 20, 20 ) );
1511+
QCOMPARE( item->positionWithUnits(), QgsLayoutPoint( 10, 10 ) );
1512+
1513+
}
1514+
14841515
QgsLayoutItem *TestQgsLayoutItem::createCopyViaXml( QgsLayout *layout, QgsLayoutItem *original )
14851516
{
14861517
//save original item to xml

0 commit comments

Comments
 (0)