Skip to content

Commit f4d38d4

Browse files
committed
Properly discard edit commands when calling QgsVectorLayer::destroyEditCommand()
Since it's not directly possible to pop the last command off an QUndoStack (the command which is destroyed/discard by calling this method), we add a dummy obsolete command to force this to occur. Pushing the new command deletes the destroyed one, and since the new command is obsolete it's automatically deleted by the undo stack.
1 parent 0a269aa commit f4d38d4

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

src/core/qgsvectorlayer.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <QDomNode>
3333
#include <QVector>
3434
#include <QStringBuilder>
35+
#include <QUndoCommand>
3536

3637
#include "qgssettings.h"
3738
#include "qgsvectorlayer.h"
@@ -3005,6 +3006,15 @@ void QgsVectorLayer::destroyEditCommand()
30053006
}
30063007
undoStack()->endMacro();
30073008
undoStack()->undo();
3009+
3010+
// it's not directly possible to pop the last command off the stack (the destroyed one)
3011+
// and delete, so we add a dummy obsolete command to force this to occur.
3012+
// Pushing the new command deletes the destroyed one, and since the new
3013+
// command is obsolete it's automatically deleted by the undo stack.
3014+
std::unique_ptr< QUndoCommand > command = qgis::make_unique< QUndoCommand >();
3015+
command->setObsolete( true );
3016+
undoStack()->push( command.release() );
3017+
30083018
mEditCommandActive = false;
30093019
mDeletedFids.clear();
30103020
emit editCommandDestroyed();

tests/src/python/test_qgsvectorlayer.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,60 @@ def test_FeatureCount(self):
238238
myCount = myLayer.featureCount()
239239
self.assertEqual(myCount, 6)
240240

241+
# undo stack
242+
def testUndoStack(self):
243+
layer = createLayerWithOnePoint()
244+
layer.startEditing()
245+
246+
self.assertEqual(layer.undoStack().count(), 0)
247+
self.assertEqual(layer.undoStack().index(), 0)
248+
f = QgsFeature()
249+
f.setAttributes(["test", 123])
250+
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
251+
self.assertTrue(layer.addFeatures([f]))
252+
self.assertEqual(layer.undoStack().count(), 1)
253+
self.assertEqual(layer.undoStack().index(), 1)
254+
self.assertEqual(layer.featureCount(), 2)
255+
256+
layer.undoStack().undo()
257+
self.assertEqual(layer.undoStack().count(), 1)
258+
self.assertEqual(layer.undoStack().index(), 0)
259+
self.assertEqual(layer.featureCount(), 1)
260+
261+
layer.undoStack().redo()
262+
self.assertEqual(layer.undoStack().count(), 1)
263+
self.assertEqual(layer.undoStack().index(), 1)
264+
self.assertEqual(layer.featureCount(), 2)
265+
266+
# macro commands
267+
layer.beginEditCommand("Test command 1")
268+
self.assertTrue(layer.addFeatures([f]))
269+
self.assertTrue(layer.addFeatures([f]))
270+
layer.endEditCommand()
271+
self.assertEqual(layer.undoStack().count(), 2)
272+
self.assertEqual(layer.undoStack().index(), 2)
273+
self.assertEqual(layer.featureCount(), 4)
274+
275+
layer.undoStack().undo()
276+
self.assertEqual(layer.undoStack().count(), 2)
277+
self.assertEqual(layer.undoStack().index(), 1)
278+
self.assertEqual(layer.featureCount(), 2)
279+
280+
layer.undoStack().redo()
281+
self.assertEqual(layer.undoStack().count(), 2)
282+
self.assertEqual(layer.undoStack().index(), 2)
283+
self.assertEqual(layer.featureCount(), 4)
284+
285+
# throw away a macro command
286+
layer.beginEditCommand("Test command 1")
287+
self.assertTrue(layer.addFeatures([f]))
288+
self.assertTrue(layer.addFeatures([f]))
289+
self.assertEqual(layer.featureCount(), 6)
290+
layer.destroyEditCommand()
291+
self.assertEqual(layer.undoStack().count(), 2)
292+
self.assertEqual(layer.undoStack().index(), 2)
293+
self.assertEqual(layer.featureCount(), 4)
294+
241295
# ADD FEATURE
242296

243297
def test_AddFeature(self):
0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)