[Libreoffice-commits] core.git: Branch 'distro/nisz/libreoffice-7-1' - offapi/com sw/inc sw/qa sw/source

László Németh (via logerrit) logerrit at kemper.freedesktop.org
Thu Aug 19 12:51:10 UTC 2021


 offapi/com/sun/star/text/TextTableRow.idl     |    8 ++
 sw/inc/doc.hxx                                |    2 
 sw/inc/swtable.hxx                            |    2 
 sw/inc/unoprnms.hxx                           |    1 
 sw/qa/extras/uiwriter/uiwriter2.cxx           |   77 ++++++++++++++++++++++++++
 sw/source/core/bastyp/init.cxx                |    2 
 sw/source/core/doc/DocumentRedlineManager.cxx |   35 +++++++++++
 sw/source/core/docnode/ndtbl1.cxx             |   26 ++++++++
 sw/source/core/frmedt/fetab.cxx               |   30 ++++++++++
 sw/source/core/table/swtable.cxx              |   15 +++++
 sw/source/core/unocore/unomap.cxx             |    1 
 sw/source/filter/html/htmltab.cxx             |   17 -----
 12 files changed, 200 insertions(+), 16 deletions(-)

New commits:
commit c2a49aa52ec2706db2af1c80d25308e9270ba229
Author:     László Németh <nemeth at numbertext.org>
AuthorDate: Wed May 19 12:22:24 2021 +0200
Commit:     Gabor Kelemen <kelemen.gabor2 at nisz.hu>
CommitDate: Thu Aug 19 14:50:34 2021 +0200

    tdf#60382 sw offapi: add change tracking of table/row deletion
    
    This is a minimal extension of the text range based change
    tracking to record and apply table row and table deletions
    with full Undo/Redo support.
    
    Add property IsNotTracked to com::sun::star::text::TextTableRow.
    
    During recording of track changes, deletion of table rows wasn't
    recorded: the rows removed completely with their text content.
    Now the deletion deletes the cell content with change tracking,
    setting also IsNotTracked property of table rows to FALSE. If
    all tracked deletions were accepted in a row, and the result is
    an empty row, the row will be removed, if its IsNotTracked
    property is FALSE.
    
    Note: Deletion of empty lines isn't recorded (they are simply
    deleted). Hiding deleted rows hasn't been supported yet in
    the Hide Changes mode.
    
    OpenDocument supports only track changes of text ranges, but
    not changes of the table structure, e.g. deletion of table
    rows. For the native export it needs to extend ODF, and
    depending on this future extension, can be based also on
    SwExtraRedlineTable (which lacks of recording and Undo/Redo,
    but supports OOXML round-trip of tracked table changes).
    See also commit d688069023959ab97d14eb1dbfd5bf6ad3c1b160
    "Add support for 'Table Row Redlines' in SW core" and its
    follow-up commits.
    
    Change-Id: I2e3807cf8ae8212bd51c210ef1c20c85878d0da8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115804
    Tested-by: László Németh <nemeth at numbertext.org>
    Reviewed-by: László Németh <nemeth at numbertext.org>
    (cherry picked from commit 05366b8e6683363688de8708a3d88cf144c7a2bf)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120649
    Tested-by: Gabor Kelemen <kelemen.gabor2 at nisz.hu>
    Reviewed-by: Gabor Kelemen <kelemen.gabor2 at nisz.hu>

diff --git a/offapi/com/sun/star/text/TextTableRow.idl b/offapi/com/sun/star/text/TextTableRow.idl
index d640d1c06cce..77191c9f57d1 100644
--- a/offapi/com/sun/star/text/TextTableRow.idl
+++ b/offapi/com/sun/star/text/TextTableRow.idl
@@ -105,6 +105,14 @@ published service TextTableRow
         @since LibreOffice 6.1
      */
     [optional, property] com::sun::star::graphic::XGraphic BackGraphic;
+
+    /** If TRUE, the table row wasn't deleted or inserted with its tracked cell content
+
+        @since LibreOffice 7.2
+     */
+
+        [optional, property, maybevoid] boolean IsNotTracked;
+
 };
 
 
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 6d1fb3a00125..fed4d61f8cb9 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1485,6 +1485,8 @@ public:
     bool BalanceRowHeight( const SwCursor& rCursor, bool bTstOnly, const bool bOptimize );
     void SetRowBackground( const SwCursor& rCursor, const SvxBrushItem &rNew );
     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
