[Libreoffice-commits] core.git: sw/inc sw/qa sw/source

László Németh (via logerrit) logerrit at kemper.freedesktop.org
Wed Mar 17 21:17:56 UTC 2021


 sw/inc/IDocumentMarkAccess.hxx            |    2 
 sw/qa/extras/uiwriter/data2/tdf115815.odt |binary
 sw/qa/extras/uiwriter/uiwriter2.cxx       |   74 +++++++++++++++++++++++++++++-
 sw/source/core/doc/docbm.cxx              |   13 +++--
 sw/source/core/doc/docredln.cxx           |   67 ++++++++++++++++-----------
 sw/source/core/inc/MarkManager.hxx        |    2 
 sw/source/uibase/shells/basesh.cxx        |    6 ++
 7 files changed, 131 insertions(+), 33 deletions(-)

New commits:
commit a001a66ba27e2fe9a485388869d53f001f2b09af
Author:     László Németh <nemeth at numbertext.org>
AuthorDate: Wed Mar 17 11:24:42 2021 +0100
Commit:     László Németh <nemeth at numbertext.org>
CommitDate: Wed Mar 17 22:17:12 2021 +0100

    tdf#140982 sw ChangesInMargin: fix annotation ranges
    
    Annotation ranges of tracked deletions collapsed in
    ChangesInMargin mode (as before saving the document,
    see commit d325cd0c69b7c0cc4f47105749a98995de81cc9d
    "tdf#115815 sw: fix lost annotation ranges of redlines").
    
    Change-Id: I413804cfcdf972f054b65e28e6265c30d25731e3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112644
    Tested-by: László Németh <nemeth at numbertext.org>
    Reviewed-by: László Németh <nemeth at numbertext.org>

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index 801ce98ba503..49ce72ad28b4 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -343,7 +343,7 @@ class IDocumentMarkAccess
         virtual sw::mark::IMark* getAnnotationMarkFor(const SwPosition& rPosition) const = 0;
         // restore text ranges of annotations of tracked deletions
         // based on the helper bookmarks (which can survive I/O and hiding redlines)
