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

List:       koffice-devel
Subject:    Re: Change Tracking of Inline Objects - Patch v1
From:       Ganesh Paramasivam <ganesh () crystalfab ! com>
Date:       2010-02-25 11:51:54
Message-ID: 9ecf537e1002250350h4c5058d9v7860aa44adf2d8d6 () mail ! gmail ! com
[Download RAW message or body]

Pierre,

Please find attached the next iteration of the patch to track changes
of inline objects. Saving of change-tracked inline-objects works and
is inter-operable with oowriter. Loading of documents containing a
change-tracked inline object is yet to be done.

Some Points

- I have tried a new approach to save deleted changes. I have added
the code to save delete changes in  KoTextWriter (
generateDeleteChangeXml() )  which leverages upon the existing
odf-saving code. The advantage with this approach is that we do not
have to specifically add anymore code for saving delete-changes
specifically. If the current odf-saving code supports a tag, saving of
delete change for that specific tag is automatically supported (
along-with saving of formatting information ) . The code has been
tested for  Simple Delete, multi-para delete, delete with inline
images and the saved odf is inter-operable with oowriter

- Your comment on the usage of KoChangeTracker in KoTextAnchor has
been fixed ( checking for null )

- Loading of documents containing deleted inline changes does not work
yet. Will be done by tomorrow

- If an inline object is deleted with record-changes enabled and
show-changes disabled, the shape does not get deleted from the
document. Will be fixing this in tomorrow's patch.

Let me know your thoughts and comments on this.

Thanks,
Ganesh


On Thu, Feb 25, 2010 at 12:12 AM, Pierre Stirnweiss
<pstirnweiss@googlemail.com> wrote:
> Le Wednesday 24 February 2010 10:40:16, Ganesh Paramasivam a =E9crit :
>> Pierre,
>>
>> Pierre please find attached the first version of the patch for
>> tracking changes of inline objects. This version is mainly for the
>> visualization of inline object changes as well as for the Show/Hide
>> changes. I'm aware of the fact that these will go away once the new
>> approach is done. But I was not sure about how soon/late the new
>> approach will take. Hence I decided to implement this as a stop-gap
>> solution thinking that the effort would be minimal ( Turned out to be
>> a bad idea. See below ). As a side-note, while implementing this, I
>> was wondering how a deleted inline image would be displayed in the new
>> solution.
>>
>> I have a really *UGLY* hack in show changes. During show changes, if
>> we find that an inserted fragment contains a KoTextAnchor, we need to
>> insert the shape associated with the Anchor. However just calling
>> KoShapeController::addShapeDirect results in a bizzare layout. On
>> further debugging, I realized that the parent of this shape needs to
>> be set before adding it. However, it is not possible to find the
>> parent of this shape that easily ( Because shapeForPosition would
>> return the right parent only once a layout is done ). So for now, I
>> set the first shape in KoTextDocumentLayout as it's parent.
>>
>> If you think that we need a complete and working solution for this
>> problem please let me know. I can go back and solve this the right
>> way.
>>
>> Thanks,
>> Ganesh
>
> I think the hack is ok for now (but perhaps I have missed something). I
> haven't had the time to hack lately and it will probably be so until next
> week. I still hope to be able to implement the delete bubbles for 2.2. I =
have
> an almost finished solution now. I need to clean up a bit and come up wit=
h a
> cache system.
>
> Regarding the patch, you are using the changeTracker in KoTextAnchor. Ple=
ase
> test for it before using one of its method. Outside KWord, the changeTrac=
ker
> will be a null pointer.
>
> Pierre
>

["inline-objects-change-tracking-v2.patch" (application/octet-stream)]

Index: libs/odf/KoGenChange.h
===================================================================
--- libs/odf/KoGenChange.h	(revision 1095930)
+++ libs/odf/KoGenChange.h	(working copy)
@@ -26,13 +26,9 @@
 #include "koodf_export.h"
 
 #include <QByteArray>
-#include <QVariant>
-#include <QTextDocumentFragment>
 
 #include <kdebug.h>
 