+    void SetRowNotTracked( const SwCursor& rCursor, const SvxPrintItem &rNotTracked );
     void SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet );
     void SetTabLineStyle( const SwCursor& rCursor,
                           const Color* pColor, bool bSetLine,
diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index d47366da42d8..d097d9e587e2 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -445,6 +445,8 @@ public:
     void RemoveFromTable();
     const SwStartNode *GetSttNd() const { return m_pStartNode; }
     sal_uLong GetSttIdx() const;
+    // it doesn't contain box content
+    bool IsEmpty() const;
 
     // Search next/previous box with content.
     SwTableBox* FindNextBox( const SwTable&, const SwTableBox*,
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 5b3d6bd33408..61cee34745ac 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -735,6 +735,7 @@
 #define UNO_NAME_ITEMS "Items"
 #define UNO_NAME_SELITEM "SelectedItem"
 #define UNO_NAME_IS_SPLIT_ALLOWED "IsSplitAllowed"
+#define UNO_NAME_IS_NOT_TRACKED "IsNotTracked"
 #define UNO_NAME_CHAR_HIDDEN "CharHidden"
 #define UNO_NAME_IS_FOLLOWING_TEXT_FLOW "IsFollowingTextFlow"
 #define UNO_NAME_WIDTH_TYPE "WidthType"
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index c7f20c586327..a171c14c591c 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -3370,6 +3370,83 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf118311)
     assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineTableRowDeletion)
