sw/inc/bitmaps.hlst                         |    2 
 sw/qa/uitest/writer_tests/trackedChanges.py |   44 +++++++++
 sw/source/uibase/inc/redlndlg.hxx           |    3 
 sw/source/uibase/misc/redlndlg.cxx          |  128 +++++++++++++++++-----------
 4 files changed, 127 insertions(+), 50 deletions(-)

New commits:
commit 6d2376bedd833fde2ae4bbf9d9557c1af188c007
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Wed Jun 7 16:53:42 2023 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Mon Jun 12 09:17:29 2023 +0200

    tdf#155342 sw tracked table column: manage changes
    
    in Manage Changes dialog window, where deleted/inserted
    table columns were shown as multiple cell changes.
    Now deleted/inserted table columns are shown with a
    single tree item in the dialog window instead of
    showing multiple cell changes.
    
    Add new Action icons to the tracked table column
    insertion/deletion tree items (re-using table column
    deletion/insertion icons).
    
    Show cell changes as children of the single parent
    item tracked table column change.
    
    Accept/Reject and Accept/Reject All support
    1-click acceptance or rejection of table column changes,
    instead of clicking on all cell changes of a single
    table column deletion/insertion.
    
    Follow-up to commit commit eebe4747d2d13545004937bb0267ccfc8ab9d63f
    "tdf#144270 sw: manage tracked table (row) deletion/insertion" and
    commit ffd8d20d368a885d6d786749278fa438573227a7
    "tdf#150673 sw xmloff: import/export tracked table column".
    
    Change-Id: Ie9c9d8ef707ee2581cf6d0b066c10901555ca04c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152711
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 67298969d80e106fd9a3727ab5d5a75fd8afd48c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152815

diff --git a/sw/inc/bitmaps.hlst b/sw/inc/bitmaps.hlst
index 6582b691d371..3d1e322af006 100644
--- a/sw/inc/bitmaps.hlst
+++ b/sw/inc/bitmaps.hlst
@@ -30,6 +30,8 @@ inline constexpr OUStringLiteral BMP_REDLINE_MOVED_INSERTION 
= u"cmd/sc_paste.pn
 inline constexpr OUStringLiteral BMP_REDLINE_MOVED_DELETION = 
u"cmd/sc_cut.png";
 inline constexpr OUStringLiteral BMP_REDLINE_ROW_INSERTION = 
u"cmd/sc_insertrows.png";
 inline constexpr OUStringLiteral BMP_REDLINE_ROW_DELETION = 
u"cmd/sc_deleterows.png";
+inline constexpr OUStringLiteral BMP_REDLINE_COL_INSERTION = 
u"cmd/sc_insertcolumns.png";
+inline constexpr OUStringLiteral BMP_REDLINE_COL_DELETION = 
u"cmd/sc_deletecolumns.png";
 inline constexpr OUStringLiteral BMP_REDLINE_COMMENT_INSERTION = 
u"cmd/sc_insertannotation.png";
 inline constexpr OUStringLiteral BMP_REDLINE_COMMENT_DELETION = 
u"cmd/sc_deleteannotation.png";
 
diff --git a/sw/qa/uitest/writer_tests/trackedChanges.py 
b/sw/qa/uitest/writer_tests/trackedChanges.py
index a76cfe5dbe36..7e780ef61730 100644
--- a/sw/qa/uitest/writer_tests/trackedChanges.py
+++ b/sw/qa/uitest/writer_tests/trackedChanges.py
@@ -281,6 +281,9 @@ class trackedchanges(UITestCase):
                 # Now: 4 changes (2 deleted/inserted rows and 2 
deleted/inserted tables)
                 self.assertEqual(4, len(changesList.getChildren()))
 
+                # jump to the parent to allow rejecting the table change
+                changesList.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"LEFT"}))
+
                 # Without the fix in place, it would have crashed here
                 for i in (3, 2, 1, 0):
                     xAccBtn = xTrackDlg.getChild("reject")
@@ -500,4 +503,45 @@ class trackedchanges(UITestCase):
                     # of the text "inserts": "Document text inserts 
document"...
                     
