sw/inc/ndtxt.hxx                          |    2 +
 sw/qa/extras/uiwriter/data/tdf150824.fodt |   48 ++++++++++++++++++++++++++++++
 sw/qa/extras/uiwriter/uiwriter5.cxx       |   36 ++++++++++++++++++++++
 sw/source/core/doc/docredln.cxx           |   43 ++++++++++++++++++++------
 4 files changed, 118 insertions(+), 11 deletions(-)

New commits:
commit 4d3d1527c4cf8ab6675d42d02cf313796398b220
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Fri May 5 14:44:11 2023 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Mon May 8 13:33:51 2023 +0200

    tdf#147180 sw: fix lost change tracking of empty rows
    
    during partitionating the redline of a tracked text
    containing tables.
    
    Empty tracked table rows use a dummy redline to store
    tracking data. Insert this, when tracked tables in a
    single redline are partitionated after modifying its
    text content, deleting its rows, or using tabulator to
    move cursor in the next cell.
    
    Follow-up to commit a9cf949efcfdb9eb459cabe1b9e15f993e789c73
    "tdf#147180 sw: fix lost change tracking of modified tables".
    
    Tests:
    
    1) Load a tracked empty table, and insert a character
       in the first cell;
    
    2) Insert a tracked empty table with multiple rows, and insert
       two paragraphs in the first cell;
    
    3) Insert a tracked empty table with multiple rows, and delete
       the first row.
    
    4. Insert a tracked empty table with multiple rows, insert a
       character and press tabulator (which triggers partitionating
       as a new regression).
    
    Change-Id: I8bf0f6b201a892a4f54d0bcdde33de440e5be67b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151425
    Tested-by: Jenkins
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index a22d1afeb2c1..c16a643ec76c 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -278,6 +278,8 @@ public:
     OUString InsertText( const OUString & rStr, const SwPosition & rIdx,
                      const SwInsertFlags nMode
                          = SwInsertFlags::DEFAULT );
+    /// Add a dummy character to the redline of the table changes
+    void InsertDummy() { m_Text = OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR); }
 
     /** delete text content
         ATTENTION: must not be called with a range that overlaps the start of
diff --git a/sw/qa/extras/uiwriter/data/tdf150824.fodt 
b/sw/qa/extras/uiwriter/data/tdf150824.fodt
new file mode 100644
index 000000000000..c1e437a12198
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/tdf150824.fodt
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+  <office:text>
+   <text:tracked-changes text:track-changes="false">
+    <text:changed-region xml:id="ct94228217946240" text:id="ct94228217946240">
+     <text:insertion>
+      <office:change-info>
+       <dc:creator>Unknown Author</dc:creator>
+       <dc:date>2022-09-06T14:47:25</dc:date>
+      </office:change-info>
+     </text:insertion>
+    </text:changed-region>
+   </text:tracked-changes>
+   <text:change-start text:change-id="ct94228217946240"/>
+   <table:table table:name="Table1" table:style-name="Table1">
+    <table:table-column table:style-name="Table1.A"/>
+    <table:table-column table:style-name="Table1.B"/>
+    <table:table-row>
+     <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents"/>
+     </table:table-cell>
+     <table:table-cell table:style-name="Table1.B1" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents"/>
+     </table:table-cell>
+    </table:table-row>
+    <table:table-row>
+     <table:table-cell table:style-name="Table1.A2" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents"/>
+     </table:table-cell>
+     <table:table-cell table:style-name="Table1.B2" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents"/>
+     </table:table-cell>
+    </table:table-row>
+    <table:table-row>
+     <table:table-cell table:style-name="Table1.A2" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents"/>
+     </table:table-cell>
+     <table:table-cell table:style-name="Table1.B2" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents"/>
+     </table:table-cell>
+    </table:table-row>
+   </table:table>
+   <text:p text:style-name="Standard"><text:change-end 
text:change-id="ct94228217946240"/></text:p>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx 
b/sw/qa/extras/uiwriter/uiwriter5.cxx
index ec2d8386d711..ee7c041b78c5 100644
--- a/sw/qa/extras/uiwriter/uiwriter5.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter5.cxx
@@ -2417,6 +2417,42 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180_empty_rows)
+{
+    // load a tracked table insertion (single redline) with empty rows
+    createSwDoc("tdf150824.fodt");
+    SwDoc* pDoc = getSwDoc();
+
+    // 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()));
+
+    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xTables(xTextTablesSupplier->getTextTables(),
+                                                    uno::UNO_QUERY);
+    // there is a table in the text
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+
+    // insert a character in the first cell with change tracking
+    SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->Insert("x");
+
+    // reject all the changes, including table insertion
+
+    IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
+    rIDRA.AcceptAllRedline(/*bAccept=*/false);
+
+    // no table left in the text
+
+    // This was 1 (lost tracking of the empty rows after modifying table text 
content)
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335)
 {
     // Load the bugdoc, which has 3 textboxes.
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 5987667a26b3..54d853065629 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -530,6 +530,16 @@ std::vector<std::unique_ptr<SwRangeRedline>> 
GetAllValidRanges(std::unique_ptr<S
             } while( pTab ); // If there is another table we have to repeat 
our step backwards
         }
 
