schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng |    9 +
 sw/inc/swtable.hxx                                          |    2 
 sw/qa/extras/uiwriter/uiwriter5.cxx                         |   85 ++++++++++++
 sw/source/core/doc/DocumentRedlineManager.cxx               |   15 ++
 sw/source/core/layout/paintfrm.cxx                          |   12 +
 sw/source/core/table/swtable.cxx                            |   17 ++
 sw/source/filter/xml/xmlitemm.cxx                           |    3 
 sw/source/filter/xml/xmltble.cxx                            |   21 ++
 8 files changed, 161 insertions(+), 3 deletions(-)

New commits:
commit 1fdb056ef034109f330b79c85da39af44c3a8251
Author:     László Németh <[email protected]>
AuthorDate: Wed May 10 15:24:24 2023 +0200
Commit:     László Németh <[email protected]>
CommitDate: Thu May 11 13:52:26 2023 +0200

    tdf#150673 sw tracked table column: color deletion
    
    Reset also HasTextChangesOnly property of the table cell
    at rejecting the deletion.
    
    Follow-up to commit f348440e17debacbcba9153e238e010e8c020bdc
    "tdf#146120 sw: show tracked table changes with different color".
    
    Change-Id: I7bc1643b13a54934d1538f39e0a0d4516c88fa31
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151638
    Tested-by: Jenkins
    Reviewed-by: László Németh <[email protected]>

diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index bd674486278f..0e01f1caecb5 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -552,6 +552,8 @@ public:
         sal_uInt16 nMaxStep ) const
         { return const_cast<SwTableBox*>(this)->FindEndOfRowSpan( rTable, 
nMaxStep ); }
     void RegisterToFormat( SwFormat& rFormat ) ;
+    // get redline type
+    RedlineType GetRedlineType() const;
 };
 
 class SwCellFrame;
diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx 
b/sw/qa/extras/uiwriter/uiwriter5.cxx
index 52fefec9194a..4dd0a42d83c0 100644
--- a/sw/qa/extras/uiwriter/uiwriter5.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter5.cxx
@@ -2603,6 +2603,42 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, 
testTdf150673_RedlineTableColumnDeletionWi
     pXmlDoc = parseLayoutDump();
     assertXPath(pXmlDoc, "//page[1]//body/tab");
     assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
+
+    // check removing HasTextChangesOnly at acceptance of the deletion
+
+    // Undo, and delete the column without change tracking
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+
+    // table column exists again
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
+
+    // reject deletion, setting HasTextChangesOnly to TRUE
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), 
pEditShell->GetRedlineCount());
+    pEditShell->RejectRedline(0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), 
pEditShell->GetRedlineCount());
+
+    // delete table column with enabled change tracking
+    dispatchCommand(mxComponent, ".uno:SelectColumn", {});
+    dispatchCommand(mxComponent, ".uno:Delete", {});
+
+    // Table column still exists
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
+
+    // reject the deletion of the content of the first cell
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), 
pEditShell->GetRedlineCount());
+    pEditShell->AcceptRedline(0);
+
+    // table column is still not deleted
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
 }
 
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335)
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index 8ce8a4873aab..ac0bfe547e90 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -509,6 +509,21 @@ namespace
         if ( !pBox )
             return;
 
+        // tracked column deletion
+
+        const SvxPrintItem *pHasBoxTextChangesOnlyProp =
+                
pBox->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT);
+        // table cell property "HasTextChangesOnly" is set and its value is 
false
+        if ( bRejectDeletion && pHasBoxTextChangesOnlyProp &&
+                !pHasBoxTextChangesOnlyProp->GetValue() )
+        {
+            SvxPrintItem aUnsetTracking(RES_PRINT, true);
+            SwCursor aCursor( *pPos, nullptr );
+            pPos->GetDoc().SetBoxAttr( aCursor, aUnsetTracking );
+        }
+
+        // tracked row deletion
+
         const SwTableLine* pLine = pBox->GetUpper();
         const SvxPrintItem *pHasTextChangesOnlyProp =
                 
pLine->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT);
diff --git a/sw/source/core/layout/paintfrm.cxx 
b/sw/source/core/layout/paintfrm.cxx
index c4134fbfa2ee..47e56b390712 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -6540,7 +6540,17 @@ void SwFrame::PaintSwFrameBackground( const SwRect 
&rRect, const SwPageFrame *pP
             bBack = true;
         }
     }
