sw/inc/doc.hxx                      |    4 +-
 sw/qa/extras/uiwriter/uiwriter5.cxx |   68 ++++++++++++++++++++++++++++++++++++
 sw/source/core/doc/tblrwcl.cxx      |    2 -
 sw/source/core/docnode/ndtbl1.cxx   |   51 ++++++++++++++++++++++++---
 4 files changed, 118 insertions(+), 7 deletions(-)

New commits:
commit 431c2af3241ebc027fe95213846b98e0456da359
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Wed Sep 7 15:22:37 2022 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri Sep 9 12:49:25 2022 +0200

    tdf#150876 sw: track new rows inserted after a tracked row insertion
    
    New row insertions after an already tracked row insertion
    weren't tracked.
    
    Regression from commit b251228d2e5e2832e0a617213173e8841f5b7428
    "tdf#150666 sw: allow to delete tracked table row insertions"
    
    Follow-up to commit dbc82c02eb24ec1c97c6ee32069771d8deb394f9
    "tdf#143358 sw: track insertion of empty table rows".
    
    Change-Id: Ic365e70aa7808237a1bd69d0101a098ae70e8813
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139594
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit e0bd04c21b9905f4cfadbf9bb879a089ebb49908)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139656
    Tested-by: Jenkins

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 3b407440ed61..6c92c94ae760 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1489,7 +1489,9 @@ public:
     static bool GetRowBackground( const SwCursor& rCursor, 
std::unique_ptr<SvxBrushItem>& rToFill );
     /// rNotTracked = false means that the row was deleted or inserted with 
its tracked cell content
     /// bAll: delete all table rows without selection
-    void SetRowNotTracked( const SwCursor& rCursor, const SvxPrintItem 
&rNotTracked, bool bAll = false );
+    /// bIns: insert table row
+    void SetRowNotTracked( const SwCursor& rCursor,
+                        const SvxPrintItem &rNotTracked, bool bAll = false, 
bool bIns = false );
     /// don't call SetRowNotTracked() for rows with tracked row change
     static bool HasRowNotTracked( const SwCursor& rCursor );
     void SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet );
diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx 
b/sw/qa/extras/uiwriter/uiwriter5.cxx
index 0dfa9e9c11d0..5b5e1d14762e 100644
--- a/sw/qa/extras/uiwriter/uiwriter5.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter5.cxx
@@ -2087,6 +2087,35 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666_regression)
+{
+    // load a table with tracked insertion of an empty row
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "TC-table-rowadd.docx");
+
+    // check table count
+    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xTables(xTextTablesSupplier->getTextTables(),
+                                                    uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+
+    // check table row count
+    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
+
+    // select the second row (tracked table row insertion)
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->Down(/*bSelect=*/false);
+
+    // insert a new table row with track changes
+    dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable->getRows()->getCount());
+
+    dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
+
+    // This was 4 (the inserted table row wasn't tracked)
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144748)
 {
     // load a table with an empty row, and an empty line before the table
diff --git a/sw/source/core/doc/tblrwcl.cxx b/sw/source/core/doc/tblrwcl.cxx
index d92d7726f7b8..4dde7b3e6192 100644
--- a/sw/source/core/doc/tblrwcl.cxx
+++ b/sw/source/core/doc/tblrwcl.cxx
@@ -599,7 +599,7 @@ bool SwTable::InsertRow_( SwDoc* pDoc, const SwSelBoxes& 
rBoxes,
                 SwPaM aPaM(aInsPos);
                 pDoc->getIDocumentContentOperations().InsertString( aPaM,
                         OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
-                pDoc->SetRowNotTracked( aCursor, aSetTracking );
+                pDoc->SetRowNotTracked( aCursor, aSetTracking, /*bAll=*/false, 
/*bIns=*/true );
             }
         }
     }
diff --git a/sw/source/core/docnode/ndtbl1.cxx 
b/sw/source/core/docnode/ndtbl1.cxx
index 0c67775684cd..59c9154f74ca 100644
--- a/sw/source/core/docnode/ndtbl1.cxx
+++ b/sw/source/core/docnode/ndtbl1.cxx
@@ -578,7 +578,8 @@ bool SwDoc::HasRowNotTracked( const SwCursor& rCursor )
     return false;
 }
 
-void SwDoc::SetRowNotTracked( const SwCursor& rCursor, const SvxPrintItem 
&rNew, bool bAll )
+void SwDoc::SetRowNotTracked( const SwCursor& rCursor,
+                                     const SvxPrintItem &rNew, bool bAll, bool 
bIns )
 {
     SwTableNode* pTableNd = 
rCursor.GetPoint()->nNode.GetNode().FindTableNode();
     if( !pTableNd )
@@ -601,28 +602,34 @@ void SwDoc::SetRowNotTracked( const SwCursor& rCursor, 
const SvxPrintItem &rNew,
         
GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoAttrTable>(*pTableNd));
     }
 
