Bug 180239 - stange text editing behaviour on undo
Summary: stange text editing behaviour on undo
Status: RESOLVED UPSTREAM
Alias: None
Product: kword
Classification: Miscellaneous
Component: general (show other bugs)
Version: git
Platform: Compiled Sources Linux
: NOR normal
Target Milestone: ---
Assignee: Thomas Zander
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-01-10 12:56 UTC by T Zachmann
Modified: 2009-01-26 17:42 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description T Zachmann 2009-01-10 12:56:13 UTC
Version:           svn (using KDE 4.1.3)
OS:                Linux
Installed from:    Compiled From Sources

I found a strange behavior when undo text changes.

To reporduce

o type aaa "Enter"
o type bbb "Enter"
o type ccc "Enter"
o type ddd "Arrow up Arrow up Pos1"
o select bbb by pressing Shit + Arrow Down
o delete selection by pressing bbb

o undo 
new you see 
aaa
bbb
ccc

but I would expect to see 

aaa
bbb
ccc
ddd
Comment 1 Pierre Stirnweiss 2009-01-17 22:32:43 UTC
This problem is caused by a bug in Qt:
when a selection is "replaced" by new text, the following happens within QTextDocumentPrivate:
- a call to remove is made, which creates a number of commands (depending whether the selection contains a linebreak or not)
- new characters are inserted, which also create a command

These commands are grouped together in the stack by a beginEditBlock/endEditBlock, so that when undo is requested, they are ALL undone.

The problem lies in that on each push of these commands, the signal undoCommandAdded is emited.

KOffice creates one undoCommand per signal on its own stack. All these are also grouped in a parent command.
When we hit undo, calls to QTextDocument::undo are done for each child undoCommands. The first time, QTextDocument undoes ALL the internal grouped commands, undoing the "replace" action completly. The second time QTextDocument::undo is called, the QTextDocument undoes the previous change (which in the case of the present bug was "type ddd". A further time would undo the previous command again (in this case the linebreak), and so on.

The signal undoCommandAdded should be emitted only once per beginEditBlock/endEditBlock. Perhaps by moving the emission from the appendUndoCommand method to the endEditBlock method somewhere?
Comment 2 Thomas Zander 2009-01-26 17:42:23 UTC
I wrote a fix for Qt and this patch fixes the issue (Will be in the 4.5 snapshots tonight)

diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 308e206..b141427 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -978,7 +978,6 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
     undoState++;
     emitUndoAvailable(true);
     emitRedoAvailable(false);
-    emit document()->undoCommandAdded();
 }

 void QTextDocumentPrivate::truncateUndoStack() {
@@ -1051,8 +1050,10 @@ void QTextDocumentPrivate::endEditBlock()
     if (--editBlock)
         return;

-    if (undoEnabled && undoState > 0)
+    if (undoEnabled && undoState > 0) {
         undoStack[undoState - 1].block = false;
+        emit document()->undoCommandAdded();
+    }

     if (framesDirty)
         scan_frames(docChangeFrom, docChangeOldLength, docChangeLength);