[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [calligra/text-undo-munichsprint] /: Fix stacking of undo/redo commands in the KoTextEditor.
From:       Pierre Stirnweiss <pstirnweiss () googlemail ! com>
Date:       2012-02-20 22:09:41
Message-ID: 20120220220941.6B4D0A60A6 () git ! kde ! org
[Download RAW message or body]

Git commit 071e4e41cb7959368d59b33d321ce88bd71600f0 by Pierre Stirnweiss.
Committed on 20/02/2012 at 23:04.
Pushed by pstirnweiss into branch 'text-undo-munichsprint'.

Fix stacking of undo/redo commands in the KoTextEditor.
Fix the DeleteCommand when deleting a selection with anchored object.
Fix PasteCommand when pasting over a selection.
Adapt ChangeStyleCommand to new framework.
Adapt Shape anchoring to new framework.

M  +2    -0    libs/flake/commands/KoShapeDeleteCommand.cpp
M  +88   -54   libs/kotext/KoTextEditor.cpp
M  +7    -2    libs/kotext/KoTextEditor.h
M  +4    -1    libs/kotext/KoTextEditor_p.h
M  +13   -8    libs/kotext/commands/ChangeStylesMacroCommand.cpp
M  +5    -2    libs/kotext/commands/DeleteAnchorsCommand.cpp
M  +6    -5    libs/kotext/commands/DeleteCommand.cpp
M  +4    -11   libs/kotext/commands/TextPasteCommand.cpp
M  +9    -2    libs/kundo2/kundo2stack.cpp
M  +4    -0    libs/kundo2/kundo2stack.h
M  +17   -1    words/part/dialogs/KWAnchoringProperties.cpp
M  +22   -2    words/part/dialogs/KWFrameDialog.cpp

http://commits.kde.org/calligra/071e4e41cb7959368d59b33d321ce88bd71600f0

diff --git a/libs/flake/commands/KoShapeDeleteCommand.cpp \
b/libs/flake/commands/KoShapeDeleteCommand.cpp index 519f047..5b194dc 100644
--- a/libs/flake/commands/KoShapeDeleteCommand.cpp
+++ b/libs/flake/commands/KoShapeDeleteCommand.cpp
@@ -24,6 +24,8 @@
 
 #include <klocale.h>
 
+#include <KDebug>
+
 class KoShapeDeleteCommand::Private
 {
 public:
diff --git a/libs/kotext/KoTextEditor.cpp b/libs/kotext/KoTextEditor.cpp
index 3c141c7..8ac671b 100644
--- a/libs/kotext/KoTextEditor.cpp
+++ b/libs/kotext/KoTextEditor.cpp
@@ -94,7 +94,8 @@ Q_DECLARE_METATYPE(QTextFrame*)
 KoTextEditor::Private::Private(KoTextEditor *qq, QTextDocument *document)
     : q(qq)
     , document (document)
-    , headCommand(0)
+    , addNewCommand(true)
+    , inCustomCommand(0)
     , editProtectionCached(false)
 {
     caret = QTextCursor(document);
@@ -121,7 +122,9 @@ void KoTextEditor::Private::documentCommandAdded()
             QTextDocument *doc = m_document.data();
             if (doc == 0)
                 return;
+            KoTextDocument(doc).textEditor()->cursor()->beginEditBlock(); //These \
are needed to get around a Qt bug in 4.8. A change through a QTextCursor outside an \
editBlock will crash (cursor position calculation on non layed out doc).  \
doc->undo(KoTextDocument(doc).textEditor()->cursor()); +            \
KoTextDocument(doc).textEditor()->cursor()->endEditBlock();  \
m_p->emitTextFormatChanged();  }
 
@@ -129,7 +132,9 @@ void KoTextEditor::Private::documentCommandAdded()
             QTextDocument *doc = m_document.data();
             if (doc == 0)
                 return;
+            KoTextDocument(doc).textEditor()->cursor()->beginEditBlock(); //Same as \
above  doc->redo(KoTextDocument(doc).textEditor()->cursor());
+            KoTextDocument(doc).textEditor()->cursor()->endEditBlock();
             m_p->emitTextFormatChanged();
         }
 
@@ -137,35 +142,50 @@ void KoTextEditor::Private::documentCommandAdded()
         KoTextEditor::Private *m_p;
     };
 
