使用QUndoCommand的子/父推送几个命令一次撤消堆栈

时间:2015-06-30 21:13:20

标签: c++ qt qt4 undo-redo

我正在使用QUndoStack实现具有撤消堆栈的可编辑树。删除节点需要删除所有它的后代。我正在使用子QUndoCommand:

部首:

class RemoveNodeCommand : QUndoCommand
{
public:
    RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent = 0);
    void undo();
    void redo();

private:
    NodeParams mParams;
    NodesContainer *mCont;
};

命令实施:

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);
}

树编辑类中的插槽:

RemoveNodeSlot(int id)
{
     mUndoStack->push( new RemoveNodeCommand(mContainer, id));
}

在QUndoStack文档中指出了 如果parent不为0,则此命令将附加到父级子列表中。
并且它是真的,每次创建新的子命令时,父命令的child_list都会增加。 然而,推父母不会导致推动所有孩子。 redo()仅为父节点调用 我做错了什么?我需要手动推送所有孩子吗?而且,由于我需要在单个撤消步骤中执行所有这些命令,因此我需要使用beginMacro和endMacro?但是这样,在QUndoCommand中持有指向子命令的指针是没有意义的。我想不是QT错误,而是我对撤销堆栈概念的误解。如何正确使用子命令机制?

2 个答案:

答案 0 :(得分:2)

必须在嵌套实现中调用QUndoCommand :: undo()和QUndoCommand :: redo()的默认实现。 在redo()中,必须在处理数据之前添加默认实现,在undo()之后 - 必须在所有树数据继续之后添加。

void RemoveNodeCommand::redo()
{
    QUndoCommand::redo();
    mCont->deleteNode(mParams);
}

答案 1 :(得分:0)

子命令构造函数需要将参数传递给QUndoCommand构造函数:

RemoveNodeCommand::RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent) 
: QUndoCommand(parent) {
// ...
}

因为您为父母和孩子使用单个课程,所以您还需要调用父母的撤消+重做方法,如Dmitry Kurgansky所解释的那样