+    bool bInsertDummy = !bAll && !bIns &&
+            // HasTextChangesOnly == false, i.e. a tracked row change 
(deletion, if bIns == false)
+            !rNew.GetValue();
     std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
     aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) );
 
     SwRedlineTable::size_type nRedlinePos = 0;
     for( auto pLn : aRowArr )
     {
-        // tdf#150666 row insertion from the same author needs special 
handling,
+        // tdf#150666 deleting row insertion from the same author needs 
special handling,
         // because removing redlines of the author can result an empty line,
         // which doesn't contain any redline for the tracked row
         bool bDeletionOfOwnRowInsertion = false;
-        SwRedlineTable::size_type nPos = 
pLn->UpdateTextChangesOnly(nRedlinePos);
-        if ( nPos != SwRedlineTable::npos )
+        if ( bInsertDummy )
         {
-            SwDoc* pDoc = pLn->GetFrameFormat()->GetDoc();
-            IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
-            const SwRedlineTable& aRedlineTable = rIDRA.GetRedlineTable();
-            SwRangeRedline* pTmp = aRedlineTable[ nPos ];
-            if ( RedlineType::Insert == pTmp->GetType() &&
-                     rIDRA.GetRedlineAuthor() == 
pTmp->GetRedlineData().GetAuthor() &&
-                     pTmp->GetText()[0] == CH_TXT_TRACKED_DUMMY_CHAR )
+            SwRedlineTable::size_type nPos = 
pLn->UpdateTextChangesOnly(nRedlinePos);
+            if ( nPos != SwRedlineTable::npos )
             {
-                bDeletionOfOwnRowInsertion = true;
+                SwDoc* pDoc = pLn->GetFrameFormat()->GetDoc();
+                IDocumentRedlineAccess& rIDRA = 
pDoc->getIDocumentRedlineAccess();
+                const SwRedlineTable& aRedlineTable = rIDRA.GetRedlineTable();
+                SwRangeRedline* pTmp = aRedlineTable[ nPos ];
+                if ( RedlineType::Insert == pTmp->GetType() &&
+                         rIDRA.GetRedlineAuthor() == 
pTmp->GetRedlineData().GetAuthor() &&
+                         pTmp->GetText()[0] == CH_TXT_TRACKED_DUMMY_CHAR )
+                {
+                    bDeletionOfOwnRowInsertion = true;
+                }
             }
         }
 
@@ -631,9 +638,7 @@ void SwDoc::SetRowNotTracked( const SwCursor& rCursor, 
const SvxPrintItem &rNew,
         // add a redline with invisible text CH_TXT_TRACKED_DUMMY_CHAR
         // (unless the table is part of a bigger deletion, where the
         // new redline can cause a problem)
-        if ( !bAll &&
-            // HasTextChangesOnly == false, i.e. a tracked row insertion or 
deletion
-            !rNew.GetValue() && (pLn->IsEmpty() || bDeletionOfOwnRowInsertion 
) )
+        if ( bInsertDummy && (pLn->IsEmpty() || bDeletionOfOwnRowInsertion ) )
         {
             SwNodeIndex aInsPos( *(pLn->GetTabBoxes()[0]->GetSttNd()), 1 );
             RedlineFlags eOld = getIDocumentRedlineAccess().GetRedlineFlags();
commit c46ab9ff1e6bd53881e5f9dfdf9f44e030a93d2b
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Wed Sep 7 09:27:00 2022 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri Sep 9 12:49:12 2022 +0200

    tdf#150666 sw: allow to delete tracked table row insertions
    
    It was not possible to delete tracked table row insertions,
    if only those were selected, or if they were own insertions.
    
    Regression from commit 95213407dfcbf34056037d60243ff915340d1a2e
    "tdf#146622 sw crash fix: don't delete already deleted rows".
    
    Change-Id: Idd3bc78bca1c76bceba63cf339c6d8c73f8f9508
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139575
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit a0566ae34a704a9ad9b147d560007dde7d2ccf7d)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139556
    Tested-by: László Németh <nem...@numbertext.org>

diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx 
b/sw/qa/extras/uiwriter/uiwriter5.cxx
index 1e9d5a0b7560..0dfa9e9c11d0 100644
--- a/sw/qa/extras/uiwriter/uiwriter5.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter5.cxx
@@ -2048,6 +2048,45 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143215)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666)
+{
+    // load a table with tracked insertion of an empty row
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "TC-table-rowadd.docx");
+
+    // check table count
+    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xTables(xTextTablesSupplier->getTextTables(),
+                                                    uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+
+    // check table row count
+    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
+
+    // select the second row (tracked table row insertion)
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->Down(/*bSelect=*/false);
+
+    // delete it, and accept all tracked changes
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+    dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
+
+    // This was 4 (it was not possible to delete only the tracked row 
insertions)
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
+
+    // insert a new table row with track changes
+    dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
+
+    // select and delete it
+    pWrtShell->Down(/*bSelect=*/false);
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+    dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
+
+    // This was 4 (it was not possible to delete own tracked row insertions)
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144748)
 {
     // load a table with an empty row, and an empty line before the table
diff --git a/sw/source/core/docnode/ndtbl1.cxx 
b/sw/source/core/docnode/ndtbl1.cxx
index 35f4b8e7e943..0c67775684cd 100644
--- a/sw/source/core/docnode/ndtbl1.cxx
+++ b/sw/source/core/docnode/ndtbl1.cxx
@@ -52,6 +52,7 @@
 #include <o3tl/enumrange.hxx>
 #include <o3tl/safeint.hxx>
 #include <osl/diagnose.h>
+#include <redline.hxx>
 
 using ::editeng::SvxBorderLine;
 using namespace ::com::sun::star;
@@ -540,6 +541,7 @@ bool SwDoc::GetRowBackground( const SwCursor& rCursor, 
std::unique_ptr<SvxBrushI
     return bRet;
 }
 
+// has a table row, which is not a tracked deletion
 bool SwDoc::HasRowNotTracked( const SwCursor& rCursor )
 {
     SwTableNode* pTableNd = 
rCursor.GetPoint()->nNode.GetNode().FindTableNode();
@@ -552,12 +554,26 @@ bool SwDoc::HasRowNotTracked( const SwCursor& rCursor )
     if( aRowArr.empty() )
         return false;
 
+    SwRedlineTable::size_type nRedlinePos = 0;
+    SwDoc* pDoc = aRowArr[0]->GetFrameFormat()->GetDoc();
+    const IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
+
     for( auto pLn : aRowArr )
     {
         auto pHasTextChangesOnlyProp = 
pLn->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT);
         if ( !pHasTextChangesOnlyProp || pHasTextChangesOnlyProp->GetValue() )
-            // there is a not deleted row in the table selection
+            // there is a not tracked row in the table selection
             return true;
+
+        // tdf#150666 examine tracked row: it's possible to delete a tracked 
insertion
+        SwRedlineTable::size_type nPos = 
pLn->UpdateTextChangesOnly(nRedlinePos);
+        if ( nPos != SwRedlineTable::npos )
+        {
+            const SwRedlineTable& aRedlineTable = rIDRA.GetRedlineTable();
+            SwRangeRedline* pTmp = aRedlineTable[ nPos ];
+            if ( RedlineType::Insert == pTmp->GetType() )
+                return true;
+        }
     }
     return false;
 }