+{
+    // load a 1-row table, and delete the row with enabled change tracking:
+    // now the row is not deleted silently, but keeps the deleted cell contents,
+    // and only accepting all of them will result the deletion of the table row.
+    SwDoc* pDoc = createDoc("tdf118311.fodt");
+
+    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()));
+
+    // check table
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // delete table row with enabled change tracking
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+
+    // This was deleted without change tracking
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // accept the deletion of the content of the first cell
+
+    SwEditShell* const pEditShell(pDoc->GetEditShell());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
+    pEditShell->AcceptRedline(0);
+
+    // table row was still not deleted
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // accept last redline
+    pEditShell->AcceptRedline(0);
+
+    // table row (and the 1-row table) was deleted finally
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
+
+    // Undo, and delete the row without change tracking
+
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+
+    // table exists again
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // disable change tracking
+    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
+                                                      | RedlineFlags::ShowInsert);
+
+    CPPUNIT_ASSERT_MESSAGE("redlining should be off",
+                           !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+
+    // delete table row without change tracking
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+
+    // the table (row) was deleted
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf128335)
 {
     // Load the bugdoc, which has 3 textboxes.
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
index 1d59814cd810..e6775a11666c 100644
--- a/sw/source/core/bastyp/init.cxx
+++ b/sw/source/core/bastyp/init.cxx
@@ -206,6 +206,8 @@ sal_uInt16 const aTableSetRange[] = {
 
 sal_uInt16 const aTableLineSetRange[] = {
     RES_FILL_ORDER,     RES_FRM_SIZE,
+    // IsNotTracked
+    RES_PRINT,          RES_PRINT,
     RES_LR_SPACE,       RES_UL_SPACE,
     RES_BACKGROUND,     RES_SHADOW,
     RES_ROW_SPLIT,      RES_ROW_SPLIT,
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index 14d6b76c71f0..d7c3e1e1e545 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -37,6 +37,8 @@
 #include <authfld.hxx>
 #include <strings.hrc>
 #include <swmodule.hxx>
+#include <osl/diagnose.h>
+#include <editeng/prntitem.hxx>
 
 using namespace com::sun::star;
 
@@ -425,6 +427,36 @@ namespace
         return nullptr;
     }
 
+    // delete the empty tracked table row (i.e. if it's last tracked deletion was accepted)
+    void lcl_DeleteTrackedTableRow ( SwPosition* pPos )
+    {
+        if ( const SwTableBox* pBox = pPos->nNode.GetNode().GetTableBox() )
+        {
+            const SwTableLine* pLine = pBox->GetUpper();
+            const SvxPrintItem *pIsNoTrackedProp =
+                    pLine->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT);
+            // table row property "IsNotTracked" is set and its value is false
+            if ( pIsNoTrackedProp && !pIsNoTrackedProp->GetValue() )
+            {
+                bool bEmptyLine = true;
+                const SwTableBoxes & rBoxes = pLine->GetTabBoxes();
+                for (size_t nBox = 0; nBox < rBoxes.size(); ++nBox)
+                {
+                    if ( !rBoxes[nBox]->IsEmpty() )
+                    {
+                        bEmptyLine = false;
+                        break;
+                    }
+                }
+                if ( bEmptyLine )
+                {
+                    SwCursor aCursor( *pPos, nullptr );
+                    pPos->GetDoc().DeleteRow( aCursor );
+                }
+            }
+        }
+    }
+
     bool lcl_AcceptRedline( SwRedlineTable& rArr, SwRedlineTable::size_type& rPos,
                             bool bCallDelete,
                             const SwPosition* pSttRng = nullptr,
@@ -560,7 +592,10 @@ namespace
                     rDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld & ~RedlineFlags(RedlineFlags::On | RedlineFlags::Ignore));
 
                     if( pCSttNd && pCEndNd )
+                    {
                         rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
+                        lcl_DeleteTrackedTableRow( aPam.End() );
+                    }
                     else if (pCSttNd && !pCEndNd)
                         {
                             aPam.GetBound().nContent.Assign( nullptr, 0 );
diff --git a/sw/source/core/docnode/ndtbl1.cxx b/sw/source/core/docnode/ndtbl1.cxx
index 84ebb7dd8821..228b4cde0267 100644
--- a/sw/source/core/docnode/ndtbl1.cxx
+++ b/sw/source/core/docnode/ndtbl1.cxx
@@ -535,6 +535,32 @@ bool SwDoc::GetRowBackground( const SwCursor& rCursor, std::unique_ptr<SvxBrushI
     return bRet;
 }
 
+void SwDoc::SetRowNotTracked( const SwCursor& rCursor, const SvxPrintItem &rNew )
+{
+    SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+    if( !pTableNd )
+        return;
+
+    std::vector<SwTableLine*> aRowArr; // For Lines collecting
+    ::lcl_CollectLines( aRowArr, rCursor, true );
+
+    if( aRowArr.empty() )
+        return;
+
+    if (GetIDocumentUndoRedo().DoesUndo())
+    {
+        GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoAttrTable>(*pTableNd));
+    }
+
+    std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
+    aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) );
+
+    for( auto pLn : aRowArr )
+        ::lcl_ProcessRowAttr( aFormatCmp, pLn, rNew );
+
+    getIDocumentState().SetModified();
+}
+
 static void InsertCell( std::vector<SwCellFrame*>& rCellArr, SwCellFrame* pCellFrame )
 {
     if( rCellArr.end() == std::find( rCellArr.begin(), rCellArr.end(), pCellFrame ) )
diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx
index 97878a01e3ea..aaa4351b023c 100644
--- a/sw/source/core/frmedt/fetab.cxx
+++ b/sw/source/core/frmedt/fetab.cxx
@@ -31,7 +31,9 @@
 #include <fmtornt.hxx>
 #include <frmatr.hxx>
 #include <fesh.hxx>
+#include <wrtsh.hxx>
 #include <doc.hxx>
+#include <docsh.hxx>
 #include <IDocumentState.hxx>
 #include <IDocumentLayoutAccess.hxx>
 #include <cntfrm.hxx>
@@ -325,6 +327,34 @@ bool SwFEShell::DeleteRow(bool bCompleteTable)
     }
 
     CurrShell aCurr( this );
+
+    // tracked deletion: remove only textbox content,
+    // and set IsNoTracked table line property to false
+    if ( GetDoc()->GetDocShell()->IsChangeRecording() )
+    {
+        StartUndo(bCompleteTable ? SwUndoId::UI_TABLE_DELETE : SwUndoId::ROW_DELETE);
+        StartAllAction();
+
+        SvxPrintItem aNotTracked(RES_PRINT, false);
+        GetDoc()->SetRowNotTracked( *getShellCursor( false ), aNotTracked );
+
+        if ( SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(this) )
+            pWrtShell->SelectTableRow();
+
+        SwEditShell* pEditShell = GetDoc()->GetEditShell();
+        SwRedlineTable::size_type nPrev = pEditShell->GetRedlineCount();
+        pEditShell->Delete();
+
+        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 ( nPrev != pEditShell->GetRedlineCount() )
+            return true;
+    }
+
     StartAllAction();
 
     // search for boxes via the layout