-    //kDebug() << "editor state: " << editorState << " headcommand: " << \
                headCommand;
-    if (!headCommand || editorState == NoOp) {
-        headCommand = new KUndo2Command(commandTitle);
+    if (commandStack.isEmpty()) {
+        commandStack.push(new KUndo2Command(commandTitle, \
!commandStack.isEmpty()?commandStack.top():0));  if \
                (KoTextDocument(document).undoStack()) {
-            //kDebug() << "pushing head: " << headCommand->text();
-            KoTextDocument(document).undoStack()->push(headCommand);
+            KoTextDocument(document).undoStack()->push(commandStack.top());
         }
+        addNewCommand = false;
     }
-    else if ((editorState == KeyPress || editorState == Delete) && \
                headCommand->childCount()) {
-        headCommand = new KUndo2Command(commandTitle);
+    else if (addNewCommand) {
+        commandStack.push(new KUndo2Command(commandTitle, \
!commandStack.isEmpty()?commandStack.top():0)); +        addNewCommand = false;
+    }
+    else if ((editorState == KeyPress || editorState == Delete) && \
!commandStack.isEmpty() && commandStack.top()->childCount()) { +        \
commandStack.pop(); +        commandStack.push(new KUndo2Command(commandTitle, \
!commandStack.isEmpty()?commandStack.top():0));  if \
                (KoTextDocument(document).undoStack()) {
-            //kDebug() << "pushing head: " << headCommand->text();
-            KoTextDocument(document).undoStack()->push(headCommand);
+            KoTextDocument(document).undoStack()->push(commandStack.top());
         }
     }
 
-    new UndoTextCommand(document, this, headCommand);
+    new UndoTextCommand(document, this, commandStack.top());
 }
 
 void KoTextEditor::Private::updateState(KoTextEditor::Private::State newState, \
QString title)  {
-    if (editorState == Custom && newState !=NoOp)
+    if (editorState == Custom && newState != NoOp) {
+        addNewCommand = true;
+        if (!title.isEmpty())
+            commandTitle = title;
+        else
+            commandTitle = i18n("Text");
+        return;
+    }
+    if (newState == NoOp && !commandStack.isEmpty()) {
+        commandStack.pop();
+        addNewCommand = true;
+        if (commandStack.isEmpty()) {
+            editorState = NoOp;
+        }
         return;
-    //kDebug() << "updateState from: " << editorState << " to: " << newState;
+    }
     if (editorState != newState || commandTitle != title) {
-        if (headCommand /*&& headCommand->childCount() && \
                KoTextDocument(document).undoStack()*/) {
-            //kDebug() << "reset headCommand";
-            //            KoTextDocument(document).undoStack()->push(headCommand);
-            headCommand = 0;
+        if (!commandStack.isEmpty()) {
+            commandStack.pop();
+            addNewCommand = true;
         }
     }
     editorState = newState;
@@ -173,7 +193,6 @@ void \
KoTextEditor::Private::updateState(KoTextEditor::Private::State newState, Q  \
commandTitle = title;  else
         commandTitle = i18n("Text");
-    //kDebug() << "commandTitle is now: " << commandTitle;
 }
 
 bool KoTextEditor::Private::deleteInlineObjects(bool backwards)
@@ -347,26 +366,37 @@ QTextCursor* KoTextEditor::cursor()
 
 void KoTextEditor::addCommand(KUndo2Command *command)
 {
+    ++d->inCustomCommand;
     d->updateState(KoTextEditor::Private::Custom, \
                (!command->text().isEmpty())?command->text():i18n("Text"));
-    //kDebug() << "will push the custom command: " << command->text();
-    d->headCommand = command;
-    KUndo2QStack *stack = KoTextDocument(d->document).undoStack();
-    if (stack) {
-        stack->push(command);
-    } else {
+    d->addNewCommand = false;
+    if (d->commandStack.isEmpty()) {
+        d->commandStack.push(command);
+        KUndo2QStack *stack = KoTextDocument(d->document).undoStack();
+        if (stack && !command->hasParent()) {
+            stack->push(command);
+        } else {
+            command->redo();
+        }
+    }
+    else {
+        d->commandStack.push(command);
         command->redo();
     }
-    //kDebug() << "custom command pushed";
+    while(d->commandStack.top() != command) { //clean auto generated commands which \
at that point should not be here anymore. in particular insertText being open ended \
will not have been cleared. +        d->commandStack.pop();
+    }
+    d->updateState(KoTextEditor::Private::NoOp);
+    --d->inCustomCommand;
 }
 
 void KoTextEditor::instantlyExecuteCommand(KUndo2Command *command)
 {
     d->updateState(KoTextEditor::Private::Custom, \
                (!command->text().isEmpty())?command->text():i18n("Text"));
-    //kDebug() << "will push the custom command: " << command->text();
-    d->headCommand = command; // So any text it does is store as sub commands
     command->redo();
     // instant replay done let's not keep it dangling
-    d->updateState(KoTextEditor::Private::NoOp);
+    if (!command->hasParent()) {
+        d->updateState(KoTextEditor::Private::NoOp);
+    }
 }
 
 void KoTextEditor::registerTrackedChange(QTextCursor &selection, KoGenChange::Type \
changeType, QString title, QTextFormat& format, QTextFormat& prevFormat, bool \
applyToWholeBlock) @@ -836,8 +866,8 @@ public:
 
         QList<QTextCharFormat>::Iterator it = m_formats.begin();
         foreach(QTextCursor cursor, m_cursors) {
-            cursor.setCharFormat(*it);
             QTextFormat prevFormat(cursor.charFormat());
+            cursor.setCharFormat(*it);
             editor()->registerTrackedChange(cursor, KoGenChange::FormatChange, \
i18n("Set Character Style"), *it, prevFormat, false);  ++it;
         }
@@ -1068,6 +1098,8 @@ KoInlineObject *KoTextEditor::insertIndexMarker()
         return 0;
     }
 
+    d->updateState(KoTextEditor::Private::Custom, i18n("Insert Index"));
+
     int startPosition = d->caret.position();
 
     if (d->caret.blockFormat().hasProperty(KoParagraphStyle::HiddenByTable)) {
@@ -1091,7 +1123,6 @@ KoInlineObject *KoTextEditor::insertIndexMarker()
     if (block.text()[ d->caret.position() - block.position()].isSpace())
         return 0; // can't insert one on a whitespace as that does not indicate a \
word.  
-    d->updateState(KoTextEditor::Private::Custom, i18n("Insert Index"));
     KoTextLocator *tl = new KoTextLocator();
     KoTextDocument(d->document).inlineTextObjectManager()->insertInlineObject(d->caret, \
tl);  d->updateState(KoTextEditor::Private::NoOp);
@@ -1163,7 +1194,7 @@ void KoTextEditor::updateInlineObjectPosition(int start, int \
end)  void KoTextEditor::removeAnchors(const QList<KoTextAnchor*> &anchors, \
KUndo2Command *parent)  {
     Q_ASSERT(parent);
-    instantlyExecuteCommand(new DeleteAnchorsCommand(anchors, d->document, parent));
+    addCommand(new DeleteAnchorsCommand(anchors, d->document, parent));
 }
 
 void KoTextEditor::insertFrameBreak()
@@ -1483,18 +1514,14 @@ void KoTextEditor::deleteChar()
         }
     }
 
-    if (!d->deleteInlineObjects(false) || d->caret.hasSelection()) {
-        d->updateState(KoTextEditor::Private::Delete, i18n("Delete"));
+    QTextCharFormat charFormat = d->caret.charFormat();
 
-        QTextCharFormat charFormat = d->caret.charFormat();
-
-        if (!d->caret.hasSelection())
-            d->caret.movePosition(QTextCursor::NextCharacter, \
QTextCursor::KeepAnchor); +    if (!d->caret.hasSelection())
+        d->caret.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
 
-        d->caret.deleteChar();
+    d->caret.deleteChar();
 
-        d->caret.setCharFormat(charFormat);
-    }
+    d->caret.setCharFormat(charFormat);
 
     emit cursorPositionChanged();
 }
@@ -1528,18 +1555,14 @@ void KoTextEditor::deletePreviousChar()
         }
     }
 