@@ -588,8 +604,28 @@ void SwDoc::SetRowNotTracked( const SwCursor& rCursor, 
const SvxPrintItem &rNew,
     std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
     aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) );
 
+    SwRedlineTable::size_type nRedlinePos = 0;
     for( auto pLn : aRowArr )
     {
+        // tdf#150666 row insertion from the same author needs special 
handling,
+        // because removing redlines of the author can result an empty line,
+        // which doesn't contain any redline for the tracked row
+        bool bDeletionOfOwnRowInsertion = false;
+        SwRedlineTable::size_type nPos = 
pLn->UpdateTextChangesOnly(nRedlinePos);
+        if ( nPos != SwRedlineTable::npos )
+        {
+            SwDoc* pDoc = pLn->GetFrameFormat()->GetDoc();
+            IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
+            const SwRedlineTable& aRedlineTable = rIDRA.GetRedlineTable();
+            SwRangeRedline* pTmp = aRedlineTable[ nPos ];
+            if ( RedlineType::Insert == pTmp->GetType() &&
+                     rIDRA.GetRedlineAuthor() == 
pTmp->GetRedlineData().GetAuthor() &&
+                     pTmp->GetText()[0] == CH_TXT_TRACKED_DUMMY_CHAR )
+            {
+                bDeletionOfOwnRowInsertion = true;
+            }
+        }
+
         ::lcl_ProcessRowAttr( aFormatCmp, pLn, rNew );
         // as a workaround for the rows without text content,
         // add a redline with invisible text CH_TXT_TRACKED_DUMMY_CHAR
@@ -597,7 +633,7 @@ void SwDoc::SetRowNotTracked( const SwCursor& rCursor, 
const SvxPrintItem &rNew,
         // new redline can cause a problem)
         if ( !bAll &&
             // HasTextChangesOnly == false, i.e. a tracked row insertion or 
deletion
-            !rNew.GetValue() && pLn->IsEmpty() )
+            !rNew.GetValue() && (pLn->IsEmpty() || bDeletionOfOwnRowInsertion 
) )
         {
             SwNodeIndex aInsPos( *(pLn->GetTabBoxes()[0]->GetSttNd()), 1 );
             RedlineFlags eOld = getIDocumentRedlineAccess().GetRedlineFlags();

Reply via email to