diff --git a/sw/source/core/table/swtable.cxx b/sw/source/core/table/swtable.cxx
index 97e999b1e21f..a3b1b16d2781 100644
--- a/sw/source/core/table/swtable.cxx
+++ b/sw/source/core/table/swtable.cxx
@@ -1867,6 +1867,21 @@ sal_uLong SwTableBox::GetSttIdx() const
     return m_pStartNode ? m_pStartNode->GetIndex() : 0;
 }
 
+bool SwTableBox::IsEmpty() const
+{
+    const SwStartNode *pSttNd = GetSttNd();
+    if( pSttNd &&
+        pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex() )
+    {
+        const SwContentNode *pCNd =
+            pSttNd->GetNodes()[pSttNd->GetIndex()+1]->GetContentNode();
+        if( pCNd && !pCNd->Len() )
+            return true;
+    }
+
+    return false;
+}
+
     // retrieve information from the client
 bool SwTable::GetInfo( SfxPoolItem& rInfo ) const
 {
diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx
index fc8d3713c4a2..a1282519d47e 100644
--- a/sw/source/core/unocore/unomap.cxx
+++ b/sw/source/core/unocore/unomap.cxx
@@ -543,6 +543,7 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetPropertyMapEntries(s
                     { u"" UNO_NAME_SIZE_TYPE, RES_FRM_SIZE,           cppu::UnoType<sal_Int16>::get()  ,         PROPERTY_NONE,   MID_FRMSIZE_SIZE_TYPE  },
                     { u"" UNO_NAME_WIDTH_TYPE, RES_FRM_SIZE,          cppu::UnoType<sal_Int16>::get()  ,         PROPERTY_NONE,   MID_FRMSIZE_WIDTH_TYPE },
                     { u"" UNO_NAME_IS_SPLIT_ALLOWED, RES_ROW_SPLIT,       cppu::UnoType<bool>::get()  , PropertyAttribute::MAYBEVOID, 0},
+                    { u"" UNO_NAME_IS_NOT_TRACKED, RES_PRINT, cppu::UnoType<bool>::get()  , PropertyAttribute::MAYBEVOID, 0},
                     { u"" UNO_NAME_ROW_INTEROP_GRAB_BAG, RES_FRMATR_GRABBAG, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), PROPERTY_NONE, 0 },
                     { u"", 0, css::uno::Type(), 0, 0 }
                 };
diff --git a/sw/source/filter/html/htmltab.cxx b/sw/source/filter/html/htmltab.cxx
index 4326e66cc029..0820dfe1e484 100644
--- a/sw/source/filter/html/htmltab.cxx
+++ b/sw/source/filter/html/htmltab.cxx
@@ -1226,21 +1226,6 @@ const SwStartNode* HTMLTable::GetPrevBoxStartNode( sal_uInt16 nRow, sal_uInt16 n
     return pTable->GetPrevBoxStartNode(USHRT_MAX, USHRT_MAX);
 }
 
-static bool IsBoxEmpty( const SwTableBox *pBox )
-{
-    const SwStartNode *pSttNd = pBox->GetSttNd();
-    if( pSttNd &&
-        pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex() )
-    {
-        const SwContentNode *pCNd =
-            pSttNd->GetNodes()[pSttNd->GetIndex()+1]->GetContentNode();
-        if( pCNd && !pCNd->Len() )
-            return true;
-    }
-
-    return false;
-}
-
 sal_uInt16 HTMLTable::GetTopCellSpace( sal_uInt16 nRow ) const
 {
     sal_uInt16 nSpace = m_nCellPadding;
@@ -1413,7 +1398,7 @@ void HTMLTable::FixFrameFormat( SwTableBox *pBox,
                 pFrameFormat->ResetFormatAttr( RES_BACKGROUND );
 
             // Only set format if there's a value or the box is empty
-            if( bHasNumFormat && (bHasValue || IsBoxEmpty(pBox)) )
+            if( bHasNumFormat && (bHasValue || pBox->IsEmpty()) )
             {
                 bool bLock = pFrameFormat->GetDoc()->GetNumberFormatter()
                                      ->IsTextFormat( nNumFormat );


More information about the Libreoffice-commits mailing list