-    if (!d->deleteInlineObjects(false) || d->caret.hasSelection()) {
-        d->updateState(KoTextEditor::Private::Delete, i18n("Delete"));
-
-        QTextCharFormat charFormat = d->caret.charFormat();
+    QTextCharFormat charFormat = d->caret.charFormat();
 
-        if (!d->caret.hasSelection())
-            d->caret.movePosition(QTextCursor::PreviousCharacter, \
QTextCursor::KeepAnchor); +    if (!d->caret.hasSelection())
+        d->caret.movePosition(QTextCursor::PreviousCharacter, \
QTextCursor::KeepAnchor);  
-        d->caret.deleteChar();
+    d->caret.deleteChar();
 
-        d->caret.setCharFormat(charFormat);
-    }
+    d->caret.setCharFormat(charFormat);
     emit cursorPositionChanged();
 }
 
@@ -1980,10 +2003,18 @@ void KoTextEditor::insertText(const QString &text)
         return;
     }
 
-    d->updateState(KoTextEditor::Private::KeyPress, i18nc("(qtundo-format)", \
"Typing")); +    bool hasSelection = d->caret.hasSelection();
+//    if (!hasSelection) {
+        d->updateState(KoTextEditor::Private::KeyPress, i18nc("(qtundo-format)", \
"Typing")); +//    }
+//    else {
+//        beginEditBlock();
+//        d->commandTitle = i18nc("(qtundo-format)", "Typing");
+//        addCommand(new );
+//    }
 
     //first we make sure that we clear the inlineObject charProperty, if we have no \
                selection
