rendered paste bodyIndex: koffice/plugins/textshape/TextTool.cpp===================================================================--- koffice/plugins/textshape/TextTool.cpp (revision 1046549)+++ koffice/plugins/textshape/TextTool.cpp (working copy)@@ -36,6 +36,8 @@ #include "commands/ChangeListCommand.h" #include "commands/ChangeListLevelCommand.h" #include "commands/ListItemNumberingCommand.h"+#include "commands/ShowChangesCommand.h"+#include "commands/DeleteCommand.h" #include <KoExecutePolicy.h> #include <KoCanvasBase.h>@@ -378,10 +380,10 @@ action->setWhatsThis(i18n("Change paragraph margins, text flow, borders, bullets, numbering etc.<p>Select text in multiple paragraphs to change the formatting of all selected paragraphs.<p>If no text is selected, the paragraph where the cursor is located will be changed.</p>")); connect(action, SIGNAL(triggered()), this, SLOT(formatParagraph())); - action = new KAction(i18n("Record"), this);- action->setCheckable(true);- addAction("edit_record_changes", action);- connect(action, SIGNAL(triggered(bool)), this, SLOT(toggleTrackChanges(bool)));+ m_actionShowChanges = new KAction(i18n("Record"), this);+ m_actionShowChanges->setCheckable(true);+ addAction("edit_record_changes", m_actionShowChanges);+ connect(m_actionShowChanges, SIGNAL(triggered(bool)), this, SLOT(toggleTrackChanges(bool))); action = new KAction(i18n("Style Manager"), this); action->setShortcut(Qt::ALT + Qt::CTRL + Qt::Key_S);@@ -749,7 +751,10 @@ void TextTool::deleteSelection() {- m_textEditor->deleteChar();+ if(m_actionShowChanges->isChecked())+ m_textEditor->addCommand(new DeleteCommand(DeleteCommand::NextChar, this));+ else+ m_textEditor->deleteChar(); editingPluginEvents(); } @@ -899,7 +904,10 @@ } else if (m_textEditor->position() > 0 || m_textEditor->hasSelection()) { if (!m_textEditor->hasSelection() && event->modifiers() & Qt::ControlModifier) // delete prev word. m_textEditor->movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);- m_textEditor->deletePreviousChar();+ if(m_actionShowChanges->isChecked())+ m_textEditor->addCommand(new DeleteCommand(DeleteCommand::PreviousChar, this));+ else+ m_textEditor->deletePreviousChar(); editingPluginEvents(); } ensureCursorVisible();@@ -915,7 +923,10 @@ m_textEditor->movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor); // the event only gets through when the Del is not used in the app // if the app forwards Del then deleteSelection is used- m_textEditor->deleteChar();+ if(m_actionShowChanges->isChecked())+ m_textEditor->addCommand(new DeleteCommand(DeleteCommand::NextChar, this));+ else+ m_textEditor->deleteChar(); editingPluginEvents(); } else if ((event->key() == Qt::Key_Left) && (event->modifiers() | Qt::ShiftModifier) == Qt::ShiftModifier) moveOperation = QTextCursor::Left;@@ -1062,7 +1073,10 @@ if (event->replacementLength() > 0) { m_textEditor->setPosition(m_textEditor->position() + event->replacementStart()); for (int i = event->replacementLength(); i > 0; --i) {- m_textEditor->deleteChar();+ if(m_actionShowChanges->isChecked())+ m_textEditor->addCommand(new DeleteCommand(DeleteCommand::NextChar, this));+ else+ m_textEditor->deleteChar(); } } if (! event->commitString().isEmpty()) {@@ -1621,20 +1635,7 @@ void TextTool::toggleTrackChanges(bool on)//TODO transfer this in KoTextEditor {- if (m_changeTracker){- m_changeTracker->setEnabled(on);- m_changeTracker->setDisplayDeleted(on);- QTextCharFormat format = m_textEditor->charFormat();- format.clearProperty(KoCharacterStyle::ChangeTrackerId);- m_textEditor->setCharFormat(format);- const QTextDocument *doc = m_textEditor->document();- Q_ASSERT(doc);- KoTextDocumentLayout *lay = qobject_cast<KoTextDocumentLayout*>(doc->documentLayout());- if(lay)- lay->scheduleLayout();- }- m_textTyping = false;- m_textDeleting = false;+ m_textEditor->addCommand(new ShowChangesCommand(on, this)); } void TextTool::selectAll()Index: koffice/plugins/textshape/CMakeLists.txt===================================================================--- koffice/plugins/textshape/CMakeLists.txt (revision 1046549)+++ koffice/plugins/textshape/CMakeLists.txt (working copy)@@ -59,6 +59,8 @@ commands/TextCommandBase.cpp commands/TextPasteCommand.cpp commands/TextCutCommand.cpp+ commands/ShowChangesCommand.cpp+ commands/DeleteCommand.cpp ) kde4_add_ui_files(textshape_SRCSIndex: koffice/plugins/textshape/commands/TextCutCommand.cpp===================================================================--- koffice/plugins/textshape/commands/TextCutCommand.cpp (revision 1046549)+++ koffice/plugins/textshape/commands/TextCutCommand.cpp (working copy)@@ -21,7 +21,8 @@ #include <KoTextEditor.h> #include <TextTool.h>-+#include "DeleteCommand.h"+#include <KAction> #include <klocale.h> TextCutCommand::TextCutCommand(TextTool *tool, QUndoCommand *parent) :@@ -44,6 +45,9 @@ } else { m_first = false; m_tool->copy();- m_tool->m_textEditor->deleteChar();+ if(m_tool->m_actionShowChanges->isChecked())+ m_tool->m_textEditor->addCommand(new DeleteCommand(DeleteCommand::NextChar, m_tool));+ else+ m_tool->m_textEditor->deleteChar(); } }Index: koffice/plugins/textshape/commands/DeleteCommand.cpp===================================================================--- koffice/plugins/textshape/commands/DeleteCommand.cpp (revision 0)+++ koffice/plugins/textshape/commands/DeleteCommand.cpp (revision 0)@@ -0,0 +1,266 @@+/*+ This file is part of the KDE project+ * Copyright (C) 2009 Ganesh Paramasivam <ganesh@crystalfab.com>+ *+ * This library is free software; you can redistribute it and/or+ * modify it under the terms of the GNU Library General Public+ * License as published by the Free Software Foundation; either+ * version 2 of the License, or (at your option) any later version.+ *+ * This library is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ * Library General Public License for more details.+ *+ * You should have received a copy of the GNU Library General Public License+ * along with this library; see the file COPYING.LIB. If not, write to+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,+ * Boston, MA 02110-1301, USA.*/++#include "DeleteCommand.h"+#include <KoTextEditor.h>+#include <TextTool.h>+#include <klocale.h>+#include <KoChangeTracker.h>+#include <KoChangeTrackerElement.h>+#include <KoTextDocument.h>+#include <KoTextDocumentLayout.h>+#include <KoInlineTextObjectManager.h>+#include <KAction>+#include <QTextDocumentFragment>+#include <QUndoCommand>++#include <KDebug>+#include <iostream>+#include <QDebug>++using namespace std;+DeleteCommand::DeleteCommand(DeleteMode mode, TextTool *tool, QUndoCommand *parent) :+ TextCommandBase (parent),+ m_tool(tool),+ m_first(true),+ m_mode(mode),+ m_undone(false),+ m_removedElements()+{+ setText(i18n("Delete"));+}++void DeleteCommand::undo()+{+ TextCommandBase::undo();+ UndoRedoFinalizer finalizer(this, m_tool);+ + QTextDocument *document = m_tool->m_textEditor->document();+ KoTextDocument(document).changeTracker()->elementById(m_addedChangeElement)->setValid(false);+ foreach (int changeId, m_removedElements) {+ KoTextDocument(document).changeTracker()->elementById(changeId)->setValid(true);+ }++ m_undone = true;+}++void DeleteCommand::redo()+{+ m_undone = false;+ if (!m_first) {+ TextCommandBase::redo();+ UndoRedoFinalizer finalizer(this, m_tool);+ QTextDocument *document = m_tool->m_textEditor->document();+ KoTextDocument(document).changeTracker()->elementById(m_addedChangeElement)->setValid(true);+ foreach (int changeId, m_removedElements) {+ KoTextDocument(document).changeTracker()->elementById(changeId)->setValid(false);+ }+ } else {+ m_first = false;+ m_tool->m_textEditor->beginEditBlock();+ if(m_mode == PreviousChar)+ deletePreviousChar();+ else+ deleteChar();+ m_tool->m_textEditor->endEditBlock();+ }+}++void DeleteCommand::deleteChar()+{+ QTextCursor *caret = m_tool->m_textEditor->cursor();++ if (caret->atEnd() && !caret->hasSelection())+ return;++ if (!caret->hasSelection())+ caret->movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);++ deleteSelection(*caret);+}++void DeleteCommand::deletePreviousChar()+{+ QTextCursor *caret = m_tool->m_textEditor->cursor();++ if (caret->atStart() && !caret->hasSelection())+ return;++ if (!caret->hasSelection())+ caret->movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);++ deleteSelection(*caret);+}++void DeleteCommand::deleteSelection(QTextCursor &selection)+{+ QTextDocument *document = m_tool->m_textEditor->document();+ KoTextDocumentLayout *layout = qobject_cast<KoTextDocumentLayout*>(document->documentLayout());+ Q_ASSERT(layout);+ Q_ASSERT(layout->inlineTextObjectManager());++ QTextCursor checker = QTextCursor(selection);+ KoDeleteChangeMarker *deleteChangemarker = 0;+ KoDeleteChangeMarker *testMarker;++ bool backwards = (checker.anchor() > checker.position());+ int selectionBegin = qMin(checker.anchor(), checker.position());+ int selectionEnd = qMax(checker.anchor(), checker.position());+ int changeId;++ QString prefix;+ QString sufix;+ QString delText;++ checker.setPosition(selectionBegin);+ if (KoTextDocument(document).changeTracker()->containsInlineChanges(checker.charFormat())) {+ int changeId = checker.charFormat().property(KoCharacterStyle::ChangeTrackerId).toInt();+ if (KoTextDocument(document).changeTracker()->elementById(changeId)->getChangeType() == KoGenChange::deleteChange) {+ prefix = KoTextDocument(document).changeTracker()->elementById(changeId)->getDeleteData();+ KoTextDocument(document).changeTracker()->elementById(changeId)->setValid(false);+ m_removedElements.push_back(changeId);+ }+ }++ checker.setPosition(selectionEnd);+ if (!checker.atEnd()) {+ checker.movePosition(QTextCursor::NextCharacter);+ testMarker = dynamic_cast<KoDeleteChangeMarker*>(layout->inlineTextObjectManager()->inlineTextObject(checker));+ if (testMarker) {+ sufix = KoTextDocument(document).changeTracker()->elementById(testMarker->changeId())->getDeleteData();+ KoTextDocument(document).changeTracker()->elementById(testMarker->changeId())->setValid(false);+ m_removedElements.push_back(testMarker->changeId());+ }+ }+ checker.setPosition(selectionBegin);++ while ((checker.position() < selectionEnd) && (!checker.atEnd())) {+ QChar charAtPos = document->characterAt(checker.position());+ checker.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);+ if (layout->inlineTextObjectManager()->inlineTextObject(checker) && charAtPos.unicode() != 0x2029) {+ testMarker = dynamic_cast<KoDeleteChangeMarker*>(layout->inlineTextObjectManager()->inlineTextObject(checker));+ if (testMarker) {+ QString inter = KoTextDocument(document).changeTracker()->elementById(testMarker->changeId())->getDeleteData();+ delText = delText + inter;+ checker.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, inter.length());+ KoTextDocument(document).changeTracker()->elementById(testMarker->changeId())->setValid(false);+ m_removedElements.push_back(testMarker->changeId());+ }+ }+ else {+ delText = delText + checker.selectedText();+ }+ checker.setPosition(checker.position());+ }+ + if (!sufix.isEmpty()) {+ selection.setPosition(selectionBegin);+ selection.setPosition(selectionEnd + sufix.length() + 1, QTextCursor::KeepAnchor);+ selectionEnd += (sufix.length() + 1);+ }++ if (!prefix.isEmpty()) {+ selection.setPosition(selectionBegin - prefix.length() - 1);+ selection.setPosition(selectionEnd, QTextCursor::KeepAnchor);+ selectionBegin -= (prefix.length() + 1);+ }++ QTextDocumentFragment deletedFragment = selection.selection();+ changeId = KoTextDocument(document).changeTracker()->getDeleteChangeId(i18n("Delete"), deletedFragment, selection.charFormat().property( KoCharacterStyle::ChangeTrackerId ).toInt());+ KoChangeTrackerElement *element = KoTextDocument(document).changeTracker()->elementById(changeId);+ deleteChangemarker = new KoDeleteChangeMarker(KoTextDocument(document).changeTracker());+ deleteChangemarker->setChangeId(changeId);+ element->setDeleteChangeMarker(deleteChangemarker);+ layout->inlineTextObjectManager()->insertInlineObject(selection, deleteChangemarker);+ + m_addedChangeElement = changeId;+ + //Clear the changeTrackerId of the marker. Should be done in KoInlineTextObjectManager ideally.+ selection.setPosition(selectionBegin);+ selection.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);+ QTextCharFormat markerFormat = selection.charFormat();+ markerFormat.setProperty(KoCharacterStyle::ChangeTrackerId,0);+ selection.mergeCharFormat(markerFormat);+ selection.setPosition(selectionBegin + 1);++ //Insert the deleted data again after the marker with the charformat set to the change-id+ QString deletedData = prefix + delText + sufix;+ QTextCharFormat f;+ f.setProperty(KoCharacterStyle::ChangeTrackerId, deleteChangemarker->changeId());+ selection.mergeCharFormat(f);+ selection.insertText(deletedData);+++ KoTextDocument(document).changeTracker()->elementById(deleteChangemarker->changeId())->setDeleteData(deletedData);+ if (backwards)+ selection.movePosition(QTextCursor::PreviousCharacter, QTextCursor::MoveAnchor, deletedData.length() + 1);++}+++int DeleteCommand::id() const+{+ return 98765;+}++bool DeleteCommand::mergeWith( const QUndoCommand *command)+{+ if (command->id() != id())+ return false;+ + DeleteCommand *other = const_cast<DeleteCommand *>(static_cast<const DeleteCommand *>(command));+ if (other->m_removedElements.contains(m_addedChangeElement)) {+ + removeChangeElement(m_addedChangeElement);+ other->m_removedElements.removeAll(m_addedChangeElement);+ m_addedChangeElement = other->m_addedChangeElement;++ m_removedElements += other->m_removedElements;+ other->m_removedElements.clear();++ for(int i=0; i < command->childCount(); i++)+ new UndoTextCommand(m_tool->m_textEditor->document(), this);++ return true;+ }+ + return false;+}++DeleteCommand::~DeleteCommand()+{+ if (m_undone) {+ removeChangeElement(m_addedChangeElement);+ } else {+ foreach (int changeId, m_removedElements) {+ removeChangeElement(changeId);+ }+ }+}++void DeleteCommand::removeChangeElement(int changeId)+{++ QTextDocument *document = m_tool->m_textEditor->document();+ KoTextDocumentLayout *layout = qobject_cast<KoTextDocumentLayout*>(document->documentLayout());+ KoChangeTrackerElement *element = KoTextDocument(document).changeTracker()->elementById(changeId);+ KoDeleteChangeMarker *marker = element->getDeleteChangeMarker();+ layout->inlineTextObjectManager()->removeInlineObject(marker);+ KoTextDocument(document).changeTracker()->removeById(changeId);+}Index: koffice/plugins/textshape/commands/DeleteCommand.h===================================================================--- koffice/plugins/textshape/commands/DeleteCommand.h (revision 0)+++ koffice/plugins/textshape/commands/DeleteCommand.h (revision 0)@@ -0,0 +1,63 @@+/*+ This file is part of the KDE project+ * Copyright (C) 2009 Ganesh Paramasivam <ganesh@crystalfab.com>+ *+ * This library is free software; you can redistribute it and/or+ * modify it under the terms of the GNU Library General Public+ * License as published by the Free Software Foundation; either+ * version 2 of the License, or (at your option) any later version.+ *+ * This library is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ * Library General Public License for more details.+ *+ * You should have received a copy of the GNU Library General Public License+ * along with this library; see the file COPYING.LIB. If not, write to+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,+ * Boston, MA 02110-1301, USA.*/++#ifndef DELETECOMMAND_H+#define DELETECOMMAND_H++#include <QUndoStack>+#include "TextCommandBase.h"+#include <QList>++class TextTool;+class QTextCursor;+class KoChangeTrackerElement;++class DeleteCommand : public TextCommandBase+{+public:+ typedef enum+ {+ PreviousChar,+ NextChar+ }DeleteMode;++ DeleteCommand(DeleteMode mode, TextTool *tool, QUndoCommand* parent = 0);+ ~DeleteCommand();++ virtual void undo();+ virtual void redo();++ virtual int id() const;+ virtual bool mergeWith ( const QUndoCommand *command);++private:+ TextTool *m_tool;+ bool m_first;+ bool m_undone;+ DeleteMode m_mode;+ QList<int> m_removedElements;+ int m_addedChangeElement;++ virtual void deleteChar();+ virtual void deletePreviousChar();+ virtual void deleteSelection(QTextCursor &selection);+ virtual void removeChangeElement(int changeId);+};++#endif // DELTECOMMAND_HIndex: koffice/plugins/textshape/commands/ShowChangesCommand.cpp===================================================================--- koffice/plugins/textshape/commands/ShowChangesCommand.cpp (revision 0)+++ koffice/plugins/textshape/commands/ShowChangesCommand.cpp (revision 0)@@ -0,0 +1,145 @@+/*+ This file is part of the KDE project+ * Copyright (C) 2009 Ganesh Paramasivam <ganesh@crystalfab.com>+ *+ * This library is free software; you can redistribute it and/or+ * modify it under the terms of the GNU Library General Public+ * License as published by the Free Software Foundation; either+ * version 2 of the License, or (at your option) any later version.+ *+ * This library is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ * Library General Public License for more details.+ *+ * You should have received a copy of the GNU Library General Public License+ * along with this library; see the file COPYING.LIB. If not, write to+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,+ * Boston, MA 02110-1301, USA.*/++#include "ShowChangesCommand.h"++#include <KoTextEditor.h>+#include <TextTool.h>+#include <klocale.h>+#include <KoChangeTracker.h>+#include <KoChangeTrackerElement.h>+#include <KoTextDocument.h>+#include <KoTextDocumentLayout.h>+#include <KAction>++ShowChangesCommand::ShowChangesCommand(bool showChanges, TextTool *tool, QUndoCommand *parent) :+ TextCommandBase (parent),+ m_showChanges(showChanges),+ m_tool(tool),+ m_first(true)+{+ if (showChanges)+ setText(i18n("Show Changes"));+ else+ setText(i18n("Hide Changes"));+}++void ShowChangesCommand::undo()+{+ TextCommandBase::undo();+ UndoRedoFinalizer finalizer(this, m_tool);+ m_tool->m_actionShowChanges->setChecked(!m_showChanges);+ enableDisableStates(!m_showChanges);+}++void ShowChangesCommand::redo()+{+ if (!m_first) {+ TextCommandBase::redo();+ UndoRedoFinalizer finalizer(this, m_tool);+ m_tool->m_actionShowChanges->setChecked(m_showChanges);+ enableDisableStates(m_showChanges);+ } else {+ m_first = false;+ enableDisableChanges();+ }+}++void ShowChangesCommand::enableDisableChanges()+{+ if (m_tool->m_changeTracker) {+ enableDisableStates(m_showChanges);++ if(m_showChanges)+ insertDeletedChanges();+ else+ removeDeletedChanges();++ const QTextDocument *doc = m_tool->m_textEditor->document();+ Q_ASSERT(doc);+ KoTextDocumentLayout *lay = qobject_cast<KoTextDocumentLayout*>(doc->documentLayout());+ if(lay)+ lay->scheduleLayout();+ }+}++void ShowChangesCommand::enableDisableStates(bool showChanges)+{+ m_tool->m_changeTracker->setEnabled(showChanges);+ m_tool->m_changeTracker->setDisplayDeleted(showChanges);++ QTextCharFormat format = m_tool->m_textEditor->charFormat();+ format.clearProperty(KoCharacterStyle::ChangeTrackerId);+ m_tool->m_textEditor->setCharFormat(format);++ m_tool->m_textTyping = false;+ m_tool->m_textDeleting = false;+}++void ShowChangesCommand::insertDeletedChanges()+{+ int numAddedChars = 0;+ QVector<KoChangeTrackerElement *> elementVector;+ KoTextDocument(m_tool->m_textEditor->document()).changeTracker()->getDeletedChanges(elementVector);++ QTextCursor caret(m_tool->m_textEditor->document());+ caret.beginEditBlock();++ foreach(KoChangeTrackerElement *element, elementVector)+ {+ if (element->isValid()) {+ QTextCharFormat f;+ caret.setPosition(element->getDeleteChangeMarker()->position() + numAddedChars + 1);+ f.setProperty(KoCharacterStyle::ChangeTrackerId, element->getDeleteChangeMarker()->changeId());+ caret.mergeCharFormat(f);+ caret.insertText(element->getDeleteData());+ numAddedChars += element->getDeleteData().length();+ }+ }++ caret.endEditBlock();+}++void ShowChangesCommand::removeDeletedChanges()+{+ int numDeletedChars = 0;+ QVector<KoChangeTrackerElement *> elementVector;+ KoTextDocument(m_tool->m_textEditor->document()).changeTracker()->getDeletedChanges(elementVector);++ QTextCursor caret(m_tool->m_textEditor->document());+ caret.beginEditBlock();++ foreach(KoChangeTrackerElement *element, elementVector)+ {+ if (element->isValid()) {+ QTextCharFormat f;+ caret.setPosition(element->getDeleteChangeMarker()->position() + 1 - numDeletedChars);+ caret.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, element->getDeleteData().length());+ caret.removeSelectedText();+ numDeletedChars += element->getDeleteData().length();+ }+ }++ caret.endEditBlock();+}++ShowChangesCommand::~ShowChangesCommand()+{++}Index: koffice/plugins/textshape/commands/ShowChangesCommand.h===================================================================--- koffice/plugins/textshape/commands/ShowChangesCommand.h (revision 0)+++ koffice/plugins/textshape/commands/ShowChangesCommand.h (revision 0)@@ -0,0 +1,49 @@+/*+ This file is part of the KDE project+ * Copyright (C) 2009 Ganesh Paramasivam <ganesh@crystalfab.com>+ *+ * This library is free software; you can redistribute it and/or+ * modify it under the terms of the GNU Library General Public+ * License as published by the Free Software Foundation; either+ * version 2 of the License, or (at your option) any later version.+ *+ * This library is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ * Library General Public License for more details.+ *+ * You should have received a copy of the GNU Library General Public License+ * along with this library; see the file COPYING.LIB. If not, write to+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,+ * Boston, MA 02110-1301, USA.*/++#ifndef SHOWCHANGECOMMAND_H+#define SHOWCHANGECOMMAND_H++#include <QUndoStack>+#include "TextCommandBase.h"++class TextTool;++class ShowChangesCommand : public TextCommandBase+{+public:++ ShowChangesCommand(bool shoeChanges, TextTool *tool, QUndoCommand* parent = 0);+ ~ShowChangesCommand();++ virtual void undo();+ virtual void redo();++private:+ void enableDisableChanges();+ void enableDisableStates(bool showChanges);+ void insertDeletedChanges();+ void removeDeletedChanges();++ TextTool *m_tool;+ bool m_first;+ bool m_showChanges;+};++#endif // SHOWCHANGECOMMAND_HIndex: koffice/plugins/textshape/commands/TextPasteCommand.cpp===================================================================--- koffice/plugins/textshape/commands/TextPasteCommand.cpp (revision 1046549)+++ koffice/plugins/textshape/commands/TextPasteCommand.cpp (working copy)@@ -30,6 +30,8 @@ #include <QApplication> #include <QMimeData>+#include "DeleteCommand.h"+#include <KAction> TextPasteCommand::TextPasteCommand(QClipboard::Mode mode, TextTool *tool, QUndoCommand *parent) : QUndoCommand (parent),@@ -56,7 +58,10 @@ editor->cursor()->beginEditBlock(); m_first = false; if (editor->hasSelection()) {//TODO- editor->deleteChar();+ if(m_tool->m_actionShowChanges->isChecked())+ editor->addCommand(new DeleteCommand(DeleteCommand::NextChar, m_tool));+ else+ editor->deleteChar(); } // check for mime typeIndex: koffice/plugins/textshape/TextTool.h===================================================================--- koffice/plugins/textshape/TextTool.h (revision 1046549)+++ koffice/plugins/textshape/TextTool.h (working copy)@@ -262,6 +262,8 @@ friend class ChangeTracker; friend class TextPasteCommand; friend class TextCutCommand;+ friend class ShowChangesCommand;+ friend class DeleteCommand; TextShape *m_textShape; KoTextShapeData *m_textShapeData; QPointer<KoTextEditor> m_textEditor;@@ -286,6 +288,7 @@ KAction *m_actionFormatSub; KAction *m_actionFormatIncreaseIndent; KAction *m_actionFormatDecreaseIndent;+ KAction *m_actionShowChanges; KFontSizeAction *m_actionFormatFontSize; KFontAction *m_actionFormatFontFamily; #ifndef NO_PIGMENTIndex: koffice/libs/kotext/opendocument/KoTextLoader.cpp===================================================================--- koffice/libs/kotext/opendocument/KoTextLoader.cpp (revision 1046549)+++ koffice/libs/kotext/opendocument/KoTextLoader.cpp (working copy)@@ -711,6 +711,7 @@ KoDeleteChangeMarker *deleteChangemarker = new KoDeleteChangeMarker(d->changeTracker); deleteChangemarker->setChangeId(changeId); KoChangeTrackerElement *changeElement = d->changeTracker->elementById(changeId);+ changeElement->setDeleteChangeMarker(deleteChangemarker); changeElement->setEnabled(true); KoTextDocumentLayout *layout = qobject_cast<KoTextDocumentLayout*>(cursor.block().document()->documentLayout()); Index: koffice/libs/kotext/KoTextEditor.h===================================================================--- koffice/libs/kotext/KoTextEditor.h (revision 1046549)+++ koffice/libs/kotext/KoTextEditor.h (working copy)@@ -30,6 +30,8 @@ #include <QClipboard> #include <QMetaType> #include <QTextCursor>+#include <QUndoCommand>+#include <QPointer> class KoCharacterStyle; class KoInlineObject;@@ -41,7 +43,6 @@ class QTextDocument; class QTextDocumentFragment; class QString;-class QUndoCommand; class KOTEXT_EXPORT KoTextEditor: public KoToolSelection {@@ -248,6 +249,18 @@ Private* const d; }; +class KOTEXT_EXPORT UndoTextCommand : public QUndoCommand+{+ public:+ UndoTextCommand(QTextDocument *document, QUndoCommand *parent = 0);++ void undo();++ void redo();++ QPointer<QTextDocument> m_document;+};+ Q_DECLARE_METATYPE(KoTextEditor*) #endif // KOTEXTEDITOR_HIndex: koffice/libs/kotext/changetracker/KoChangeTracker.h===================================================================--- koffice/libs/kotext/changetracker/KoChangeTracker.h (revision 1046549)+++ koffice/libs/kotext/changetracker/KoChangeTracker.h (working copy)@@ -66,7 +66,11 @@ int getDeleteChangeId(QString title, QTextDocumentFragment selection, int existingChangeId); KoChangeTrackerElement* elementById(int id);+ bool removeById(int id, bool freeMemory = true); + //Returns all the deleted changes+ int getDeletedChanges(QVector<KoChangeTrackerElement *>& deleteVector);+ bool containsInlineChanges(const QTextFormat &format); int mergeableId(KoGenChange::Type type, QString &title, int existingId); Index: koffice/libs/kotext/changetracker/KoDeleteChangeMarker.cpp===================================================================--- koffice/libs/kotext/changetracker/KoDeleteChangeMarker.cpp (revision 1046549)+++ koffice/libs/kotext/changetracker/KoDeleteChangeMarker.cpp (working copy)@@ -44,6 +44,7 @@ KoChangeTracker *changeTracker; QString text; int id;+ int position; }; KoDeleteChangeMarker::KoDeleteChangeMarker(KoChangeTracker* changeTracker)@@ -77,6 +78,11 @@ return d->id; } +int KoDeleteChangeMarker::position() const+{+ return d->position;+}+ bool KoDeleteChangeMarker::loadOdf(const KoXmlElement &element) { Q_UNUSED(element)@@ -86,63 +92,26 @@ void KoDeleteChangeMarker::paint(QPainter& painter, QPaintDevice *pd, const QTextDocument *document, const QRectF &rect, QTextInlineObject object, int posInDocument, const QTextCharFormat &format) { Q_UNUSED(posInDocument);- Q_UNUSED(document);-- if (!d->changeTracker)- return;-- Q_ASSERT(format.isCharFormat());-- if (d->changeTracker->isEnabled() && d->changeTracker->elementById(d->id)->isEnabled() && d->changeTracker->displayDeleted()) {- QFont font(format.font(), pd);- QTextLayout layout(d->changeTracker->elementById(d->id)->getDeleteData(), font, pd);- layout.setCacheEnabled(true);- QList<QTextLayout::FormatRange> layouts;- QTextLayout::FormatRange range;- range.start = 0;- range.length = d->changeTracker->elementById(d->id)->getDeleteData().length();- range.format = format;- range.format.setBackground(QBrush(Qt::red));- layouts.append(range);- layout.setAdditionalFormats(layouts);-- QTextOption option(Qt::AlignLeft | Qt::AlignAbsolute);- option.setTextDirection(object.textDirection());- layout.setTextOption(option);- layout.beginLayout();- layout.createLine();- layout.endLayout();- layout.draw(&painter, rect.topLeft());- } } void KoDeleteChangeMarker::resize(const QTextDocument *document, QTextInlineObject object, int posInDocument, const QTextCharFormat &format, QPaintDevice *pd) {- Q_UNUSED(posInDocument); Q_UNUSED(document);+ Q_UNUSED(object);+ Q_UNUSED(format);+ Q_UNUSED(pd);+ Q_UNUSED(document); - if (!d->changeTracker)- return;-- Q_ASSERT(format.isCharFormat());- QFontMetricsF fm(format.font(), pd);-- if (d->changeTracker->isEnabled() && d->changeTracker->elementById(d->id)->isEnabled() && d->changeTracker->displayDeleted()) {- object.setWidth(fm.width(d->changeTracker->elementById(d->id)->getDeleteData()));- object.setAscent(fm.ascent());- object.setDescent(fm.descent());- } else {- object.setWidth(0);- object.setAscent(fm.ascent());- object.setDescent(fm.descent());- }+ d->position = posInDocument;+ object.setWidth(0); } void KoDeleteChangeMarker::updatePosition(const QTextDocument *document, QTextInlineObject object, int posInDocument, const QTextCharFormat &format) {+ d->position = posInDocument;+ Q_UNUSED(document); Q_UNUSED(object);- Q_UNUSED(posInDocument); Q_UNUSED(format); } Index: koffice/libs/kotext/changetracker/KoChangeTrackerElement.cpp===================================================================--- koffice/libs/kotext/changetracker/KoChangeTrackerElement.cpp (revision 1046549)+++ koffice/libs/kotext/changetracker/KoChangeTrackerElement.cpp (working copy)@@ -35,9 +35,12 @@ QString creator; QString date; QString extraMetaData;+ //These two elements are valid for delete changes. Need to move it to a sub-class QString deleteData;+ KoDeleteChangeMarker *marker; bool enabled;+ bool valid; }; KoChangeTrackerElement::KoChangeTrackerElement(const QString& title, KoGenChange::Type type)@@ -45,6 +48,7 @@ { d->title = title; d->type = type;+ d->valid = true; } KoChangeTrackerElement::KoChangeTrackerElement()@@ -64,6 +68,7 @@ d->extraMetaData = other.d->extraMetaData; d->deleteData = other.d->deleteData; d->enabled = other.d->enabled;+ d->valid = other.d->valid; } KoChangeTrackerElement::~KoChangeTrackerElement()@@ -81,6 +86,16 @@ return d->enabled; } +void KoChangeTrackerElement::setValid(bool valid)+{+ d->valid = valid;+}++bool KoChangeTrackerElement::isValid() const+{+ return d->valid;+}+ void KoChangeTrackerElement::setChangeType(KoGenChange::Type type) { d->type = type;@@ -181,3 +196,13 @@ return d->deleteData; } +void KoChangeTrackerElement::setDeleteChangeMarker(KoDeleteChangeMarker *marker)+{+ d->marker = marker;+}++KoDeleteChangeMarker *KoChangeTrackerElement::getDeleteChangeMarker()+{+ return d->marker;+}+Index: koffice/libs/kotext/changetracker/KoDeleteChangeMarker.h===================================================================--- koffice/libs/kotext/changetracker/KoDeleteChangeMarker.h (revision 1046549)+++ koffice/libs/kotext/changetracker/KoDeleteChangeMarker.h (working copy)@@ -53,6 +53,9 @@ /// return the change id int changeId() const; + ///Return the position of the marker in the document+ int position() const;+ bool loadOdf(const KoXmlElement &element); ///reimplemented virtual void saveOdf(KoShapeSavingContext &context);Index: koffice/libs/kotext/changetracker/KoChangeTrackerElement.h===================================================================--- koffice/libs/kotext/changetracker/KoChangeTrackerElement.h (revision 1046549)+++ koffice/libs/kotext/changetracker/KoChangeTrackerElement.h (working copy)@@ -27,7 +27,9 @@ #include <KoGenChange.h> #include "kotext_export.h"+#include "KoDeleteChangeMarker.h" + class KOTEXT_EXPORT KoChangeTrackerElement { public:@@ -43,6 +45,9 @@ void setEnabled(bool enabled); bool isEnabled() const; + void setValid(bool valid);+ bool isValid() const;+ void setChangeType(KoGenChange::Type type); KoGenChange::Type getChangeType() const; @@ -71,6 +76,9 @@ void setDeleteData(const QString& data); QString getDeleteData() const; + void setDeleteChangeMarker(KoDeleteChangeMarker *marker);+ KoDeleteChangeMarker *getDeleteChangeMarker();+ private: class Private; Private* const d;Index: koffice/libs/kotext/changetracker/KoChangeTracker.cpp===================================================================--- koffice/libs/kotext/changetracker/KoChangeTracker.cpp (revision 1046549)+++ koffice/libs/kotext/changetracker/KoChangeTracker.cpp (working copy)@@ -178,6 +178,14 @@ return d->m_changes.value(id); } +bool KoChangeTracker::removeById(int id, bool freeMemory)+{+ if (freeMemory) {+ KoChangeTrackerElement *temp = d->m_changes.value(id);+ delete temp;+ }+ return d->m_changes.remove(id);+} bool KoChangeTracker::containsInlineChanges(const QTextFormat &format) {@@ -308,4 +316,19 @@ return true; } +int KoChangeTracker::getDeletedChanges(QVector<KoChangeTrackerElement *>& deleteVector)+{+ int numAppendedItems = 0;+ foreach(KoChangeTrackerElement *element, d->m_changes.values())+ {+ if(element->getChangeType() == KoGenChange::deleteChange)+ {+ deleteVector << element;+ numAppendedItems++;+ }+ }++ return numAppendedItems;+}+ #include "KoChangeTracker.moc"Index: koffice/libs/kotext/KoTextEditor.cpp===================================================================--- koffice/libs/kotext/KoTextEditor.cpp (revision 1046549)+++ koffice/libs/kotext/KoTextEditor.cpp (working copy)@@ -98,28 +98,6 @@ void KoTextEditor::Private::documentCommandAdded() {- class UndoTextCommand : public QUndoCommand- {- public:- UndoTextCommand(QTextDocument *document, QUndoCommand *parent = 0)- : QUndoCommand(i18n("Text"), parent),- m_document(document)- {}-- void undo() {- if (m_document.isNull())- return;- m_document->undo(KoTextDocument(m_document).textEditor()->cursor());- }-- void redo() {- if (m_document.isNull())- return;- m_document->redo(KoTextDocument(m_document).textEditor()->cursor());- }-- QPointer<QTextDocument> m_document;- }; //kDebug() << "editor state: " << editorState << " headcommand: " << headCommand; if (!headCommand || editorState == NoOp) { headCommand = new QUndoCommand(commandTitle);@@ -218,12 +196,7 @@ delText.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); QString text = delText.selectedText(); QTextDocumentFragment selection = delText.selection();- if (KoTextDocument(document).changeTracker() && KoTextDocument(document).changeTracker()->isEnabled()) {- QTextCharFormat format = caret.charFormat();- q->registerTrackedChange(caret, KoGenChange::deleteChange, i18n("Delete"), format, format); //this will replace the text to be deleted by a marker.- }- else- caret.deleteChar();+ caret.deleteChar(); } void KoTextEditor::Private::runDirectionUpdater()@@ -376,62 +349,7 @@ selection.mergeCharFormat(f); } else {- QTextCursor checker = QTextCursor(selection);- KoDeleteChangeMarker *deleteChangemarker = 0;- KoDeleteChangeMarker *testMarker;- bool backwards = (checker.anchor() > checker.position());- int selectionBegin = qMin(checker.anchor(), checker.position());- int selectionEnd = qMax(checker.anchor(), checker.position());- int changeId;- QString prefix;- QString sufix;- QString delText;- checker.setPosition(selectionBegin);- testMarker = dynamic_cast<KoDeleteChangeMarker*>(layout->inlineTextObjectManager()->inlineTextObject(checker));- if (testMarker) {- prefix = KoTextDocument(d->document).changeTracker()->elementById(testMarker->changeId())->getDeleteData();- }- checker.setPosition(selectionEnd);- if (!checker.atEnd()) {- checker.movePosition(QTextCursor::NextCharacter);- testMarker = dynamic_cast<KoDeleteChangeMarker*>(layout->inlineTextObjectManager()->inlineTextObject(checker));- if (testMarker) {- sufix = KoTextDocument(d->document).changeTracker()->elementById(testMarker->changeId())->getDeleteData();- }- }- checker.setPosition(selectionBegin);- while (checker.position() < selectionEnd && !checker.atEnd()) {- checker.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);- if (layout->inlineTextObjectManager()->inlineTextObject(checker)) {- testMarker = dynamic_cast<KoDeleteChangeMarker*>(layout->inlineTextObjectManager()->inlineTextObject(checker));- if (testMarker) {- delText = delText + KoTextDocument(d->document).changeTracker()->elementById(testMarker->changeId())->getDeleteData();- }- }- else {- delText = delText + checker.selectedText();- }- checker.setPosition(checker.position());- }-- QTextDocumentFragment deletedFragment = selection.selection();- changeId = KoTextDocument(d->document).changeTracker()->getDeleteChangeId(i18n("Delete"), deletedFragment, selection.charFormat().property( KoCharacterStyle::ChangeTrackerId ).toInt()); //TODO this needs to be done like a visitor for individualised parenting- deleteChangemarker = new KoDeleteChangeMarker(KoTextDocument(d->document).changeTracker());- deleteChangemarker->setChangeId(changeId);- if (!sufix.isEmpty()) {- selection.setPosition(selectionBegin);- selection.setPosition(selectionEnd+1, QTextCursor::KeepAnchor);- selectionEnd++;- }- if (!prefix.isEmpty()) {- selection.setPosition(selectionBegin-1);- selection.setPosition(selectionEnd, QTextCursor::KeepAnchor);- selectionBegin--;- }- layout->inlineTextObjectManager()->insertInlineObject(selection, deleteChangemarker);- KoTextDocument(d->document).changeTracker()->elementById(deleteChangemarker->changeId())->setDeleteData(prefix + delText + sufix);- if (backwards)- selection.movePosition(QTextCursor::PreviousCharacter);+ //Handled in DeleteCommand } } @@ -1132,4 +1050,27 @@ d->caret.endEditBlock(); } +UndoTextCommand::UndoTextCommand(QTextDocument *document, QUndoCommand *parent)+ : QUndoCommand(i18n("Text"), parent),+ m_document(document)+{++}++void UndoTextCommand::undo()+{+ if (m_document.isNull())+ return;+ + m_document->undo(KoTextDocument(m_document).textEditor()->cursor());+}++void UndoTextCommand::redo()+{+ if (m_document.isNull())+ return;+ + m_document->redo(KoTextDocument(m_document).textEditor()->cursor());+}+ #include "KoTextEditor.moc"