-    else if ( bBack && IsCellFrame() && !getRootFrame()->IsHideRedlines() &&
+    else if ( IsCellFrame() && !getRootFrame()->IsHideRedlines() )
+    {
+        RedlineType eType = static_cast<const 
SwCellFrame*>(this)->GetTabBox()->GetRedlineType();
+        if ( RedlineType::Delete == eType || RedlineType::Insert == eType )
+        {
+            pCol = RedlineType::Delete == eType ? COL_AUTHOR_TABLE_DEL : 
COL_AUTHOR_TABLE_INS;
+            bBack = true;
+        }
+    }
+
+    if ( bBack && IsCellFrame() && !getRootFrame()->IsHideRedlines() &&
         // skip cell background to show the row colored according to its 
tracked change
         RedlineType::None != static_cast<const 
SwRowFrame*>(GetUpper())->GetTabLine()->GetRedlineType() )
     {
diff --git a/sw/source/core/table/swtable.cxx b/sw/source/core/table/swtable.cxx
index d4881974e5df..83cb70fc0a65 100644
--- a/sw/source/core/table/swtable.cxx
+++ b/sw/source/core/table/swtable.cxx
@@ -2960,6 +2960,23 @@ void SwTableBox::ActualiseValueBox()
     }
 }
 
+RedlineType SwTableBox::GetRedlineType() const
+{
+    const SwRedlineTable& aRedlineTable = 
GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable();
+    if ( aRedlineTable.empty() )
+        return RedlineType::None;
+
+    // check table row property "HasTextChangesOnly", if it's defined and its 
value is
+    // false, return with RedlineType::Delete
+    // TODO add support for RedlineType::Insert
+    const SvxPrintItem *pHasTextChangesOnlyProp =
+            GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT);
+    if ( pHasTextChangesOnlyProp && !pHasTextChangesOnlyProp->GetValue() )
+        return RedlineType::Delete;
+
+    return RedlineType::None;
+}
+
 struct SwTableCellInfo::Impl
 {
     const SwTable * m_pTable;
commit ffd8d20d368a885d6d786749278fa438573227a7
Author:     László Németh <[email protected]>
AuthorDate: Wed May 10 11:39:49 2023 +0200
Commit:     László Németh <[email protected]>
CommitDate: Thu May 11 13:52:16 2023 +0200

    tdf#150673 sw xmloff: import/export tracked table column
    
    to OpenDocument format using
    
    <style:table-cell-properties loext:text-changes-only="false"/>
    
    Follow-up to commit 05366b8e6683363688de8708a3d88cf144c7a2bf
    "tdf#60382 sw offapi: add change tracking of table/row deletion"
    and commit 48898a72066ff9982feafebb26708c4e779fd460
    "tdf#60382 sw xmloff: import/export tracked table/row deletion".
    
    Change-Id: I6fb37322056a42a6746db0e4144b0848b0754b0f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151606
    Tested-by: László Németh <[email protected]>
    Reviewed-by: László Németh <[email protected]>

diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng 
b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
index 5fe259dbd5e5..c0a983f46aab 100644
--- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
@@ -3210,6 +3210,15 @@ 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
     </rng:optional>
   </rng:define>
 
+  <!-- TODO no proposal -->
+  <rng:define name="style-table-cell-properties-attlist" combine="interleave">
+    <rng:optional>
+      <rng:attribute name="loext:text-changes-only">
+        <rng:ref name="boolean"/>
+      </rng:attribute>
+    </rng:optional>
+  </rng:define>
+
   <!-- https://issues.oasis-open.org/browse/OFFICE-4108 -->
   <rng:define name="common-num-format-prefix-suffix-attlist" 
combine="interleave">
     <rng:optional>
diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx 
b/sw/qa/extras/uiwriter/uiwriter5.cxx
index 38fe2143a992..52fefec9194a 100644
--- a/sw/qa/extras/uiwriter/uiwriter5.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter5.cxx
@@ -2556,6 +2556,55 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, 
testRedlineTableColumnDeletion)
     assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, 