-    if (!d->caret.hasSelection() && \
d->caret.charFormat().hasProperty(KoCharacterStyle::InlineInstanceId)) +    if \
(!hasSelection && d->caret.charFormat().hasProperty(KoCharacterStyle::InlineInstanceId))
  d->clearCharFormatProperty(KoCharacterStyle::InlineInstanceId);
 
     int startPosition = d->caret.position();
@@ -2374,17 +2405,20 @@ const QTextTable *KoTextEditor::currentTable () const
     return d->caret.currentTable();
 }
 
-
 void KoTextEditor::beginEditBlock()
 {
-    d->updateState(KoTextEditor::Private::Custom);
+    if (!d->inCustomCommand) {
+        d->updateState(KoTextEditor::Private::Custom);
+    }
     d->caret.beginEditBlock();
 }
 
 void KoTextEditor::endEditBlock()
 {
     d->caret.endEditBlock();
-    d->updateState(KoTextEditor::Private::NoOp);
+    if (!d->inCustomCommand) {
+        d->updateState(KoTextEditor::Private::NoOp);
+    }
 }
 
 #include <KoTextEditor.moc>
diff --git a/libs/kotext/KoTextEditor.h b/libs/kotext/KoTextEditor.h
index 689051b..2e58056 100644
--- a/libs/kotext/KoTextEditor.h
+++ b/libs/kotext/KoTextEditor.h
@@ -307,8 +307,6 @@ public slots:
 
     bool atStart() const;
 
-    void beginEditBlock();
-
     QTextBlock block() const;
 
     QTextCharFormat blockCharFormat() const;
@@ -323,12 +321,19 @@ public slots:
 
     int columnNumber() const;
 
+//the two following methods are called by the DeleteCommand. They are not meant to \
be called directly. Do it with extreme care, if and only if you perfectly understand \
the undo/redo framework.  void deleteChar();
 
     void deletePreviousChar();
 
     const QTextDocument *document() const;
 
+    //Starts a new custom command. Everything between these two is one custom \
command. These should not be called from whithin a KUndo2Command +//    void \
beginCustomCommand(); +//    void endCustomCommand();
+
+    //Same as Qt, only to be used inside KUndo2Commands
+    void beginEditBlock();
     void endEditBlock();
 
     bool hasComplexSelection() const;
diff --git a/libs/kotext/KoTextEditor_p.h b/libs/kotext/KoTextEditor_p.h
index 77725f3..2a188a6 100644
--- a/libs/kotext/KoTextEditor_p.h
+++ b/libs/kotext/KoTextEditor_p.h
@@ -31,6 +31,7 @@
 #include <KLocale>
 #include <kdebug.h>
 
+#include <QStack>
 #include <QTextBlock>
 #include <QTextDocument>
 #include <QTimer>
@@ -62,7 +63,9 @@ public:
     KoTextEditor *q;
     QTextCursor caret;
     QTextDocument *document;