+        // insert dummy character to the empty table rows to keep their changes
+        SwNode& rBoxNode = pNew->GetMark()->GetNode();
+        if ( rBoxNode.GetDoc().GetIDocumentUndoRedo().DoesUndo() && 
rBoxNode.GetTableBox() &&
+             rBoxNode.GetTableBox()->GetUpper()->IsEmpty() && 
rBoxNode.GetTextNode() )
+        {
+            ::sw::UndoGuard const 
undoGuard(rBoxNode.GetDoc().GetIDocumentUndoRedo());
+            rBoxNode.GetTextNode()->InsertDummy();
+            pNew->GetMark()->SetContent( 1 );
+        }
+
         if( *pNew->GetPoint() > *pEnd )
         {
             pC = nullptr;
@@ -582,11 +592,32 @@ std::vector<std::unique_ptr<SwRangeRedline>> 
GetAllValidRanges(std::unique_ptr<S
 
 } // namespace sw
 
+static void lcl_setRowNotTracked(SwNode& rNode)
+{
+    SwDoc& rDoc = rNode.GetDoc();
+    if ( rDoc.GetIDocumentUndoRedo().DoesUndo() && rNode.GetTableBox() )
+    {
+        SvxPrintItem aSetTracking(RES_PRINT, false);
+        SwNodeIndex aInsPos( *(rNode.GetTableBox()->GetSttNd()), 1);
+        SwCursor aCursor( SwPosition(aInsPos), nullptr );
+        ::sw::UndoGuard const undoGuard(rNode.GetDoc().GetIDocumentUndoRedo());
+        rDoc.SetRowNotTracked( aCursor, aSetTracking );
+    }
+}
+
 bool SwRedlineTable::InsertWithValidRanges(SwRangeRedline*& p, size_type* 
pInsPos)
 {
     bool bAnyIns = false;
+    bool bInsert = RedlineType::Insert == p->GetType();
+    SwNode* pSttNode = &p->Start()->GetNode();
+
     std::vector<std::unique_ptr<SwRangeRedline>> redlines(
             GetAllValidRanges(std::unique_ptr<SwRangeRedline>(p)));
+
+    // tdf#147180 set table change tracking in the empty row with text 
insertion
+    if ( bInsert )
+        lcl_setRowNotTracked(*pSttNode);
+
     for (std::unique_ptr<SwRangeRedline> & pRedline : redlines)
     {
         assert(pRedline->HasValidRange());
@@ -595,17 +626,7 @@ bool 
SwRedlineTable::InsertWithValidRanges(SwRangeRedline*& p, size_type* pInsPo
         if (Insert(pTmpRedline, nInsPos))
         {
             // tdf#147180 set table tracking to the table row
-            // TODO handle also empty rows
-            SwDoc& rDoc = pTmpRedline->GetDoc();
-            if ( rDoc.GetIDocumentUndoRedo().DoesUndo() &&
-                 pTmpRedline->GetPointNode().GetTableBox() )
-            {
-                SvxPrintItem aSetTracking(RES_PRINT, false);
-                SwNodeIndex aInsPos( 
*(pTmpRedline->GetPointNode().GetTableBox()->GetSttNd()), 1);
-                SwCursor aCursor( SwPosition(aInsPos), nullptr );
-                ::sw::UndoGuard const 
undoGuard(pTmpRedline->GetDoc().GetIDocumentUndoRedo());
-                rDoc.SetRowNotTracked( aCursor, aSetTracking );
-            }
+            lcl_setRowNotTracked(pTmpRedline->GetPointNode());
 
             pTmpRedline->CallDisplayFunc(nInsPos);
             bAnyIns = true;

Reply via email to