-Q_DECLARE_METATYPE(QTextDocumentFragment)
-
 class KoGenChanges;
 class KoXmlWriter;
 
@@ -113,15 +109,9 @@
      * The value of @p elementName isn't used, except that it must be unique.
      */
     void addChildElement(const QString& elementName, const QString& elementContents) \
                {
-        m_literalData.insert(elementName, QVariant(elementContents));
+        m_literalData.insert(elementName, elementContents);
     }
 
-    void addChildElement(const QString &elementName, const QTextDocumentFragment \
                &textFragment) {
-        QVariant var;
-        var.setValue(textFragment);
-        m_literalData.insert(elementName, var);
-    }
-
     /**
      *  Write the definition of this change to @p writer, using the OASIS format.
      *  @param writer the KoXmlWriter in which the element will be created and \
filled in @@ -151,17 +141,14 @@
 
     void writeChangeMetaData(KoXmlWriter* writer) const;
 
-    void writeDeleteChange(KoXmlWriter *writer) const;
-
 private:
     // Note that the copy constructor and assignment operator are allowed.
     // Better not use pointers below!
     Type m_type;
     /// We use QMaps since they provide automatic sorting on the key (important for \
unicity!)  typedef QMap<QString, QString> ChangeMap;
-    typedef QMap<QString, QVariant> GenericChangeMap;
     ChangeMap m_changeMetaData;
-    GenericChangeMap m_literalData;
+    ChangeMap m_literalData;
 
     short m_unused2;
 };
Index: libs/odf/KoGenChange.cpp
===================================================================
--- libs/odf/KoGenChange.cpp	(revision 1095930)
+++ libs/odf/KoGenChange.cpp	(working copy)
@@ -18,9 +18,6 @@
 */
 
 #include <QDateTime>
-#include <QTextDocument>
-#include <QTextCursor>
-#include <QTextBlock>
 
 #include "KoGenChange.h"
 #include <KoXmlWriter.h>
@@ -41,32 +38,7 @@
     return 0; // equal
 }
 
-// Return true if equal else false
-static bool compareGenericMap(const QMap<QString, QVariant> &map1, const \
                QMap<QString, QVariant> &map2)
-{
-    QMap<QString, QVariant>::const_iterator it = map1.begin();
-    QMap<QString, QVariant>::const_iterator oit = map2.begin();
 
-    for (; it != map1.end(); ++it, ++oit) {
-        if (it.key() != oit.key())
-            return false;
-        if (it.value().type() != oit.value().type())
-            return false;
-        if (it.value().type() == QVariant::String) {
-            if (it.value().toString() != oit.value().toString())
-                return false;
-        } else {
-            QString itHtml = it.value().value<QTextDocumentFragment>().toHtml();
-            QString oitHtml = oit.value().value<QTextDocumentFragment>().toHtml();
-            if (itHtml != oitHtml)
-                return false;
-        }
-    }
-
-    return true;
-}
-
-
 KoGenChange::KoGenChange()
 {
 }
@@ -121,29 +93,16 @@
         writer->startElement("office:change-info");
         writeChangeMetaData(writer);
         if (m_literalData.contains("changeMetaData"))
-            writer->addCompleteElement(m_literalData.value("changeMetaData").toString().toUtf8());
 +            writer->addCompleteElement(m_literalData.value("changeMetaData").toUtf8());
  writer->endElement(); // office:change-info
     }
-    if ((m_type == KoGenChange::deleteChange) && \
                m_literalData.contains("deletedData")) {
-        writeDeleteChange(writer);
-    }
+    if ((m_type == KoGenChange::deleteChange) && \
m_literalData.contains("deleteChangeXml")) +        \
writer->addCompleteElement(m_literalData.value("deleteChangeXml").toUtf8()); +    
     writer->endElement(); // text:insertion/format/deletion
     writer->endElement(); // text:change
 }
 
