[SOLVED] QUndoStack multiple steps



  • Hello,

    Could someone please help me to figure out how to do multiple undos, basically group undo or redo event together.

    Basically, I have a node with arrows pointing to a different node, when I delete it, I'm deleting it's arrows as well and putting all events in undo stack. Now when I press undo button I want the node and it's arrows to reappear, so far I have to click 3-4 times to get all the arrows back.

    I hope what I wrote makes sense, it's kinda difficult to explain.

    I looked into QUndoGroup, if I understood correctly it's for having multiple Undo stacks in your application rather than grouping events.

    Best Regards
    Raivis



  • I'm not sure if my solution is good enough, I don't like it myself but it works.

    Basically what I came up with was:

    1. Create a dummy command, which doesn't do anything, except gets into the undo stack
    2. When you want to set that this is the group, before and after your command was executed push the dummy command in.
    3. In your Redo and Undo functions, check if undo or redo text is equal to the dummy command, then just repeat undo +1 iteration until you get to the other dummy

    It's pretty difficult to explain in words, but the concept is very easy, and as I said I don't like it.
    Here some code snippets from my app about this issue:

    @void MainWindow::undoAction()
    {
    if(undoStack->canUndo())
    {
    if(undoStack->undoText() == "Undo Redo Group Node at (0, 0)")
    {
    undoStack->undo();
    while(undoStack->undoText() != "Undo Redo Group Node at (0, 0)") undoStack->undo();
    }
    undoStack->undo();
    }
    canIUndoOrRedo();
    }@
    Similar to undo, you have to do to redo as well.

    Here is have I group two commands together:
    @undoStack->push( new UndoRedoGroupCommand() );
    undoStack->push(new DeleteBlockCommand(currentItem,scene));
    undoStack->push(new DeleteBlockCommand(lineItem,scene));
    undoStack->push( new UndoRedoGroupCommand() );@

    Hopefully it will help someone, and if anybody comes up with a more proper way of grouping undos / redos together, I'm very eager to hear it.



  • Hi,

    [quote author="xcoder" date="1349364379"]Hello,
    Basically, I have a node with arrows pointing to a different node, when I delete it, I'm deleting it's arrows as well and putting all events in undo stack. Now when I press undo button I want the node and it's arrows to reappear, so far I have to click 3-4 times to get all the arrows back.
    [/quote]

    I know another method, but the node must "know" it's associated arrows. Something like this:

    @
    class Node
    {
    private:
    QList<Arrow *> myArrows;
    };
    @

    Now, when you deletes a node, you must store the node and it's arrows, then hide it. If you press redo button, the node and it's arrows is shown. Something like this:

    @
    class deleteNode
    {
    public:
    deleteNode()
    {
    // store node and it's arrows
    }

    void redo()
    {
    // hide node and it's arrows
    }

    void undo()
    {
    // show node and it's arrows
    }
    };
    @

    As an ilustrative example, you can use this files ("mQDeleteCommand.h":http://code.google.com/p/scaphandre/source/browse/trunk/src/commands/mQDeleteCommand.h and "mQDeleteCommand.cpp":http://code.google.com/p/scaphandre/source/browse/trunk/src/commands/mQDeleteCommand.cpp). Where Outsiders act as Arrows, and if arrows can connect with another arrows are stored recursively.

    I don't know if this is the proper way that you want, but is the way that I used.

    Mario.



  • Hi Mario,

    I looked at the code, looks interesting. I'll try to do it this way again, before I was trying to do the undo stack similar how you described it, but I failed :)

    Kind Regards
    Raivis



  • Hi xcoder,

    to achieve this grouping, the QUnbdoStack has the method beginMacro/endMacro.
    This is some code of mine, where I use it:

    @
    m_undoStack->beginMacro(tr("Paste data from clipboard to article categories"));
    int nRowMin = qMax(qMin(rTopLeft.row(), rBottomRight.row()), 0);
    updateOrAddEntries(pMimeData, nRowMin, tr("paste data to article categories"));
    m_undoStack->endMacro();
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.