Search code examples
c++mergeqt5undo-redocommand-pattern

Command pattern for undo/redo: when to NOT merge undo commands?


I'm implementing an undo/redo feature in our graphical Qt5-based app, using QUndoCommands which have a nice mergeWith() feature: for example, if the user repeatedly clicks the font size increase button on my app, rather than creating a ton of commands in the undo list, it just updates one command on the QUndoStack. So a single undo will go back to the original font size.

That's great, but there are times I don't want to automatically merge commands. For example, if I drag an item to a new location and drop it there, then drag the same item to another location: my app should create 2 move commands, not merge them both into one command.

So, here's a list of events that I think create a logical break, where the user will expect a command NOT to be merged with the next command, even if the next command changes the same property of the same object:

  • mouse release
  • widget lose focus
  • timer (after ??? seconds)
  • text typing, after ??? characters (or this can be handled with the timer?)
  • text typing, after certain keys are pressed, such as backspace?

As indicated by the question marks in my list, I'm not really sure in what situations to suppress merging commands. So my question is, are there any best practices in this regard? Where can I find them?


Solution

  • FWIW, I did not find any best practices, but for my software I suppressed merges on focus change (which in my app also occurs on mouse release on the graphics part). Additionally, for typing, I suppress merges if the input position changes in a way other that as expected for deleting or typing 1 character, and if the user switches between deleting characters and typing characters.

    I did not bother with the timer, or with maximum characters when typing.