-void KoGenChange::writeDeleteChange(KoXmlWriter *writer) const
-{
-    QTextDocument document;
-    QTextCursor cursor(&document);
-    cursor.insertFragment(m_literalData["deletedData"].value<QTextDocumentFragment>());
                
-
-    for (QTextBlock block = document.begin(); block.isValid(); block = block.next()) \
                {
-        QString deletedElement;
-        deletedElement = QString("<text:p>") + block.text() + QString("</text:p>");
-        writer->addCompleteElement(deletedElement.toUtf8());
-    }
-}
-
 bool KoGenChange::operator<(const KoGenChange &other) const
 {
     Q_UNUSED(other);
@@ -160,6 +119,7 @@
     if (m_literalData.count() != other.m_literalData.count()) return false;
     int comp = compareMap(m_changeMetaData, other.m_changeMetaData);
     if (comp != 0) return false;
-    bool compResult = compareGenericMap(m_literalData, other.m_literalData);
-    return compResult;
+    comp = compareMap(m_literalData, other.m_literalData);
+    if (comp != 0) return false;
+    return true;
 }
Index: libs/kotext/KoTextAnchor.cpp
===================================================================
--- libs/kotext/KoTextAnchor.cpp	(revision 1095930)
+++ libs/kotext/KoTextAnchor.cpp	(working copy)
@@ -34,6 +34,12 @@
 #include <QPainter>
 #include <KDebug>
 
+#include "changetracker/KoChangeTracker.h"
+#include "changetracker/KoChangeTrackerElement.h"
+#include "styles/KoCharacterStyle.h"
+#include "KoTextDocument.h"
+#include <KoGenChanges.h>
+
 // #define DEBUG_PAINTING
 
 class KoTextAnchorPrivate : public KoInlineObjectPrivate
@@ -123,6 +129,7 @@
     KoTextAnchor::AnchorVertical verticalAlignment;
     const QTextDocument *document;
     int position;
+    QTextCharFormat format;
     KoTextShapeContainerModel *model;
     QPointF distance;
 };
@@ -182,6 +189,7 @@
     Q_D(KoTextAnchor);
     d->document = document;
     d->position = posInDocument;
+    d->format = format;
     d->setContainer(dynamic_cast<KoShapeContainer*>(shapeForPosition(document, \
posInDocument)));  }
 
