Results 1 to 12 of 12

Thread: Cancel to QUndoStack in redo()

  1. #1
    Join Date
    Mar 2011
    Posts
    25
    Thanks
    7
    Qt products
    Qt4

    Default Cancel to QUndoStack in redo()

    Could somebody confirm that it's not possible to abort the push to the stack if something happens in the redo() function? I only found one related post that didn't have an answer.

    Thanks in advance!

  2. #2
    Join Date
    Jun 2011
    Location
    Finland
    Posts
    164
    Thanks
    1
    Thanked 26 Times in 26 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Maemo/MeeGo

    Default Re: Cancel to QUndoStack in redo()

    Well you could always do some "hack" stuff. Get the pointer to the undoStack object in the constructor of your command. Use that object to call undo() and revert the stuff that failed in you redo(). This is the same command object, so it should be quite easy to do with some flags to handle it properly.
    Don't write a post just to thank someone, use "Thanks" button.

  3. The following user says thank you to Rachol for this useful post:

    iwatsu (21st September 2011)

  4. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Cancel to QUndoStack in redo()

    Why do you want to cancel a redo()?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #4
    Join Date
    Mar 2011
    Posts
    25
    Thanks
    7
    Qt products
    Qt4

    Default Re: Cancel to QUndoStack in redo()

    Quote Originally Posted by wysota View Post
    Why do you want to cancel a redo()?
    The operation that I'm doing in redo might fail in rare cases. If that happens I don't want to have a QUndoCommand that doesn't do anything (since the actual operation was never performed)

  6. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Cancel to QUndoStack in redo()

    Maybe you can check the condition before before you call redo?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. The following user says thank you to wysota for this useful post:

    iwatsu (21st September 2011)

  8. #6
    Join Date
    Mar 2011
    Posts
    25
    Thanks
    7
    Qt products
    Qt4

    Default Re: Cancel to QUndoStack in redo()

    yes, I might just have to refactor some code or try Rachol's hack.

    Thanks

  9. #7
    Join Date
    Jul 2011
    Posts
    3
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Cancel to QUndoStack in redo()

    This is a great topic. The QUndoCommand is a fine implementation of the command pattern, except for the fact that you can't roll back an incomplete redo operation. I have had to customize the redo to 'skipInitialRedo' - so I can add an undo command to the stack after the operation has completed successfully, and to prevent the stack from re-redoing when items are pushed onto it, at which point I've basically implemented my own command pattern and now have to integrate it with the undocommand.

    It would be awesome to not have to always hack the damn undo command - if I could just catch an exception around the undostack.push and then pop off a bad command, I think the undo system would be much more useful. This wouldn't be too hard to add, and would make the UndoCommand useful.

  10. #8
    Join Date
    Apr 2012
    Posts
    13
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Cancel to QUndoStack in redo()

    Why not subclass QUndoCommand, for example TransactionalUndoCommand. You don't want to hide everything in your program. It should be explicit that some commands (instances of TransactionalUndoCommand) can be rolled back or committed. Programming using exceptions is not always a good idea: a rolled back command may not be exceptional, but normal.

    For example, in my use, a TransactionalUndoCommand is used to ghost a dragged something. The command is executed, and the results are visible, but if the user's drag turns out to be small, it gets rolled back, meaning that the user changed their mind (but doesn't have to explicitly undo), else it is committed(), which pushes it on the command stack (but redo() doesn't execute it on this initial redo.)

    On the other hand, the Qt documentation should say what happens if the redo() that happens on a call to push() throws an exception. In other words, during push() does the command first get put on the stack, then redo() called on it, or vice versa? It must be the former, otherwise this thread wouldn't exist.

  11. #9
    Join Date
    Jul 2011
    Posts
    3
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Cancel to QUndoStack in redo()

    Quote Originally Posted by bootchk View Post
    Why not subclass QUndoCommand, for example TransactionalUndoCommand. You don't want to hide everything in your program. It should be explicit that some commands (instances of TransactionalUndoCommand) can be rolled back or committed. Programming using exceptions is not always a good idea: a rolled back command may not be exceptional, but normal.
    But then there are actual exceptional circumstances. I'm not the genius I'd like to be, so encountering an exception happens in complicated code and whether or not your command causes an exception or manages error codes, you can still end up with an ineffective command on your stack and no way to pop it off, unless you write your own command pattern.

    I could attribute it to laziness, but an exceptional design should encourage laziness - the lazy course is also the most efficient, and the most efficient course should also be the best practices of a library.

    Quote Originally Posted by bootchk View Post
    For example, in my use, a TransactionalUndoCommand is used to ghost a dragged something. The command is executed, and the results are visible, but if the user's drag turns out to be small, it gets rolled back, meaning that the user changed their mind (but doesn't have to explicitly undo), else it is committed(), which pushes it on the command stack (but redo() doesn't execute it on this initial redo.)
    I've done this before as well, and it is fine. What I find coming up in my work is a pattern where a simple derivation of a QUndoCommand would do the job, without any functors or custom logic for the when's and how's of the execution. I was using an undoCommand class that was a shell holding a list of functors, so I could drop it on the stack the post-populate it, but, again, that's a lot of ground work that needs to be done even for simple undo in a simple tool - I write a lot of simpler tools in PyQt.

    My latest trick is using a macro on the undo stack, dropping a bunch of stuff in there and rolling back if there is a fail. I still can't pop the stack, but I very much appreciate the simplicity in my code.

    It may come down to a simple matter of taste, but the undo system seems to be at 80% of where it could be, and I think that extra nudge would make it a lot more useful. If I get some time I may crack open the open-source code, add it, and see if it blows up in my face.

  12. #10
    Join Date
    Apr 2013
    Posts
    14
    Thanks
    3
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Cancel to QUndoStack in redo()

    Sorry to reply to such an old thread but I didn't want to create a new one.

    I have a very similar problem. I have a QGraphicsScene and all the operations on it are done using undo commands. I have a place in the application to import from various sources. I want the import to be a single undoable operation. So what I did was to surround the code that does the import in a QUndoStack::endMacro() and QUndoStack::beginMacro(). However, the user can choose to cancel the process in the middle in some cases (depending on where you import from) - in such cases I end up with an empty undo command. Here's some code to illustrate the situation:

    Qt Code:
    1. IImporter *importer;
    2. ...
    3. // set the importer to be a concrete instance
    4. ...
    5. undoStack->beginMacro("Import");
    6. ...
    7. if(!importer->importItems()) // a complex operation, many things could happen inside or none at all depending on the importer
    8. { // the operation didn't import anything or the user canceled
    9. ...
    10. undoStack->endMacro(); // I know this failed but I can't remove the empty added command from the stack
    11. return;
    12. }
    13. ...
    14. undoStack->endMacro();
    To copy to clipboard, switch view to plain text mode 

    I could bring the macro creation in each importer but that seems like a bad idea maintenance-wise (there are a lot of importers). Any suggestions? I agree that there should be a way to pop a command from the undo stack.

  13. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Cancel to QUndoStack in redo()

    Import first (the user can cancel here), create the command later passing it the imported data structure, activate the structure in redo(), deactivate it in undo(). You don't want to "reimport" data each time user does a redo, right?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #12
    Join Date
    Apr 2013
    Posts
    14
    Thanks
    3
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Cancel to QUndoStack in redo()

    Hmm OK, that makes sense. I'll have to use a modified version of your advice.

    Just to clarify, what is undone and redone right now is not the whole "import" process (i.e. parsing/interpreting the source) but just the operations on the scene (add, remove, set position, resize, etc.) since only those are implemented as undo commands. Because all of those commands are embedded in the scene itself and the importers work on it without knowledge of the undo commands, they have no control. Thankfully though, the scene itself can be set to not use undo actions internally so I'll use that before an import and follow your advice from there.

    Thanks

Similar Threads

  1. QAbstractItemModel with QUndoStack
    By No-Nonsense in forum Qt Programming
    Replies: 7
    Last Post: 28th October 2012, 17:15
  2. QUndoStack::index() crashed because of segmentation fault
    By learning_qt in forum Qt Programming
    Replies: 1
    Last Post: 24th January 2011, 18:45
  3. Replies: 0
    Last Post: 3rd August 2010, 11:47
  4. QTreeWidget and QUndoStack?
    By olihey in forum Qt Programming
    Replies: 0
    Last Post: 7th July 2010, 09:08
  5. QUndoStack problem
    By swiety in forum Qt Programming
    Replies: 1
    Last Post: 24th October 2007, 21:57

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.