Sunday, January 27, 2013

Catching Line Changes (Undo/Redo)

Detecting modified lines properly with undo and redo required some effort.  The undo and redo functions were reimplemented in the EditBox class so that these operations could be controlled.  The key press event handler was modified to catch the undo and redo key sequences and to call these reimplemented functions.  A new slot was added to catch when a new undo command is added to the undo queue. This was necessary to catch when a line is modified due to an undo command.

To properly detect line changes, there are several things that undo and redo need to keep track of.  No changes are detected until the cursor has been moved from the line, so if all the changes are undone, then no line change gets detected.  Therefore, the number of changes made to a line are counted, where this count is decremented for an undo and incremented for a redo.  Only upon leaving the line does change get detected if this count is not zero.

Once a modified line is detect, if a further undo returns the cursor to the line, each undo is counted, so that when the cursor leaves the line, the modified line (from the undo) gets detected.  Any redo operation while the cursor is on the line adjust the line modification count accordingly.

The source code can be studied for exactly the steps required to accomplish this, which consists of various checks throughout.  A new line changed signal was added to EditBox, so modified lines are now emitted with the line number.  A slot was added to the MainWindow class that is connected to this signal.  For now, this slot function simply outputs the modified line number and text to the console.

There is still a problem when undoing entire lines where lines are actually deleted by the undo.  These changes will need to be emitted as line deletions.  The same signal can be used, but somehow needs to indicate the line is being delete.  There are similar issues when two lines are combined (the second line needs to be deleted), or when cutting, pasting or deleting multiple line selections.  There also needs to be a way to indicate when new lines are added.

[commit 6112a7ffd8] [commit f941edae59]