self.assertTrue(document.getText().getString().startswith('Document text 
document text'))
 
+    def test_tdf155342_tracked_table_colums(self):
+        with 
self.ui_test.load_file(get_url_for_data_file("TC-table-del-add.docx")) as 
document:
+
+            # accept all changes and insert new columns with change tracking
+            self.xUITest.executeCommand(".uno:AcceptAllTrackedChanges")
+            tables = document.getTextTables()
+            self.assertEqual(2, len(tables))
+            self.assertEqual(len(tables[0].getColumns()), 3)
+            self.xUITest.executeCommand(".uno:InsertColumnsAfter")
+            self.xUITest.executeCommand(".uno:InsertColumnsAfter")
+            self.assertEqual(len(tables[0].getColumns()), 5)
+
+            xToolkit = 
self.xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit')
+            xToolkit.processEventsToIdle()
+
+            # check and reject changes
+            with 
self.ui_test.execute_modeless_dialog_through_command(".uno:AcceptTrackedChanges",
 close_button="close") as xTrackDlg:
+                changesList = xTrackDlg.getChild("writerchanges")
+
+                # six changes, but only one visible in the Manage Changes 
dialog window
+                state = get_state_as_dict(changesList)
+                self.assertEqual(state['Children'], '6')
+                self.assertEqual(state['VisibleCount'], '1')
+
+                # This was 6 (every cell is a different change instead of 
counting column changes)
+                # Now: 1 changes (2 inserted columns)
+                self.assertEqual(1, len(changesList.getChildren()))
+
+                # reject column insertion
+
+                xAccBtn = xTrackDlg.getChild("reject")
+                xAccBtn.executeAction("CLICK", tuple())
+
+                # all inserted columns are removed
+
+                self.assertEqual(len(tables[0].getColumns()), 3)
+
+                # no changes in the dialog window
+
+                self.assertEqual(0, len(changesList.getChildren()))
+
 # vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/uibase/inc/redlndlg.hxx 
b/sw/source/uibase/inc/redlndlg.hxx
index 36be9513a932..7337f1fadce4 100644
--- a/sw/source/uibase/inc/redlndlg.hxx
+++ b/sw/source/uibase/inc/redlndlg.hxx
@@ -97,7 +97,8 @@ class SW_DLLPUBLIC SwRedlineAcceptDlg final
     SAL_DLLPRIVATE void          RemoveParents(SwRedlineTable::size_type 
nStart, SwRedlineTable::size_type nEnd);
     SAL_DLLPRIVATE void          InitAuthors();
 
-    SAL_DLLPRIVATE static OUString GetActionImage(const SwRangeRedline& 
rRedln, sal_uInt16 nStack = 0, bool bRowChanges = false);
+    SAL_DLLPRIVATE static OUString GetActionImage(const SwRangeRedline& 
rRedln, sal_uInt16 nStack = 0,
+                                                  bool bTableChanges = false, 
bool bRowChanges = false);
     SAL_DLLPRIVATE OUString      GetActionText(const SwRangeRedline& rRedln, 
sal_uInt16 nStack = 0);
     SAL_DLLPRIVATE SwRedlineTable::size_type GetRedlinePos(const 
weld::TreeIter& rEntry);
 
diff --git a/sw/source/uibase/misc/redlndlg.cxx 
b/sw/source/uibase/misc/redlndlg.cxx
index 19374e5187a2..e583dc3af1a9 100644
--- a/sw/source/uibase/misc/redlndlg.cxx
+++ b/sw/source/uibase/misc/redlndlg.cxx
@@ -312,19 +312,24 @@ void SwRedlineAcceptDlg::InitAuthors()
                                 m_bOnlyFormatedRedlines );
 }
 