-    KUndo2Command *headCommand;
+    QStack<KUndo2Command*> commandStack;
+    bool addNewCommand;
+    int inCustomCommand;
     QString commandTitle;
 
     State editorState;
diff --git a/libs/kotext/commands/ChangeStylesMacroCommand.cpp \
b/libs/kotext/commands/ChangeStylesMacroCommand.cpp index 34c3822..41a7f99 100644
--- a/libs/kotext/commands/ChangeStylesMacroCommand.cpp
+++ b/libs/kotext/commands/ChangeStylesMacroCommand.cpp
@@ -23,8 +23,10 @@
 #include "ChangeStylesCommand.h"
 #include "KoCharacterStyle.h"
 #include "KoParagraphStyle.h"
+#include "ChangeFollower.h"
 
 #include <KoTextDocument.h>
+#include <KoTextEditor.h>
 
 #include <KLocale>
 
@@ -48,13 +50,6 @@ ChangeStylesMacroCommand::~ChangeStylesMacroCommand()
 //     finally the new styles are applied to the documents through super::redo()
 void ChangeStylesMacroCommand::redo()
 {
-    if (m_first) {
-        foreach(ChangeFollower *cf, m_changeFollowers) {
-            new ChangeStylesCommand(cf, m_origCharacterStyles, \
                m_origParagraphStyles, m_changedStyles, this);
-        }
-        m_first = false;
-    }
-
     foreach(KoCharacterStyle *newStyle, m_changedCharacterStyles) {
         int id = newStyle->styleId();
         m_styleManager->characterStyle(id)->copyProperties(newStyle);
@@ -69,7 +64,17 @@ void ChangeStylesMacroCommand::redo()
         emit m_styleManager->styleAltered(m_styleManager->paragraphStyle(id));
     }
 
-    KUndo2Command::redo(); // calls redo on all children
+    if (m_first) {
+        foreach(ChangeFollower *cf, m_changeFollowers) {
+            ChangeStylesCommand *cmd = new ChangeStylesCommand(cf, \
m_origCharacterStyles, m_origParagraphStyles, m_changedStyles, this); +
+            //add and execute it's redo
+            KoTextDocument(cf->document()).textEditor()->addCommand(cmd);
+        }
+        m_first = false;
+    } else {
+        KUndo2Command::redo(); // calls redo on all children
+    }
 }
 
 void ChangeStylesMacroCommand::undo()
diff --git a/libs/kotext/commands/DeleteAnchorsCommand.cpp \
b/libs/kotext/commands/DeleteAnchorsCommand.cpp index 621829f..4d4cbcf 100644
--- a/libs/kotext/commands/DeleteAnchorsCommand.cpp
+++ b/libs/kotext/commands/DeleteAnchorsCommand.cpp
@@ -24,6 +24,8 @@
 #include "KoTextDocument.h"
 #include "KoInlineTextObjectManager.h"
 
+#include <KDebug>
+
 bool sortAnchor(KoTextAnchor *a1, KoTextAnchor *a2)
 {
     return a1->positionInDocument() > a2->positionInDocument();
@@ -59,7 +61,9 @@ void DeleteAnchorsCommand::redo()
         foreach (KoTextAnchor *anchor, m_anchors) {
             QTextCursor cursor(m_document);
             cursor.setPosition(anchor->positionInDocument());
-            cursor.deleteChar();
+//            cursor.beginEditBlock();
+            cursor.deleteChar(); //this works also when the DeleteCommand further \
deletes its selection, which contained this char. Odd +//            \
cursor.endEditBlock();  }
     }
     KoInlineTextObjectManager *manager = \
KoTextDocument(m_document).inlineTextObjectManager(); @@ -83,4 +87,3 @@ void \
DeleteAnchorsCommand::undo()  KUndo2Command::undo();
     m_deleteAnchors = false;
 }
-
diff --git a/libs/kotext/commands/DeleteCommand.cpp \
b/libs/kotext/commands/DeleteCommand.cpp index 2a4527d..b960505 100644
--- a/libs/kotext/commands/DeleteCommand.cpp
+++ b/libs/kotext/commands/DeleteCommand.cpp
@@ -122,11 +122,13 @@ void DeleteCommand::doDelete()
 
     //Now finally Delete the selected text. Don't use selection.deleteChar() direct
     //cause the Texteditor needs to know about the changes too.