@@ -210,6 +218,38 @@
 {
     Q_UNUSED(painter);
     Q_UNUSED(rect);
+
+    // This section of code is to indicate changes done to KoTextAnchors. Once the \
new approach is complete this can be removed +    // In this approach we draw a \
rectangle around the shape with the appropriate change indication color. +    \
Q_D(KoTextAnchor); +    int changeId = \
d->format.property(KoCharacterStyle::ChangeTrackerId).toInt(); +    bool \
drawChangeRect = false; +
+    QRectF changeRect = rect;
+    changeRect.adjust(0,0,1,0);
+    QPen changePen;
+    changePen.setWidth(2);
+   
+    KoChangeTracker *changeTracker = KoTextDocument(d->document).changeTracker(); 
+
+    if (!changeTracker)
+        return;
+
+    KoChangeTrackerElement *changeElement = changeTracker->elementById(changeId);
+    if (changeElement && changeElement->getChangeType() == \
KoGenChange::deleteChange) { +        \
changePen.setColor(changeTracker->getDeletionBgColor()); +        drawChangeRect = \
true; +    } else if (changeElement && changeElement->getChangeType() == \
KoGenChange::insertChange) { +        \
changePen.setColor(changeTracker->getInsertionBgColor()); +        drawChangeRect = \
true; +    }
+
+    painter.setPen(changePen);
+    if (drawChangeRect && changeTracker->displayChanges())
+        painter.drawRect(changeRect);
+
+    // End of Change Visualization Section. Can be removed once the new approach is \
finalized +
     // we never paint ourselves; the shape can do that.
 #ifdef DEBUG_PAINTING
     painter.setOpacity(0.5);
Index: libs/kotext/opendocument/KoTextWriter.cpp
===================================================================
--- libs/kotext/opendocument/KoTextWriter.cpp	(revision 1095930)
+++ libs/kotext/opendocument/KoTextWriter.cpp	(working copy)
@@ -27,6 +27,7 @@
 #include <QTextTable>
 #include <QStack>
 #include <QTextTableCellFormat>
+#include <QBuffer>
 
 #include "KoInlineObject.h"
 #include "KoInlineTextObjectManager.h"
@@ -82,7 +83,7 @@
     void saveTable(QTextTable *table, QHash<QTextList *, QString> &listStyles);
     void saveTableOfContents(QTextDocument *document, int from, int to, \
QHash<QTextList *, QString> &listStyles, QTextTable *currentTable, QTextFrame *toc);  \
void writeBlocks(QTextDocument *document, int from, int to, QHash<QTextList *, \
                QString> &listStyles, QTextTable *currentTable = 0, QTextFrame \
                *currentFrame = 0);
-
+    QString generateDeleteChangeXml(KoDeleteChangeMarker *marker);
     KoShapeSavingContext &context;
     KoTextSharedSavingData *sharedData;
     KoXmlWriter *writer;
@@ -131,6 +132,8 @@
     KoDeleteChangeMarker *changeMarker;
     if (layout && (changeMarker = \
dynamic_cast<KoDeleteChangeMarker*>(layout->inlineTextObjectManager()->inlineTextObject(format)))) \
{  if (!savedDeleteChanges.contains(changeMarker->changeId())) {
+            QString deleteChangeXml = generateDeleteChangeXml(changeMarker);
+            changeMarker->setDeleteChangeXml(deleteChangeXml);
             changeMarker->saveOdf(context);
             savedDeleteChanges.append(changeMarker->changeId());
         }
@@ -328,11 +331,6 @@
                 inlineRdf->saveOdf(context, writer);
             }
 
-            if (changeTracker
-                    && \
                charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt()
-                    && \
changeTracker->elementById(charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt())->getChangeType() \
                == KoGenChange::deleteChange)
-                continue;
-
             KoInlineObject *inlineObject = layout ? \
layout->inlineTextObjectManager()->inlineTextObject(charFormat) : 0;  if \
                (currentFragment.length() == 1 && inlineObject
                     && currentFragment.text()[0].unicode() == \
QChar::ObjectReplacementCharacter) { @@ -598,6 +596,37 @@
     }
 }
 
+QString KoTextWriter::Private::generateDeleteChangeXml(KoDeleteChangeMarker *marker)
+{
+    //Create a QTextDocument from the Delete Fragment
+    QTextDocument doc;
+    QTextCursor cursor(&doc);
+    cursor.insertFragment(changeTracker->elementById(marker->changeId())->getDeleteData());
 +
+    //Save the current writer
+    KoXmlWriter &oldWriter = context.xmlWriter();
+
+    //Create a new KoXmlWriter pointing to a QBuffer
+    QByteArray xmlArray;
+    QBuffer xmlBuffer(&xmlArray);
+    KoXmlWriter newXmlWriter(&xmlBuffer);
+
+    //Set our xmlWriter as the writer to be used
+    writer = &newXmlWriter;
+    context.setXmlWriter(newXmlWriter);
+
+    //Call writeBlocks to generate the xml
+    QHash<QTextList *,QString> listStyles = saveListStyles(doc.firstBlock(), \
doc.characterCount()); +    writeBlocks(&doc, 0, doc.characterCount(),listStyles);
+
+    //Restore the actual xml writer
+    writer = &oldWriter;
+    context.setXmlWriter(oldWriter);
+
+    QString generatedXmlString(xmlArray);
+    return generatedXmlString;
+}
+
 void KoTextWriter::write(QTextDocument *document, int from, int to)
 {
     d->styleManager = KoTextDocument(document).styleManager();
Index: libs/kotext/changetracker/KoDeleteChangeMarker.cpp
===================================================================
--- libs/kotext/changetracker/KoDeleteChangeMarker.cpp	(revision 1095930)
+++ libs/kotext/changetracker/KoDeleteChangeMarker.cpp	(working copy)
@@ -47,6 +47,7 @@
     QString text;
     int id;
     int position;
+    QString deleteChangeXml;
 };
 
 KoDeleteChangeMarker::KoDeleteChangeMarker(KoChangeTracker* changeTracker)
