Reputation: 96
I am implementing editable tree with undo stack, using QUndoStack. Remove node requires removing all it's offsprings. I am using child QUndoCommand for this:
Header:
class RemoveNodeCommand : QUndoCommand
{
public:
RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent = 0);
void undo();
void redo();
private:
NodeParams mParams;
NodesContainer *mCont;
};
Command implementation:
RemoveNodeCommand::RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent)
{
QList<int> offsprings_ids;
QUndoCommand *tmpcomm;
//Keep params of deleted notes to use in Undo if necessary
mParams = cont->getNogeParams();
mCont = cont;
//List all offsprings of node to be deleted
cont->getOffspringsIds(&offsprings_ids);
for(int co = 0; co < basket.size(); co++)
{
tmpcomm = new RemoveNodeCommand(cont, offsprings_ids.at(co), this);
}
}
void RemoveNodeCommand::redo()
{
mCont->deleteNode(mParams);
}
Slot in tree editing class:
RemoveNodeSlot(int id)
{
mUndoStack->push( new RemoveNodeCommand(mContainer, id));
}
In QUndoStack documentation it is indicated that
If parent is not 0, this command is appended to parent's child list.,
and it's true, child_list of parent command is increased each time new child command created.
However, pushing parent does not lead to pushing all it's children. redo() is called only for parent node.
What I'm doing wrong? Do I need to push all children manually? And, as I need all this commands inside single undo step, I'll need to use beginMacro and endMacro? But this way, holding pointers to children commands in QUndoCommand is senseless. I guess t is not QT fault, but my misunderstanding of undo stack conception. How to use child commands mechanism correctly?
Upvotes: 4
Views: 1197
Reputation: 131
The child command constructor needs to pass the parent argument to the QUndoCommand constructor:
RemoveNodeCommand::RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent)
: QUndoCommand(parent) {
// ...
}
Because you use a single class for parent and child you also need to call through to the parent's undo+redo methods as explained by Dmitry Kurgansky
Upvotes: 1
Reputation: 96
It is necessary to call default implementation of QUndoCommand::undo() and QUndoCommand::redo() in nested implementations. In redo() default implementation must be added before processing data, and in undo() - after all tree data proceed.
void RemoveNodeCommand::redo()
{
QUndoCommand::redo();
mCont->deleteNode(mParams);
}
Upvotes: 4