Использование дочерних / родительских элементов QUndoCommand для отправки нескольких команд одновременно для отмены стека

Я реализую редактируемое дерево со стеком отмены, используя 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

Решение

Необходимо вызывать реализацию по умолчанию QUndoCommand :: undo () и QUndoCommand :: redo () во вложенных реализациях.
В redo () реализация по умолчанию должна быть добавлена ​​перед обработкой данных, а в undo () — после того, как все данные дерева продолжаются.

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

Другие решения

Дочерний командный конструктор должен передать родитель аргумент для конструктора QUndoCommand:

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

Поскольку вы используете один и тот же класс для родителя и ребенка, вам также необходимо вызвать методы родительского вызова «Отменить + Повторить», как объяснил Дмитрий Курганский.

0

По вопросам рекламы [email protected]