@@ -86,6 +87,11 @@
     return d->position;
 }
 
+void KoDeleteChangeMarker::setDeleteChangeXml(QString &deleteChangeXml)
+{
+    d->deleteChangeXml = deleteChangeXml;
+}
+
 bool KoDeleteChangeMarker::loadOdf(const KoXmlElement &element)
 {
     Q_UNUSED(element)
@@ -143,6 +149,7 @@
         }
     }
     d->changeTracker->saveInlineChange(d->id, change);
+    change.addChildElement("deleteChangeXml", d->deleteChangeXml);
     changeName = sharedData->genChanges().insert(change);
 
     context.xmlWriter().startElement("text:change", false);
Index: libs/kotext/changetracker/KoDeleteChangeMarker.h
===================================================================
--- libs/kotext/changetracker/KoDeleteChangeMarker.h	(revision 1095930)
+++ libs/kotext/changetracker/KoDeleteChangeMarker.h	(working copy)
@@ -65,6 +65,8 @@
     ///reimplemented
     virtual void saveOdf(KoShapeSavingContext &context);
 
+    void setDeleteChangeXml(QString &deleteChangeXml);
+
 protected:
 
     virtual void paint(QPainter &painter, QPaintDevice *pd, const QTextDocument \
*document, const QRectF &rect, QTextInlineObject object, int posInDocument, const \
                QTextCharFormat &format);
Index: libs/kotext/changetracker/KoChangeTracker.cpp
===================================================================
--- libs/kotext/changetracker/KoChangeTracker.cpp	(revision 1095930)
+++ libs/kotext/changetracker/KoChangeTracker.cpp	(working copy)
@@ -274,9 +274,6 @@
     if (d->changes.value(changeId)->hasExtraMetaData())
         change.addChildElement("changeMetaData", \
d->changes.value(changeId)->getExtraMetaData());  
-    if (d->changes.value(changeId)->hasDeleteData())
-        change.addChildElement("deletedData", \
                d->changes.value(changeId)->getDeleteData());
-
     return true;
 }
 
Index: plugins/textshape/ChangeTrackingTool.cpp
===================================================================
--- plugins/textshape/ChangeTrackingTool.cpp	(revision 1095930)
+++ plugins/textshape/ChangeTrackingTool.cpp	(working copy)
@@ -56,7 +56,8 @@
     m_textShape(0),
     m_model(0),
     m_trackedChangeManager(0),
-    m_changesTreeView(0)
+    m_changesTreeView(0),
+    m_canvas(canvas)
 {
     KAction *action;
     action = new KAction(i18n("Tracked change manager"), this);
@@ -279,7 +280,7 @@
     }
     if (!data) {
         if (m_disableShowChangesOnExit) {
-            ShowChangesCommand *command = new ShowChangesCommand(false, \
m_textShapeData->document()); +            ShowChangesCommand *command = new \
ShowChangesCommand(false, m_textShapeData->document(), m_canvas);  \
m_textEditor->addCommand(command);  }
     }