-    if (m_mode == PreviousChar)
+    if (m_mode == PreviousChar) {
         textEditor->deletePreviousChar();
-    else
+    }
+    else {
         textEditor->deleteChar();
- }
+    }
+}
 
 void DeleteCommand::deleteInlineObjects()
 {
@@ -168,7 +170,7 @@ void DeleteCommand::deleteTextAnchor(KoInlineObject *object)
         KoTextAnchor *anchor = dynamic_cast<KoTextAnchor *>(object);
         if (anchor) {
             KoShape *shape = anchor->shape();
-            KUndo2Command *shapeDeleteCommand = \
m_shapeController->removeShape(shape); +            KUndo2Command *shapeDeleteCommand \
= m_shapeController->removeShape(shape, this);  shapeDeleteCommand->redo();
             m_shapeDeleteCommands.push_back(shapeDeleteCommand);
         }
@@ -295,4 +297,3 @@ DeleteCommand::~DeleteCommand()
             delete command;
     }
 }
-
diff --git a/libs/kotext/commands/TextPasteCommand.cpp \
b/libs/kotext/commands/TextPasteCommand.cpp index 6b9de68..85a56c9 100644
--- a/libs/kotext/commands/TextPasteCommand.cpp
+++ b/libs/kotext/commands/TextPasteCommand.cpp
@@ -78,16 +78,15 @@ void TextPasteCommand::redo()
     if (!m_first) {
         KUndo2Command::redo();
     } else {
-        //kDebug() << "begin paste command";
-        editor->beginEditBlock();
+        editor->beginEditBlock(); //this is needed so Qt does not merge successive \
paste actions together  m_first = false;
         if (editor->hasSelection()) { //TODO
             // XXX: this was m_tool->m_actionShowChanges.isChecked -- but shouldn't \
we check  // whether we should record changes here, instead of showing?
             if (textDocument.changeTracker()->recordChanges()) {
-                editor->addCommand(new \
ChangeTrackedDeleteCommand(ChangeTrackedDeleteCommand::NextChar, m_document.data(), \
m_shapeController)); +                editor->addCommand(new \
ChangeTrackedDeleteCommand(ChangeTrackedDeleteCommand::NextChar, m_document.data(), \
m_shapeController, this));  } else {
-                editor->addCommand(new DeleteCommand(DeleteCommand::NextChar, \
m_document.data(), m_shapeController)); +                editor->addCommand(new \
DeleteCommand(DeleteCommand::NextChar, m_document.data(), m_shapeController, this));  \
}  }
 
@@ -114,10 +113,8 @@ void TextPasteCommand::redo()
                 }
 #endif
 
-                //kDebug() << "pasting odf text";
                 KoTextPaste paste(editor, m_shapeController, rdfModel);
                 paste.paste(odfType, m_mimeData);
-                //kDebug() << "done with pasting odf";
 
 #ifdef SHOULD_BUILD_RDF
                 if (m_rdf) {
@@ -129,14 +126,10 @@ void TextPasteCommand::redo()
 #endif
             }
         } else if (!m_pasteAsText && m_mimeData->hasHtml()) {
-            //kDebug() << "pasting html";
             editor->insertHtml(m_mimeData->html());
-            //kDebug() << "done with pasting";
         } else if (m_pasteAsText || m_mimeData->hasText()) {
-            //kDebug() << "pasting text";
             editor->insertText(m_mimeData->text());
-            //kDebug() << "done with pasting";
         }
-        editor->endEditBlock();
+        editor->endEditBlock(); //see above beginEditBlock
     }
 }
diff --git a/libs/kundo2/kundo2stack.cpp b/libs/kundo2/kundo2stack.cpp
index 48d6625..bf63eea 100644
--- a/libs/kundo2/kundo2stack.cpp
+++ b/libs/kundo2/kundo2stack.cpp
@@ -111,11 +111,13 @@
     \sa ~KUndo2Command()
 */
 
-KUndo2Command::KUndo2Command(const QString &text, KUndo2Command *parent)
+KUndo2Command::KUndo2Command(const QString &text, KUndo2Command *parent):
+    m_hasParent(parent != 0)
 {
     d = new KUndo2CommandPrivate;
-    if (parent != 0)
+    if (parent != 0) {
         parent->d->child_list.append(this);
+    }
     setText(text);
 }
 