-OUString SwRedlineAcceptDlg::GetActionImage(const SwRangeRedline& rRedln, 
sal_uInt16 nStack, bool bRowChanges)
+OUString SwRedlineAcceptDlg::GetActionImage(const SwRangeRedline& rRedln, 
sal_uInt16 nStack,
+                                            bool bTableChanges, bool 
bRowChanges)
 {
     switch (rRedln.GetType(nStack))
     {
-        case RedlineType::Insert:  return bRowChanges
-            ? OUString(BMP_REDLINE_ROW_INSERTION)
+        case RedlineType::Insert:  return bTableChanges
+            ? bRowChanges
+                ? OUString(BMP_REDLINE_ROW_INSERTION)
+                : OUString(BMP_REDLINE_COL_INSERTION)
             : rRedln.IsMoved()
                 ? OUString(BMP_REDLINE_MOVED_INSERTION)
                 : rRedln.IsAnnotation()
                     ? OUString(BMP_REDLINE_COMMENT_INSERTION)
                     : OUString(BMP_REDLINE_INSERTED);
-        case RedlineType::Delete:  return bRowChanges
-            ? OUString(BMP_REDLINE_ROW_DELETION)
+        case RedlineType::Delete:  return bTableChanges
+            ? bRowChanges
+                 ? OUString(BMP_REDLINE_ROW_DELETION)
+                 : OUString(BMP_REDLINE_COL_DELETION)
             : rRedln.IsMoved()
                 ? OUString(BMP_REDLINE_MOVED_DELETION)
                 : rRedln.IsAnnotation()
@@ -790,25 +795,23 @@ void 
SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedli
 
     bool bIsShowChangesInMargin = 
SW_MOD()->GetUsrPref(false)->IsShowChangesInMargin();
 
-    // collect redlines of tracked table or table row insertion/deletions 
under a single tree list
-    // item to accept/reject table (row) insertion/deletion with a single 
click on Accept/Reject
+    // collect redlines of tracked table/row/column insertion/deletions under 
a single tree list
+    // item to accept/reject the table change with a single click on 
Accept/Reject
     // Note: because update of the tree list depends on parent count, we don't 
modify
     // m_RedlineParents, only store the 2nd and more redlines as children of 
the tree list
     // item of the first redline
 
     // count of items stored as children (to adjust parent position)
-    sal_Int32 nSkipRedlines = 0;
-    // count of items of the actual table row (or joined table rows) stored as 
children =
-    // redlines of the row(s) - 1 (first redline is associated to the parent 
tree list item)
-    sal_Int32 nSkipRedline = 0;
-    // nSkipRedline of the previous table row (to join multiple table rows, if 
it's possible)
-    sal_Int32 nPrevSkipRedline = 0;
-
-    // last SwRangeRedline in the table row
+    SwRedlineTable::size_type nSkipRedlines = 0;
+    // count of items of the actual table change stored as children =
+    // redlines of the change - 1 (first redline is associated to the parent 
tree list item)
+    SwRedlineTable::size_type nSkipRedline = 0;
+
+    // last SwRangeRedline in the table row/column
     SwRedlineTable::size_type nLastChangeInRow = SwRedlineTable::npos;
-    // descriptor redline of the tracked table row
-    SwRedlineTable::size_type nRowChange = SwRedlineTable::npos;
-    // descriptor redline of the previous table row to join the table rows
+    // descriptor redline of the tracked table row/column
+    SwRedlineTable::size_type nRowChange = 0;
+    // descriptor redline of the previous table change to join with the next 
one
     SwRedlineTable::size_type nPrevRowChange = SwRedlineTable::npos;
 
     // show all redlines as tree list items,
@@ -825,42 +828,69 @@ void 
SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedli
         // handle tracked table row changes
         const SwTableBox* pTableBox;
         const SwTableLine* pTableLine;
-        // first SwRangeRedline of the tracked table row(s), base of the 
parent tree list
-        // of the other SwRangeRedlines of the tracked table row(s)
+        bool bChange = false;
+        bool bRowChange = false;
+        // first SwRangeRedline of the tracked table rows/columns, base of the 
parent tree list
+        // of the other SwRangeRedlines of the tracked table rows or columns
         SwRedlineTable::size_type nNewTableParent = SwRedlineTable::npos;
         if ( // not recognized yet as tracked table row change
-             nLastChangeInRow == SwRedlineTable::npos &&
              nullptr != ( pTableBox = 
pSh->GetRedline(i).Start()->GetNode().GetTableBox() ) &&
              nullptr != ( pTableLine = pTableBox->GetUpper() ) &&
-             // it's a tracked row change based on the cached row data
-             RedlineType::None != pTableLine->GetRedlineType() )
+             // it's a tracked row (or column change) based on the cached row 
data
+             ( RedlineType::None != pTableLine->GetRedlineType() ||
+               RedlineType::None != pTableBox->GetRedlineType() ) )
         {
-            SwRedlineTable::size_type nRedline = i;
-            nRowChange = pTableLine->UpdateTextChangesOnly(nRedline);
+            // start redline search from the start from the tracked row/column 
change
+            SwRedlineTable::size_type nStartPos =
+                                        nRowChange > nSkipRedline ? nRowChange 
- nSkipRedline : 0;
+            bChange = true;
+            bRowChange = RedlineType::None != pTableLine->GetRedlineType();
+            nRowChange = bRowChange
+                            ? pTableLine->UpdateTextChangesOnly(nStartPos)
+                            : pTableBox->GetRedline();
             if ( SwRedlineTable::npos != nRowChange )
             {
-                nSkipRedline = nRedline - i - 1;
-                nLastChangeInRow = nRedline - 1;
-                // join the consecutive deleted/inserted rows under a single 
treebox item,
+                // redline is there in a tracked table change
+
+                // join the consecutive deleted/inserted rows/columns under a 
single treebox item,
                 // if they have the same redline data (equal type, author and 
time stamp)
-                if ( nPrevRowChange != SwRedlineTable::npos &&
-                    pSh->GetRedline(nRowChange).GetRedlineData() == 
pSh->GetRedline(nPrevRowChange).GetRedlineData() )
+                if ( nPrevRowChange != SwRedlineTable::npos )
                 {
-                    nSkipRedline += nPrevSkipRedline + 1;
-                    nPrevSkipRedline = 0;
-                    nPrevRowChange = SwRedlineTable::npos;
+                    // note: CanCombine() allows a time frame to join the 
changes within a short
+                    // time period: this avoid of falling apart of the tracked 
columns inserted
+                    // by several clicks
+                    if ( pSh->GetRedline(nRowChange).GetRedlineData()
+                             
.CanCombine(pSh->GetRedline(nPrevRowChange).GetRedlineData()) &&
+                         // in the same table?
+                         
pSh->GetRedline(nRowChange).Start()->GetNode().FindTableNode() ==
+                             
pSh->GetRedline(nPrevRowChange).Start()->GetNode().FindTableNode() )
+                    {
+                        nSkipRedline++;
+                    }
+                    else
+                    {
+                        nNewTableParent = i;
+                        nLastChangeInRow = i;
+                        nPrevRowChange = nRowChange;
+                    }
                 }
                 else
+                {
+                    nLastChangeInRow = i;
                     nNewTableParent = i;
+                }
             }
             else
