Details
-
Bug
-
Resolution: Unresolved
-
P1: Critical
-
None
-
5.12.10
-
None
Description
Command compression does not work at all:
1) With parent command still need to call QUndoStack::undo() twice.
2) with beginMacro()/endMacro() does not work at all - undoes nothing and breaks undo sequence integrity so underlying object list crashes application with QList<T>::operator[]: "index out of range" error which does not happen if we do not compress commands.
So beginMacro()/endMacro() is not an equivalent to parent command like documentation mentions here: https://doc.qt.io/qt-5/qundostack.html#beginMacro.
I wonder if you tested this feature at all?
Sample code:
class RemoveItemCommand : public QUndoCommand { public: RemoveItemCommand(ItemListController *controller, Item *item, QUndoCommand *parent = nullptr); void undo() override; void redo() override; int id() const { return 1; } bool mergeWith(const QUndoCommand *command) { return true; } private: ItemListController *_controller; Item *_item; }; class MoveItemCommand : public QUndoCommand { public: MoveItemCommand(ItemListController *controller, int from, int to, QUndoCommand *parent = nullptr); void undo() override; void redo() override; int id() const { return 1; } bool mergeWith(const QUndoCommand *command) { return true; } private: ItemListController *_controller; int _from, _to; };
Undo stack variants (both do not work as expected):
Variant 1:
// Several commands can be compressed into a single command that can be undone and // redone in a single operation. This allows Item to move back to its original // position with undo. QUndoCommand *removeCommand = new QUndoCommand(); // Compressed command new MoveItemCommand(this, from, visualItems()->count() - 1, removeCommand); new RemoveItemCommand(this, removedItem, removeCommand); _undoStack.push(removeCommand);
Variant 2:
// A command macro is a sequence of commands, all of which are undone and redone // in one go. This allows Item to move back to its original position with undo. _undoStack.beginMacro("Remove Item"); _undoStack.push(new MoveItemCommand(this, from, visualItems()->count() - 1)); _undoStack.push(new RemoveItemCommand(this, removedItem)); _undoStack.endMacro();