@@ -310,6 +312,11 @@ const KUndo2Command *KUndo2Command::child(int index) const
     return d->child_list.at(index);
 }
 
+bool KUndo2Command::hasParent()
+{
+    return m_hasParent;
+}
+
 #endif // QT_NO_UNDOCOMMAND
 
 #ifndef QT_NO_UNDOSTACK
diff --git a/libs/kundo2/kundo2stack.h b/libs/kundo2/kundo2stack.h
index c0539fe..30ff215 100644
--- a/libs/kundo2/kundo2stack.h
+++ b/libs/kundo2/kundo2stack.h
@@ -78,9 +78,13 @@ public:
     int childCount() const;
     const KUndo2Command *child(int index) const;
 
+    bool hasParent();
+
 private:
     Q_DISABLE_COPY(KUndo2Command)
     friend class KUndo2QStack;
+
+    bool m_hasParent;
 };
 
 #endif // QT_NO_UNDOCOMMAND
diff --git a/words/part/dialogs/KWAnchoringProperties.cpp \
b/words/part/dialogs/KWAnchoringProperties.cpp index c742e26..d5f09a4 100644
--- a/words/part/dialogs/KWAnchoringProperties.cpp
+++ b/words/part/dialogs/KWAnchoringProperties.cpp
@@ -29,6 +29,7 @@
 #include <KoTextShapeData.h>
 #include <KoShapeContainer.h>
 #include <commands/ChangeAnchorPropertiesCommand.h>
+#include <KoTextDocument.h>
 
 #include <kundo2command.h>
 
@@ -561,7 +562,22 @@ void KWAnchoringProperties::save(KUndo2Command *macro)
             anchorProperties.setHorizontalPos(KoTextAnchor::HorizontalPos(m_horizPos));
                
             anchorProperties.setVerticalPos(KoTextAnchor::VerticalPos(m_vertPos));
 
-            new ChangeAnchorPropertiesCommand(anchor, anchorProperties, container, \
macro); +            ChangeAnchorPropertiesCommand *cmd = new \
ChangeAnchorPropertiesCommand(anchor, anchorProperties, container, macro); +
+            KoTextShapeDataBase *textData = 0;
+            KoShape *oldParent = anchor->shape()->parent();
+            if (oldParent) {
+                textData = \
qobject_cast<KoTextShapeDataBase*>(oldParent->userData()); +            } else  if \
(container) { +                textData = \
qobject_cast<KoTextShapeDataBase*>(container->userData()); +            }
+
+            if (textData) {
+                KoTextDocument doc(textData->document());
+                doc.textEditor()->addCommand(cmd); //will call redo too
+            } else {
+                cmd->redo();
+            }
         }
     }
 
diff --git a/words/part/dialogs/KWFrameDialog.cpp \
b/words/part/dialogs/KWFrameDialog.cpp index 0fcc0b7..99d8283 100644
--- a/words/part/dialogs/KWFrameDialog.cpp
+++ b/words/part/dialogs/KWFrameDialog.cpp
@@ -76,10 +76,30 @@ void KWFrameDialog::okClicked()
         m_frameConnectSelector->save();
 
     // create the master command
-    KUndo2Command *macro = new KUndo2Command(i18nc("(qtundo-format)", "Change Shape \
Properties")); +    class MasterCommand : public KUndo2Command
+    {
+    public:
+        MasterCommand(KWAnchoringProperties *anchoringProperties)
+            : KUndo2Command(i18nc("(qtundo-format)", "Change Shape Properties"))
+            , m_anchoringProperties(anchoringProperties)
+            , m_first(true)
+        {}
+
+        void redo() {
+            if (m_first) {
+                m_first = false;
+                m_anchoringProperties->save(this);
+            }
+           KUndo2Command::redo();
+        }
+        KWAnchoringProperties *m_anchoringProperties;
+        bool m_first;
+    };
+
+    MasterCommand *macro = new MasterCommand(m_anchoringProperties);
 
+    //these we can just add as children as they don't deal with kotexteditor
     m_generalFrameProperties->save();
-    m_anchoringProperties->save(macro);
     m_runAroundProperties->save(macro);
 
     m_canvas->addCommand(macro);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic