My program consists of multiple QLineEdit
's in my QMainWindow
. The user can change the text in any QLineEdit
. Currently I can perform undo-redo by the default implementation for each QLineEdit
when the respective QLineEdit
is selected. However I want to add functionality so that when my undo *redo* buttons are pressed then, correspondingly the edited QLineEdit
performs undo/redo. i.e. say L1, L2, etc are my QLineEdit
's. Then the following operations are done by the user:
1. L2->text added
...
5. L5->text added
...
9. L3->text deleted
10. L5->undo (by selecting L5 & then "ctrl + z")
Now when the user presses Undo/Redo button as follows: 1. Undo -> Should undo the undo performed in step 10 2. Undo -> Should undo the text deleted in step 9 3. Redo -> Should redo the text deleted in step 9 4. Undo -> Should undo the operation done by step 8
Currently I can vaguely think of a mechanism of mainlining the History but it will be pretty tedious. So I would like to know if Qt provides me any inbuilt functionality for doing this? Thank You.
Qt provides an Undo/Redo framework.
You basically implement a command, derived from
QUndoCommand
, for each of the actions you want to make undoable/redoable, and then push them to aQUndoStack
. Later, the commands can be undone and redone by calling the corresponding slots on theQUndoStack
.Note that, when pushing a command on the stack, it is automatically redone, means executed for the first time. Sometimes this is not what you want, since the command might actually already have been executed - you would need to consider this in the implementation of your commands.
Qt has classes to help with undo, see
QUndoStack
. Each undoable step should be implemented as a subclass ofQUndoCommand
.What you're trying to achieve is not straightforward because you will need to bypass the internal undo stacks of your
QLineEdit
s. Here's one suggestion: listen for thefocusChanged
signal fromQApplication
. If one of your line edits has focus store it's content and connect to theQLineEdit::editingFinished()
signal. When this is received put a command on the stack with the old and the new text. The flaw in this approach is that you will not capture intermediate edits in a singleQLineEdit
. For example if you wanted to store 1) the user selecting text and hitting delete, then 2) typing some new text, as separate undoable steps you might need to start filtering key events and the logic can get quite complex. But that's the general approach.One way of implementing this is by using the 'Command' pattern. Qt provides an undo framework that follows this pattern: http://qt-project.org/doc/qt-4.8/tools-undoframework.html
To facilitate this, it you may need to make some changes to you program to make it a bit more MVC (model-view-controller). You'd have a data model that represents the contents of your form. The form itself is the view and the controller - any changes to the line edits made by the user would update the data model. The data model would implement changes to it using QUndoCommands which are pushed onto a QUndoStack from the Qt undo framework. When the state of the model changes (due to undo/redo), the UI would respond to the change and be updated to reflect the model's state.