sw/inc/doc.hxx                      |    2 +
 sw/qa/extras/uiwriter/uiwriter3.cxx |   53 ++++++++++++++++++++++++++++++++++++
 sw/source/core/docnode/ndtbl1.cxx   |   22 ++++++++++++++
 sw/source/core/frmedt/fetab.cxx     |   12 +++-----
 4 files changed, 82 insertions(+), 7 deletions(-)

New commits:
commit b907c008c2c65ca461097cfc636883331fd1357c
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Mon Feb 14 19:13:37 2022 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Mon Feb 21 18:41:59 2022 +0100

    tdf#146622 sw crash fix: don't delete already deleted rows
    
    Delete tables and rows removed also tables and table rows
    with tracked row deletion/insertion. This resulted not only
    lost change tracking, but a crashing Undo.
    
    Crash regression from commit 99059a1ececa3621c2fe46fabdd79eed9d626c42
    "tdf#143359 sw: track deletion of empty table rows".
    
    Non-tracked deletion of the tracked row changes was a
    temporary solution for the missing UI of tracked
    row changes, implemented in commit 05366b8e6683363688de8708a3d88cf144c7a2bf
    "tdf#60382 sw offapi: add change tracking of table/row deletion".
    
    Note: UI was added in commit f348440e17debacbcba9153e238e010e8c020bdc
    "tdf#146120 sw: show tracked table changes with different color",
    commit 95c003d75e0f8b255344715a35358072b5eba99d
    "tdf#146145 sw: 1-click Accept/Reject of table row changes",
    commit 84fbb3398f7486f00e7b7dea415e1ea2510a9535
    "tdf#146144 sw: add tooltip to table rows with change tracking",
    commit eebe4747d2d13545004937bb0267ccfc8ab9d63f
    "tdf#144270 sw: manage tracked table (row) deletion/insertion",
    commit f481c2c8e74bded11fac754e493560391229dbcd
    "tdf#144057 sw track changes: hide deleted table rows" and
    commit 23846867ea32667ccf328c36142394dd6aaee8ba
    "tdf#147182 sw: accept/reject all changes of a table selection".
    
    (cherry-picked from commit 95213407dfcbf34056037d60243ff915340d1a2e)
    
    Change-Id: I384b750b0d3626fa8b3f256c7eaf5b93f382e4e5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130011
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 6b80222d6bc043eb78a2986e9051cee3e5ee0967)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130019
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 831c59d2cc05..f7749190e3ea 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1491,6 +1491,8 @@ public:
     /// 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 );
+    /// don't call SetRowNotTracked() for rows with tracked row change
+    static bool HasRowNotTracked( const SwCursor& rCursor );
     void SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet );
     void SetTabLineStyle( const SwCursor& rCursor,
                           const Color* pColor, bool bSetLine,
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx 
b/sw/qa/extras/uiwriter/uiwriter3.cxx
index cf8c4e07e9b6..d2123c33b20c 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -1890,6 +1890,59 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf132744)
     CPPUNIT_ASSERT_EQUAL(1, getShapes());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf146622)
+{
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "TC-table-del-add.docx");
+    CPPUNIT_ASSERT(pDoc);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+
+    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
+                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+
+    uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xTables(xTablesSupplier->getTextTables(),
+                                                    uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTables->getCount());
+    uno::Reference<container::XNameAccess> xTableNames = 
xTablesSupplier->getTextTables();
+    CPPUNIT_ASSERT(xTableNames->hasByName("Table1"));
+    uno::Reference<text::XTextTable> xTable1(xTableNames->getByName("Table1"), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1->getRows()->getCount());
+
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+
+    // This was 3 (deleting the already deleted row with change tracking)
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1->getRows()->getCount());
+
+    dispatchCommand(mxComponent, ".uno:SelectAll", {});
+    dispatchCommand(mxComponent, ".uno:SelectAll", {});
+    Scheduler::ProcessEventsToIdle();
+
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1->getRows()->getCount());
+
+    dispatchCommand(mxComponent, ".uno:SelectAll", {});
+    dispatchCommand(mxComponent, ".uno:SelectAll", {});
+    Scheduler::ProcessEventsToIdle();
+
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+    // This was 2 (deleting the already deleted table with change tracking)
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTables->getCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1->getRows()->getCount());
+
+    // check that the first table was deleted with change tracking
+    dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+
+    // Undo AcceptAllTrackedChanges and DeleteRows
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+
+    // now only the second table deleted by AcceptAllTrackedChanges
+    dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables->getCount());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf135014)
 {
     createSwDoc();
diff --git a/sw/source/core/docnode/ndtbl1.cxx 
b/sw/source/core/docnode/ndtbl1.cxx
index 1cb5fc651b6c..4d0e38b794ab 100644
--- a/sw/source/core/docnode/ndtbl1.cxx
+++ b/sw/source/core/docnode/ndtbl1.cxx
@@ -540,6 +540,28 @@ bool SwDoc::GetRowBackground( const SwCursor& rCursor, 
std::unique_ptr<SvxBrushI
     return bRet;
 }
 
+bool SwDoc::HasRowNotTracked( const SwCursor& rCursor )
+{
+    SwTableNode* pTableNd = 
rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+    if( !pTableNd )
+        return false;
+
+    std::vector<SwTableLine*> aRowArr; // For Lines collecting
+    ::lcl_CollectLines( aRowArr, rCursor, true );
+
+    if( aRowArr.empty() )
+        return false;
+
+    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
+            return true;
+    }
+    return false;
+}
+
 void SwDoc::SetRowNotTracked( const SwCursor& rCursor, const SvxPrintItem 
&rNew, bool bAll )
 {
     SwTableNode* pTableNd = 
rCursor.GetPoint()->nNode.GetNode().FindTableNode();
diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx
index f388067c27c5..ec9968271d3d 100644
--- a/sw/source/core/frmedt/fetab.cxx
+++ b/sw/source/core/frmedt/fetab.cxx
@@ -332,8 +332,11 @@ bool SwFEShell::DeleteRow(bool bCompleteTable)
     // and set IsNoTracked table line property to false
     if ( GetDoc()->GetDocShell()->IsChangeRecording() )
     {
+        // all rows have already had tracked row change in the table selection
+        if ( !SwDoc::HasRowNotTracked( *getShellCursor( false ) ) )
+            return false;
+
         SwEditShell* pEditShell = GetDoc()->GetEditShell();
-        SwRedlineTable::size_type nOldRedlineCount = 
pEditShell->GetRedlineCount();
         StartUndo(bCompleteTable ? SwUndoId::UI_TABLE_DELETE : 
SwUndoId::ROW_DELETE);
         StartAllAction();
 
@@ -347,12 +350,7 @@ bool SwFEShell::DeleteRow(bool bCompleteTable)
 
         EndAllActionAndCall();
         EndUndo(bCompleteTable ? SwUndoId::UI_TABLE_DELETE : 
SwUndoId::ROW_DELETE);
-
-        // track row deletion only if there were tracked text changes
-        // FIXME redline count can be the same in special cases, e.g. adding a
-        // new tracked deletion with removing an own tracked insertion...
-        if ( nOldRedlineCount != pEditShell->GetRedlineCount() )
-            return true;
+        return true;
     }
 
     StartAllAction();

Reply via email to