Skip to content
Permalink
Browse files

Properly discard edit commands when calling QgsVectorLayer::destroyEd…

…itCommand()

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.
  • Loading branch information
nyalldawson committed May 2, 2018
1 parent 0a269aa commit f4d38d4f09bf9b32faf1cbf6cf94d48b2dfa30ae
@@ -32,6 +32,7 @@
#include <QDomNode>
#include <QVector>
#include <QStringBuilder>
#include <QUndoCommand>

#include "qgssettings.h"
#include "qgsvectorlayer.h"
@@ -3005,6 +3006,15 @@ void QgsVectorLayer::destroyEditCommand()
}
undoStack()->endMacro();
undoStack()->undo();

// it's not directly possible to pop the last command off the stack (the destroyed one)
// and delete, so 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.
std::unique_ptr< QUndoCommand > command = qgis::make_unique< QUndoCommand >();
command->setObsolete( true );

This comment has been minimized.

Copy link
@alexbruy

alexbruy May 4, 2018

Contributor

This breaks builds with Qt < 5.9.0 as setObsolete() was added in Qt 5.9.0. We still have minimal Qt version set to 5.2 for builds without 3D support.

This comment has been minimized.

Copy link
@pblottiere

pblottiere May 4, 2018

Member

This breaks builds with Qt < 5.9.0 as setObsolete() was added in Qt 5.9.0

I confirm. Our OGC tests platform for QGIS Server is KO due to that (Qt 5.5 only).

undoStack()->push( command.release() );

mEditCommandActive = false;
mDeletedFids.clear();
emit editCommandDestroyed();
@@ -238,6 +238,60 @@ def test_FeatureCount(self):
myCount = myLayer.featureCount()
self.assertEqual(myCount, 6)

# undo stack
def testUndoStack(self):
layer = createLayerWithOnePoint()
layer.startEditing()

self.assertEqual(layer.undoStack().count(), 0)
self.assertEqual(layer.undoStack().index(), 0)
f = QgsFeature()
f.setAttributes(["test", 123])
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
self.assertTrue(layer.addFeatures([f]))
self.assertEqual(layer.undoStack().count(), 1)
self.assertEqual(layer.undoStack().index(), 1)
self.assertEqual(layer.featureCount(), 2)

layer.undoStack().undo()
self.assertEqual(layer.undoStack().count(), 1)
self.assertEqual(layer.undoStack().index(), 0)
self.assertEqual(layer.featureCount(), 1)

layer.undoStack().redo()
self.assertEqual(layer.undoStack().count(), 1)
self.assertEqual(layer.undoStack().index(), 1)
self.assertEqual(layer.featureCount(), 2)

# macro commands
layer.beginEditCommand("Test command 1")
self.assertTrue(layer.addFeatures([f]))
self.assertTrue(layer.addFeatures([f]))
layer.endEditCommand()
self.assertEqual(layer.undoStack().count(), 2)
self.assertEqual(layer.undoStack().index(), 2)
self.assertEqual(layer.featureCount(), 4)

layer.undoStack().undo()
self.assertEqual(layer.undoStack().count(), 2)
self.assertEqual(layer.undoStack().index(), 1)
self.assertEqual(layer.featureCount(), 2)

layer.undoStack().redo()
self.assertEqual(layer.undoStack().count(), 2)
self.assertEqual(layer.undoStack().index(), 2)
self.assertEqual(layer.featureCount(), 4)

# throw away a macro command
layer.beginEditCommand("Test command 1")
self.assertTrue(layer.addFeatures([f]))
self.assertTrue(layer.addFeatures([f]))
self.assertEqual(layer.featureCount(), 6)
layer.destroyEditCommand()
self.assertEqual(layer.undoStack().count(), 2)
self.assertEqual(layer.undoStack().index(), 2)
self.assertEqual(layer.featureCount(), 4)

# ADD FEATURE

def test_AddFeature(self):
Binary file not shown.

0 comments on commit f4d38d4

Please sign in to comment.
You can’t perform that action at this time.