+            {
+                // redline is not in a tracked table change
+                bChange = bRowChange = false;
                 nPrevRowChange = SwRedlineTable::npos;
+            }
         }
         else
+            // redline is not in a tracked table change
             nPrevRowChange = SwRedlineTable::npos;
 
-        bool bRowChange(SwRedlineTable::npos != nLastChangeInRow);
-
         bool bShowDeletedTextAsComment = bIsShowChangesInMargin &&
                 RedlineType::Delete == rRedln.GetType() && 
rRedln.GetComment().isEmpty();
         const OUString& sComment = bShowDeletedTextAsComment
@@ -876,9 +906,9 @@ void 
SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedli
 
         // use descriptor SwRangeRedline of the changed row, if needed to show
         // the correct redline type, author and time stamp of the tracked row 
change
-        const SwRangeRedline& rChangeRedln = pSh->GetRedline(bRowChange ? 
nRowChange : i);
+        const SwRangeRedline& rChangeRedln = pSh->GetRedline(bChange ? 
nRowChange : i);
 
-        OUString sImage = GetActionImage(rChangeRedln, 0, bRowChange && 
nNewTableParent != SwRedlineTable::npos );
+        OUString sImage = GetActionImage(rChangeRedln, 0, bChange && 
nNewTableParent != SwRedlineTable::npos, bRowChange );
         OUString sAuthor = rChangeRedln.GetAuthorString(0);
         pData->aDateTime = rChangeRedln.GetTimeStamp(0);
         pData->eType = rChangeRedln.GetType(0);
@@ -887,12 +917,20 @@ void 
SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedli
         OUString sId = weld::toId(pData.get());
         std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator());
 
-        if ( !bRowChange || nNewTableParent != SwRedlineTable::npos )
+        if ( !bChange || nNewTableParent != SwRedlineTable::npos )
+        {
             rTreeView.insert(nullptr, i - nSkipRedlines, nullptr, &sId, 
nullptr, nullptr, false, xParent.get());
+            // before this was a tracked table change with more than a single 
redline
+            if ( nSkipRedline > 0 )
+            {
+                nSkipRedlines += nSkipRedline;
+                nSkipRedline = 0;
+            }
+        }
         else
         {
             // put 2nd or more redlines of deleted/inserted rows as children 
of their first redline
-            SwRedlineDataParent *const pParent = 
m_RedlineParents[nLastChangeInRow - nSkipRedline].get();
+            SwRedlineDataParent *const pParent = 
m_RedlineParents[nLastChangeInRow].get();
             rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, 
nullptr, nullptr, false, xParent.get());
         }
 
@@ -916,16 +954,8 @@ void 
SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedli
 
         InsertChildren(pRedlineParent, rRedln, bHasRedlineAutoFormat);
 
-        // end of a tracked deletion/insertion of a table row
-        if ( nLastChangeInRow != SwRedlineTable::npos && i == nLastChangeInRow 
)
-        {
-            nSkipRedlines += nSkipRedline;
-            nPrevSkipRedline = nSkipRedline;
-            nSkipRedline = 0;
-            nPrevRowChange = nRowChange;
-            nNewTableParent = SwRedlineTable::npos;
-            nLastChangeInRow = SwRedlineTable::npos;
-        }
+        nPrevRowChange = nRowChange;
+        nNewTableParent = SwRedlineTable::npos;
     }
     rTreeView.thaw();
     if (m_pTable->IsSorted())

Reply via email to