-        virtual void restoreAnnotationMarks() = 0;
+        virtual void restoreAnnotationMarks(bool bDelete = true) = 0;
         /** Finds the first mark that is starting after.
 
             @returns
diff --git a/sw/qa/extras/uiwriter/data2/tdf115815.odt b/sw/qa/extras/uiwriter/data2/tdf115815.odt
new file mode 100644
index 000000000000..7c2aad0da638
Binary files /dev/null and b/sw/qa/extras/uiwriter/data2/tdf115815.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 0bc22e23aca4..97fea5d32797 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -2390,7 +2390,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf138666)
     CPPUNIT_ASSERT_EQUAL(OUString("Loremm"), getParagraph(1)->getString());
     CPPUNIT_ASSERT_EQUAL(OUString("dolsit"), getParagraph(2)->getString());
 
-    // switch on "Show changes in margin" mode
+    // switch off "Show changes in margin" mode
     dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
 
     // show deletions inline again
@@ -2398,6 +2398,78 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf138666)
     CPPUNIT_ASSERT_EQUAL(OUString("dolor sit"), getParagraph(2)->getString());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf140982)
+{
+    SwDoc* pDoc = createDoc("tdf115815.odt");
+
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+
+    //turn on red-lining and show changes
+    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
+                                                      | RedlineFlags::ShowInsert);
+    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
+                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+    CPPUNIT_ASSERT_MESSAGE(
+        "redlines should be visible",
+        IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+
+    // show deletions inline
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum dolor sit amet..."), getParagraph(1)->getString());
+
+    // switch on "Show changes in margin" mode
+    dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
+
+    // show deletions in margin
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem  amet..."), getParagraph(1)->getString());
+
+    // switch off "Show changes in margin" mode
+    dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
+
+    // show deletions inline again
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum dolor sit amet..."), getParagraph(1)->getString());
+
+    // Save it and load it back.
+    reload("writer8", "tdf115815.odt");
+
+    // Test comment range feature on tracked deletion.
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
+                                                                  uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
+    uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(),
+                                                                 uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
+    bool bAnnotationStart = false;
+    bool bBeforeAnnotation = true;
+    OUString sTextBeforeAnnotation;
+    while (xRunEnum->hasMoreElements())
+    {
+        uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
+        OUString aType = getProperty<OUString>(xPropertySet, "TextPortionType");
+        // there is no AnnotationEnd with preceding AnnotationStart,
+        // i.e. annotation with lost range
+        CPPUNIT_ASSERT(aType != "AnnotationEnd" || !bAnnotationStart);
+
+        bAnnotationStart = (aType == "Annotation");
+
+        // collect paragraph text before the first annotation
+        if (bBeforeAnnotation)
+        {
+            if (bAnnotationStart)
+                bBeforeAnnotation = false;
+            else if (aType == "Text")
+            {
+                uno::Reference<text::XTextRange> xRun(xPropertySet, uno::UNO_QUERY);
+                sTextBeforeAnnotation += xRun->getString();
+            }
+        }
+    }
+
+    // This was "Lorem ipsum" (collapsed annotation range)
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), sTextBeforeAnnotation);
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf126206)
 {
     load(DATA_DIRECTORY, "tdf126206.docx");
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 9061e7b853d1..82579d079445 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -1643,7 +1643,7 @@ namespace sw::mark
 
     // restore text ranges of annotations of tracked deletions
     // based on the helper bookmarks (which can survive I/O and hiding redlines)
-    void MarkManager::restoreAnnotationMarks()
+    void MarkManager::restoreAnnotationMarks(bool bDelete)
     {
         for (auto iter = getBookmarksBegin();
               iter != getBookmarksEnd(); )
@@ -1660,9 +1660,14 @@ namespace sw::mark
                     const SwPaM aPam((**iter).GetMarkStart(), (**pMark).GetMarkEnd());
                     repositionMark(*pMark, aPam);
                 }
-                deleteMark(&**iter);
-                // this invalidates iter, have to start over...
-                iter = getBookmarksBegin();
+                if (bDelete)
+                {
+                    deleteMark(&**iter);
+                    // this invalidates iter, have to start over...
+                    iter = getBookmarksBegin();
+                }
+                else
+                    ++iter;
             }
             else
                 ++iter;
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 292600a171d6..d4d5cce88483 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -1335,6 +1335,42 @@ void SwRangeRedline::CalcStartEnd( sal_uLong nNdIdx, sal_Int32& rStart, sal_Int3
     }
 }
 
+static void lcl_storeAnnotationMarks(SwDoc& rDoc, const SwPosition* pStt, const SwPosition* pEnd)
+{
+    // tdf#115815 keep original start position of collapsed annotation ranges
+    // as temporary bookmarks (removed after file saving and file loading)
+    IDocumentMarkAccess& rDMA(*rDoc.getIDocumentMarkAccess());
+    for (auto iter = rDMA.getAnnotationMarksBegin();
+          iter != rDMA.getAnnotationMarksEnd(); )
+    {
+        SwPosition const& rStartPos((**iter).GetMarkStart());
+        if ( *pStt <= rStartPos && rStartPos < *pEnd )
+        {
+            OUString sBookmarkName((**iter).GetName() + "____");
+            IDocumentMarkAccess::const_iterator_t pOldMark = rDMA.findBookmark(sBookmarkName);
+            if ( pOldMark == rDMA.getBookmarksEnd() )
+            {
+                // at start of redlines use a 1-character length bookmark range
+                // instead of a 0-character length bookmark position to avoid its losing
+                sal_Int32 nLen = (*pStt == rStartPos) ? 1 : 0;
+                SwPaM aPam( rStartPos.nNode, rStartPos.nContent.GetIndex(),
+                                rStartPos.nNode, rStartPos.nContent.GetIndex() + nLen);
+                ::sw::mark::IMark* pMark = rDMA.makeMark(
+                    aPam,
+                    sBookmarkName,
+                    IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
+                ::sw::mark::IBookmark* pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pMark);
+                if (pBookmark)
+                {
+                    pBookmark->SetKeyCode(vcl::KeyCode());
+                    pBookmark->SetShortName(OUString());
+                }
+            }
+        }
+        ++iter;
+    }
+}
+
 void SwRangeRedline::MoveToSection()
 {
     if( !m_pContentSect )
@@ -1378,7 +1414,11 @@ void SwRangeRedline::MoveToSection()
             SwNodeIndex aNdIdx( *pTextNd );
             SwPosition aPos( aNdIdx, SwIndex( pTextNd ));
             if( pCSttNd && pCEndNd )
+            {
+                // tdf#140982 keep annotation ranges in deletions in margin mode
+                lcl_storeAnnotationMarks( rDoc, pStt, pEnd );
                 rDoc.getIDocumentContentOperations().MoveAndJoin( aPam, aPos );
+            }
             else
             {
                 if( pCSttNd && !pCEndNd )
@@ -1445,32 +1485,7 @@ void SwRangeRedline::CopyToSection()
 
         // tdf#115815 keep original start position of collapsed annotation ranges
         // as temporary bookmarks (removed after file saving and file loading)
-        auto & rDMA(*rDoc.getIDocumentMarkAccess());
-        for (auto iter = rDMA.getAnnotationMarksBegin();
-              iter != rDMA.getAnnotationMarksEnd(); )
-        {
-            SwPosition const& rStartPos((**iter).GetMarkStart());
-            if ( *pStt <= rStartPos && rStartPos < *pEnd )
-            {
-                // at start of redlines use a 1-character length bookmark range
-                // instead of a 0-character length bookmark position to avoid its losing
-                sal_Int32 nLen = (*pStt == rStartPos) ? 1 : 0;
-                SwPaM aPam( rStartPos.nNode, rStartPos.nContent.GetIndex(),
-                                rStartPos.nNode, rStartPos.nContent.GetIndex() + nLen);
-                ::sw::mark::IMark* pMark = rDMA.makeMark(
-                    aPam,
-                    (**iter).GetName() + "____",
-                    IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
-                ::sw::mark::IBookmark* pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pMark);
-                if (pBookmark)
-                {
-                    pBookmark->SetKeyCode(vcl::KeyCode());
-                    pBookmark->SetShortName(OUString());
-                }
-            }
-            ++iter;
-        }
-
+        lcl_storeAnnotationMarks( rDoc, pStt, pEnd );
         rDoc.getIDocumentContentOperations().CopyRange(*this, aPos, SwCopyFlags::CheckPosInFly);
 
         // Take over the style from the EndNode if needed
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index 4bc216ff3c7d..4e1547f00731 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -117,7 +117,7 @@ namespace sw::mark {
 
             typedef std::vector<sw::mark::MarkBase*> container_t;
 
-            virtual void restoreAnnotationMarks() override;
+            virtual void restoreAnnotationMarks(bool bDelete = true) override;
 
         private:
 
diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx
index c91fab016851..41e1c96f2711 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -1065,6 +1065,12 @@ void SwBaseShell::Execute(SfxRequest &rReq)
             if ( !bAllInText )
                 aViewOption.SetShowChangesInMargin2( FN_SET_TRACKED_INSERTIONS_IN_MARGIN == nSlot );
             rSh.ApplyViewOptions( aViewOption );
+
+            // tdf#140982 restore annotation ranges stored in temporary bookmarks
+            // (only remove temporary bookmarks during file saving to avoid possible
+            // conflict with lazy deletion of the bookmarks of the moved tracked deletions)
+            if ( bAllInText || FN_SET_TRACKED_INSERTIONS_IN_MARGIN == nSlot )
+                rSh.GetDoc()->getIDocumentMarkAccess()->restoreAnnotationMarks(false);
         }
         break;
         case SID_CONTOUR_DLG:


More information about the Libreoffice-commits mailing list