testTdf150673_RedlineTableColumnDeletionWithExport)
+{
+    // load a table, and delete the first column with enabled change tracking:
+    // now the column is not deleted silently, but keeps the deleted cell 
contents,
+    // and only accepting all of them will result the deletion of the table 
column.
+    createSwDoc("tdf118311.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()));
+
+    // check table
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // delete table column with enabled change tracking
+    // (HasTextChangesOnly property of the cell will be false)
+    dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
+
+    // Deleted text content with change tracking,
+    // but not table deletion
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
+
+    // Save it and load it back.
+    reload("writer8", "tdf150673_tracked_column_deletion.odt");
+    pDoc = getSwDoc();
+
+    // accept the deletion of the content of the first cell
+    SwEditShell* const pEditShell(pDoc->GetEditShell());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), 
pEditShell->GetRedlineCount());
+    pEditShell->AcceptRedline(0);
+
+    // first table column was deleted finally
+    // (working export/import of HasTextChangesOnly)
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335)
 {
     // Load the bugdoc, which has 3 textboxes.
diff --git a/sw/source/filter/xml/xmlitemm.cxx 
b/sw/source/filter/xml/xmlitemm.cxx
index 1d610b6a9966..a8de955916e9 100644
--- a/sw/source/filter/xml/xmlitemm.cxx
+++ b/sw/source/filter/xml/xmlitemm.cxx
@@ -219,7 +219,8 @@ const SvXMLItemMapEntry aTableCellItemMap[] =
     // RES_FOOTER
     // not required
     // RES_PRINT
-    // not required
+    // M_E_SE( STYLE, TEXT_CHANGES_ONLY, RES_PRINT, 0 ),
+    M_E_SE( LO_EXT, TEXT_CHANGES_ONLY, RES_PRINT, 0 ),
     // RES_OPAQUE
     // not required
     // RES_PROTECT
diff --git a/sw/source/filter/xml/xmltble.cxx b/sw/source/filter/xml/xmltble.cxx
index 4181a869ce45..31b24dc02005 100644
--- a/sw/source/filter/xml/xmltble.cxx
+++ b/sw/source/filter/xml/xmltble.cxx
@@ -334,9 +334,11 @@ static OUString 
lcl_xmltble_appendBoxPrefix(std::u16string_view rNamePrefix,
                                                 false );
     const SvXMLAttrContainerItem *pAttCnt = rItemSet.GetItemIfSet( 
RES_UNKNOWNATR_CONTAINER,
                                                 false );
+    const SvxPrintItem *pHasTextChangesOnly = rItemSet.GetItemIfSet( 
RES_PRINT, false);
 
     // empty styles have not to be exported
-    if( !pVertOrient && !pBrush && !pBox && !pNumFormat && !pFrameDir && 
!pAttCnt )
+    if( !pVertOrient && !pBrush && !pBox && !pNumFormat && !pFrameDir && 
!pAttCnt &&
+        !pHasTextChangesOnly )
     {
         m_rFormatMap.try_emplace(&rFrameFormat); // empty just to enable assert
         return {};
@@ -357,6 +359,7 @@ static OUString 
lcl_xmltble_appendBoxPrefix(std::u16string_view rNamePrefix,
         const SwTableBoxNumFormat *pTestNumFormat = nullptr;
         const SvxFrameDirectionItem *pTestFrameDir = nullptr;
         const SvXMLAttrContainerItem *pTestAttCnt = nullptr;
+        const SvxPrintItem *pTestHasTextChangesOnly = rItemSet.GetItemIfSet( 
RES_PRINT, false);
         const SwFrameFormat* pTestFormat = *i;
         const SfxItemSet& rTestSet = pTestFormat->GetAttrSet();
         if( const SwFormatVertOrient* pItem = rTestSet.GetItemIfSet( 
RES_VERT_ORIENT, false ) )
@@ -443,6 +446,19 @@ static OUString 
lcl_xmltble_appendBoxPrefix(std::u16string_view rNamePrefix,
 
         }
 
+        if( const SvxPrintItem* pItem = rTestSet.GetItemIfSet( RES_PRINT, 
false ) )
+        {
+            if( !pHasTextChangesOnly )
+                break;
+
+            pTestHasTextChangesOnly = pItem;
+        }
+        else
+        {
+            if( pHasTextChangesOnly )
+                continue;
+        }
+
         if( pVertOrient &&
             pVertOrient->GetVertOrient() != pTestVertOrient->GetVertOrient() )
             continue;
@@ -462,6 +478,9 @@ static OUString 
lcl_xmltble_appendBoxPrefix(std::u16string_view rNamePrefix,
         if( pAttCnt && ( *pAttCnt != *pTestAttCnt ) )
             continue;
 
+        if( pHasTextChangesOnly && (!pHasTextChangesOnly->GetValue() != 
!pTestHasTextChangesOnly->GetValue()) )
+            continue;
+
         // found!
         auto const oName(m_rFormatMap.find(pTestFormat)->second);
         assert(oName);

Reply via email to