@@ -302,7 +303,7 @@
     m_textEditor->updateDefaultTextDirection(m_textShapeData->pageDirection());
     if (!KoTextDocument(m_textShapeData->document()).changeTracker()->displayChanges()) \
{  m_disableShowChangesOnExit = true;
-        ShowChangesCommand *command = new ShowChangesCommand(true, \
m_textShapeData->document()); +        ShowChangesCommand *command = new \
ShowChangesCommand(true, m_textShapeData->document(), m_canvas);  \
m_textEditor->addCommand(command);  }
     if (m_model) {
Index: plugins/textshape/TextTool.cpp
===================================================================
--- plugins/textshape/TextTool.cpp	(revision 1095930)
+++ plugins/textshape/TextTool.cpp	(working copy)
@@ -1664,7 +1664,7 @@
 
 void TextTool::toggleShowChanges(bool on)//TODO transfer this in KoTextEditor
 {
-    ShowChangesCommand *command = new ShowChangesCommand(on, \
m_textShapeData->document()); +    ShowChangesCommand *command = new \
                ShowChangesCommand(on, m_textShapeData->document(), this->canvas());
     connect(command, SIGNAL(toggledShowChange(bool)), m_actionShowChanges, \
SLOT(setChecked(bool)));  m_textEditor->addCommand(command);
 }
Index: plugins/textshape/ChangeTrackingTool.h
===================================================================
--- plugins/textshape/ChangeTrackingTool.h	(revision 1095930)
+++ plugins/textshape/ChangeTrackingTool.h	(working copy)
@@ -73,6 +73,7 @@
     bool m_disableShowChangesOnExit;
     KoTextEditor *m_textEditor;
     KoTextShapeData *m_textShapeData;
+    KoCanvasBase *m_canvas;
     TextShape *m_textShape;
     TrackedChangeModel *m_model;
 
Index: plugins/textshape/commands/ShowChangesCommand.cpp
===================================================================
--- plugins/textshape/commands/ShowChangesCommand.cpp	(revision 1095930)
+++ plugins/textshape/commands/ShowChangesCommand.cpp	(working copy)
@@ -18,7 +18,7 @@
  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
 */
-
+#include <iostream>
 #include "ShowChangesCommand.h"
 
 #include <KoChangeTracker.h>
@@ -26,6 +26,11 @@
 #include <KoTextDocument.h>
 #include <KoTextDocumentLayout.h>
 #include <KoTextEditor.h>
+#include <KoTextAnchor.h>
+#include <KoInlineTextObjectManager.h>
+#include <KoCanvasBase.h>
+#include <KoShapeController.h>
+#include <KoShapeContainer.h>
 
 #include <KAction>
 #include <klocale.h>
@@ -33,11 +38,12 @@
 #include <QTextDocument>
 #include <QtAlgorithms>
 
-ShowChangesCommand::ShowChangesCommand(bool showChanges, QTextDocument *document, \
QUndoCommand *parent) : +ShowChangesCommand::ShowChangesCommand(bool showChanges, \
QTextDocument *document, KoCanvasBase *canvas, QUndoCommand *parent) :  \
TextCommandBase (parent),  m_document(document),
     m_first(true),
-    m_showChanges(showChanges)
+    m_showChanges(showChanges),
+    m_canvas(canvas)
 {
     Q_ASSERT(document);
     m_changeTracker = KoTextDocument(m_document).changeTracker();
@@ -114,12 +120,43 @@
             f.setProperty(KoCharacterStyle::ChangeTrackerId, \
element->getDeleteChangeMarker()->changeId());  \
f.clearProperty(KoCharacterStyle::InlineInstanceId);  caret.setCharFormat(f);
+            int insertPosition = caret.position();
             caret.insertFragment(element->getDeleteData());
+            checkAndAddAnchoredShapes(insertPosition, \
                element->getDeleteData().toPlainText().length());
             numAddedChars += element->getDeleteData().toPlainText().length();
         }
     }
 }
 
+void ShowChangesCommand::checkAndAddAnchoredShapes(int position, int length)
+{
+    QTextCursor cursor(m_textEditor->document());
+    for (int i=position;i < (position + length);i++) {
+        if (m_textEditor->document()->characterAt(i) == \
QChar::ObjectReplacementCharacter) { +            cursor.setPosition(i+1);
+            KoInlineObject *object = \
KoTextDocument(m_textEditor->document()).inlineTextObjectManager()->inlineTextObject(cursor);
 +            if (!object)
+                continue;
+
+            KoTextAnchor *anchor = dynamic_cast<KoTextAnchor *>(object);
+            if (!anchor)
+                continue;
+           
+            KoTextDocumentLayout *lay = \
qobject_cast<KoTextDocumentLayout*>(m_document->documentLayout()); +            \
KoShapeContainer *container = dynamic_cast<KoShapeContainer \
*>(lay->shapeForPosition(i)); +            
+            // a very ugly hack. Since this class is going away soon, it should be \
okay +            if (!container)
+                container = dynamic_cast<KoShapeContainer *>((lay->shapes()).at(0));
+
+            if (container) {
+                container->addChild(anchor->shape()); 
+                m_canvas->shapeController()->addShapeDirect(anchor->shape(), \
this)->redo(); +            }
+        }
+    }
+}
+
 void ShowChangesCommand::removeDeletedChanges()
 {
     int numDeletedChars = 0;
@@ -131,14 +168,35 @@
         if (element->isValid()) {
             QTextCursor caret(element->getDeleteChangeMarker()->document());
             QTextCharFormat f;
-            caret.setPosition(element->getDeleteChangeMarker()->position() +  1 - \
numDeletedChars); +            int deletePosition = \
element->getDeleteChangeMarker()->position() + 1 - numDeletedChars; +            \
                caret.setPosition(deletePosition);
             caret.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, \
element->getDeleteData().toPlainText().length()); +            \
checkAndRemoveAnchoredShapes(deletePosition, \
element->getDeleteData().toPlainText().length());  caret.removeSelectedText();
             numDeletedChars += element->getDeleteData().toPlainText().length();
         }
     }
 }
 
+void ShowChangesCommand::checkAndRemoveAnchoredShapes(int position, int length)
+{
+    QTextCursor cursor(m_textEditor->document());
+    for (int i=position;i < (position + length);i++) {
+        if (m_textEditor->document()->characterAt(i) == \
QChar::ObjectReplacementCharacter) { +            cursor.setPosition(i+1);
+            KoInlineObject *object = \
KoTextDocument(m_textEditor->document()).inlineTextObjectManager()->inlineTextObject(cursor);
 +            if (!object)
+                continue;
+
+            KoTextAnchor *anchor = dynamic_cast<KoTextAnchor *>(object);
+            if (!anchor)
+                continue;
+            
+            m_canvas->shapeController()->removeShape(anchor->shape(), this)->redo();
+        }
+    }
+}
+
 ShowChangesCommand::~ShowChangesCommand()
 {
 }
Index: plugins/textshape/commands/ShowChangesCommand.h
===================================================================
--- plugins/textshape/commands/ShowChangesCommand.h	(revision 1095930)
+++ plugins/textshape/commands/ShowChangesCommand.h	(working copy)
@@ -22,20 +22,21 @@
 #define SHOWCHANGECOMMAND_H
 
 #include "TextCommandBase.h"
-
 #include <QObject>
 
 class KoChangeTracker;
 class KoTextEditor;
+class KoCanvasBase;
 
 class QTextDocument;
+class QTextDocumentFragment;
 
 class ShowChangesCommand : public QObject, public TextCommandBase
 {
     Q_OBJECT
 public:
 
-    ShowChangesCommand(bool showChanges, QTextDocument *document, QUndoCommand* \
parent = 0); +    ShowChangesCommand(bool showChanges, QTextDocument *document, \
KoCanvasBase *canvas, QUndoCommand* parent = 0);  ~ShowChangesCommand();
 
     virtual void undo();
@@ -48,13 +49,16 @@
     void enableDisableChanges();
     void enableDisableStates(bool showChanges);
     void insertDeletedChanges();
+    void checkAndAddAnchoredShapes(int position, int length);
     void removeDeletedChanges();
+    void checkAndRemoveAnchoredShapes(int position, int length);
 
     QTextDocument *m_document;
     KoChangeTracker *m_changeTracker;
     KoTextEditor *m_textEditor;
     bool m_first;
     bool m_showChanges;
+    KoCanvasBase *m_canvas;
 };
 
 #endif // SHOWCHANGECOMMAND_H



_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


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

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