sw/inc/doc.hxx                       |    2 
 sw/inc/swtable.hxx                   |    4 -
 sw/qa/extras/uiwriter/uiwriter6.cxx  |   82 +++++++++++++++++++++++++++++++++++
 sw/source/core/doc/tblrwcl.cxx       |    5 +-
 sw/source/core/docnode/ndtbl.cxx     |    4 -
 sw/source/core/frmedt/fetab.cxx      |    5 +-
 sw/source/core/table/swnewtable.cxx  |   12 +++--
 sw/source/uibase/dochdl/swdtflvr.cxx |    6 +-
 8 files changed, 105 insertions(+), 15 deletions(-)

New commits:
commit c35828816f6fd9eff6e0d4f0f50b5312090b012e
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Wed Sep 27 22:10:15 2023 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri Sep 29 09:03:35 2023 +0200

    tdf#155846 sw tracked table column: fix drag & drop
    
    Selecting table columns by the top border, and
    moving them via drag & drop resulted only tracked
    deletion, but not tracked insertion.
    
    See also commit 912336f3c85d9a631fa0ac0f270bab04b204f619
    "tdf#154599 sw: fix crash at drag & drop table columns".
    
    Change-Id: Ib392f0700ec8c17a342df435c8bb1883967b0711
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157370
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 1d94699594f7515aa82bdeeb537eb89849f84de3)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157320
    Tested-by: László Németh <nem...@numbertext.org>

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 335ccff90317..86fd5a67c8ca 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1204,7 +1204,7 @@ public:
     void InsertCol( const SwCursor& rCursor,
                     sal_uInt16 nCnt = 1, bool bBehind = true );
     bool InsertCol( const SwSelBoxes& rBoxes,
-                    sal_uInt16 nCnt = 1, bool bBehind = true );
+                    sal_uInt16 nCnt = 1, bool bBehind = true, bool 
bInsertDummy = true );
     void InsertRow( const SwCursor& rCursor,
                     sal_uInt16 nCnt = 1, bool bBehind = true );
     bool InsertRow( const SwSelBoxes& rBoxes,
diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index e8b4ad35602f..a7d1bd87d4d4 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -168,7 +168,7 @@ private:
     std::optional<SwBoxSelection> CollectBoxSelection( const SwPaM& rPam ) 
const;
     void InsertSpannedRow( SwDoc& rDoc, sal_uInt16 nIdx, sal_uInt16 nCnt );
     bool InsertRow_( SwDoc*, const SwSelBoxes&, sal_uInt16 nCnt, bool bBehind 
);
-    bool NewInsertCol( SwDoc&, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool 
);
+    bool NewInsertCol( SwDoc&, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, 
bool, bool bInsertDummy );
     void FindSuperfluousRows_( SwSelBoxes& rBoxes, SwTableLine*, SwTableLine* 
);
     void AdjustWidths( const tools::Long nOld, const tools::Long nNew );
     void NewSetTabCols( Parm &rP, const SwTabCols &rNew, const SwTabCols &rOld,
@@ -252,7 +252,7 @@ public:
     void PrepareDeleteCol( tools::Long nMin, tools::Long nMax );
 
     bool InsertCol( SwDoc&, const SwSelBoxes& rBoxes,
-                    sal_uInt16 nCnt, bool bBehind );
+                    sal_uInt16 nCnt, bool bBehind, bool bInsertDummy );
     bool InsertRow( SwDoc*, const SwSelBoxes& rBoxes,
                     sal_uInt16 nCnt, bool bBehind );
     void PrepareDelBoxes( const SwSelBoxes& rBoxes );
diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx 
b/sw/qa/extras/uiwriter/uiwriter6.cxx
index 3c7f616a5be3..716b995ec5ac 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -979,6 +979,88 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, 
testTdf154599_MovingColumn)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1->getColumns()->getCount());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf155846_MovingColumn)
+{
+    createSwDoc();
+    SwDoc* pDoc = getSwDoc();
+    CPPUNIT_ASSERT(pDoc);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+
+    // Create a table
+    SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+    (void)&pWrtShell->InsertTable(TableOpt, 4, 3);
+
+    uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    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());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1->getColumns()->getCount());
+
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+
+    // fill table with data
+    for (int i = 0; i < 4; ++i)
+    {
+        pWrtShell->Insert("x");
+        pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN);
+    }
+
+    Scheduler::ProcessEventsToIdle();
+
+    uno::Reference<text::XTextRange> xCellA1(xTable1->getCellByName("A1"), 
uno::UNO_QUERY);
+    xCellA1->setString("A1");
+    uno::Reference<text::XTextRange> xCellA2(xTable1->getCellByName("A2"), 
uno::UNO_QUERY);
+    xCellA2->setString("A2");
+    uno::Reference<text::XTextRange> xCellA3(xTable1->getCellByName("A3"), 
uno::UNO_QUERY);
+    xCellA3->setString("A3");
+    uno::Reference<text::XTextRange> xCellA4(xTable1->getCellByName("A4"), 
uno::UNO_QUERY);
+    xCellA4->setString("A4");
+
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    assertXPathContent(pXmlDoc, "/root/page/body/tab/row[1]/cell[1]/txt", 
"A1");
+    assertXPathContent(pXmlDoc, "/root/page/body/tab/row[2]/cell[1]/txt", 
"A2");
+    assertXPathContent(pXmlDoc, "/root/page/body/tab/row[3]/cell[1]/txt", 
"A3");
+    assertXPathContent(pXmlDoc, "/root/page/body/tab/row[4]/cell[1]/txt", 
"A4");
+
+    // enable redlining
+    dispatchCommand(mxComponent, ".uno:TrackChanges", {});
+    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
+                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+
+    // Move first column of the table before the third column by drag & drop
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    SwFrame* pPage = pLayout->Lower();
+    SwFrame* pBody = pPage->GetLower();
+    SwFrame* pTable = pBody->GetLower();
+    SwFrame* pRow1 = pTable->GetLower();
+    SwFrame* pCellA1 = pRow1->GetLower();
+    SwFrame* pCellC1 = pCellA1->GetNext()->GetNext();
+    const SwRect& rCellA1Rect = pCellA1->getFrameArea();
+    const SwRect& rCellC1Rect = pCellC1->getFrameArea();
+    Point ptTo(rCellC1Rect.Left() + rCellC1Rect.Width() / 2,
+               rCellC1Rect.Top() + rCellC1Rect.Height() / 2);
+    // select first table column by using the middle point of the top border 
of column A
+    Point ptColumn(rCellA1Rect.Left() + rCellA1Rect.Width() / 2, 
rCellA1Rect.Top() - 5);
+    pWrtShell->SelectTableRowCol(ptColumn);
+
+    // This crashed here before the fix.
+    rtl::Reference<SwTransferable> xTransfer = new SwTransferable(*pWrtShell);
+
+    xTransfer->PrivateDrop(*pWrtShell, ptTo, /*bMove=*/true, 
/*bXSelection=*/true);
+
+    // reject changes results 3 columns again, not 4
+    dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
+
+    xTableNames = xTablesSupplier->getTextTables();
+    CPPUNIT_ASSERT(xTableNames->hasByName("Table1"));
+    uno::Reference<text::XTextTable> xTable2(xTableNames->getByName("Table1"), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable2->getRows()->getCount());
+    // This was 4 (moving column without change tracking)
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2->getColumns()->getCount());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf154771_MovingMultipleColumns)
 {
     createSwDoc();
diff --git a/sw/source/core/doc/tblrwcl.cxx b/sw/source/core/doc/tblrwcl.cxx
index addf5ec8d41c..c12efb06b7a0 100644
--- a/sw/source/core/doc/tblrwcl.cxx
+++ b/sw/source/core/doc/tblrwcl.cxx
@@ -452,7 +452,8 @@ static SwRowFrame* GetRowFrame( SwTableLine& rLine )
     return nullptr;
 }
 
-bool SwTable::InsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 
nCnt, bool bBehind )
+bool SwTable::InsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 
nCnt,
+    bool bBehind, bool bInsertDummy )
 {
     OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid Box List" );
     SwTableNode* pTableNd = 
const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
@@ -461,7 +462,7 @@ bool SwTable::InsertCol( SwDoc& rDoc, const SwSelBoxes& 
rBoxes, sal_uInt16 nCnt,
 
     bool bRes = true;
     if( IsNewModel() )
-        bRes = NewInsertCol( rDoc, rBoxes, nCnt, bBehind );
+        bRes = NewInsertCol( rDoc, rBoxes, nCnt, bBehind, bInsertDummy );
     else
     {
         // Find all Boxes/Lines
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 0b625fb3651c..a4158813e916 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -1705,7 +1705,7 @@ void SwDoc::InsertCol( const SwCursor& rCursor, 
sal_uInt16 nCnt, bool bBehind )
         InsertCol( aBoxes, nCnt, bBehind );
 }
 
-bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind 
)
+bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool 
bBehind, bool bInsertDummy )
 {
     OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
     SwTableNode* pTableNd = 
const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
@@ -1730,7 +1730,7 @@ bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, 
sal_uInt16 nCnt, bool bBehind )
         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
 
         rTable.SwitchFormulasToInternalRepresentation();
-        bRet = rTable.InsertCol(*this, rBoxes, nCnt, bBehind);
+        bRet = rTable.InsertCol(*this, rBoxes, nCnt, bBehind, bInsertDummy);
         if (bRet)
         {
             getIDocumentState().SetModified();
diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx
index 59b031ce772a..b53d6666c8ea 100644
--- a/sw/source/core/frmedt/fetab.cxx
+++ b/sw/source/core/frmedt/fetab.cxx
@@ -233,6 +233,9 @@ void SwFEShell::InsertCol( sal_uInt16 nCnt, bool bBehind )
         return;
     }
 
+    // pending drag & drop?
+    bool bAction = ActionPend();
+
     StartAllAction();
     // search boxes via the layout
     SwSelBoxes aBoxes;
@@ -241,7 +244,7 @@ void SwFEShell::InsertCol( sal_uInt16 nCnt, bool bBehind )
     TableWait aWait( nCnt, pFrame, *GetDoc()->GetDocShell(), aBoxes.size() );
 
     if( !aBoxes.empty() )
-        GetDoc()->InsertCol( aBoxes, nCnt, bBehind );
+        GetDoc()->InsertCol( aBoxes, nCnt, bBehind, /*bInsertDummy=*/!bAction 
);
 
     EndAllActionAndCall();
 }
diff --git a/sw/source/core/table/swnewtable.cxx 
b/sw/source/core/table/swnewtable.cxx
index 6debaf7fa577..70765843388c 100644
--- a/sw/source/core/table/swnewtable.cxx
+++ b/sw/source/core/table/swnewtable.cxx
@@ -653,7 +653,7 @@ insertion behind (true) or before (false) the selected boxes
 */
 
 bool SwTable::NewInsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes,
-    sal_uInt16 nCnt, bool bBehind )
+    sal_uInt16 nCnt, bool bBehind, bool bInsertDummy )
 {
     if( m_aLines.empty() || !nCnt )
         return false;
@@ -749,14 +749,18 @@ bool SwTable::NewInsertCol( SwDoc& rDoc, const 
SwSelBoxes& rBoxes,
             SwTableBox *pCurrBox = pLine->GetTabBoxes()[nInsPos+j];
 
             // set tracked insertion by inserting a dummy redline
+            // drag & drop: no need to insert dummy character
             if ( rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
             {
                 SwPosition aPos(*pCurrBox->GetSttNd());
                 SwCursor aCursor( aPos, nullptr );
-                SwNodeIndex aInsDummyPos(*pCurrBox->GetSttNd(), 1 );
-                SwPaM aPaM(aInsDummyPos);
-                rDoc.getIDocumentContentOperations().InsertString( aPaM,
+                if ( bInsertDummy )
+                {
+                    SwNodeIndex aInsDummyPos(*pCurrBox->GetSttNd(), 1 );
+                    SwPaM aPaM(aInsDummyPos);
+                    rDoc.getIDocumentContentOperations().InsertString( aPaM,
                         OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
+                }
                 SvxPrintItem aHasTextChangesOnly(RES_PRINT, false);
                 rDoc.SetBoxAttr( aCursor, aHasTextChangesOnly );
             }
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx 
b/sw/source/uibase/dochdl/swdtflvr.cxx
index 201b7fa1b5d2..9e0440a71f17 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -1635,7 +1635,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, 
TransferableDataHelper& rData, RndSt
             // (without setting the rows to tracked table row insertion here, 
do that at the end
             // to avoid layout problems and unnecessary insertion of dummy 
characters for empty rows)
             RedlineFlags eOld = 
rSh.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
-            if ( eOld & RedlineFlags::On )
+            if ( eOld & RedlineFlags::On && bRowMode )
                 rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( 
eOld | RedlineFlags::Ignore );
 
             const sal_uInt16 nDispatchSlot = bRowMode ? 
FN_TABLE_INSERT_ROW_BEFORE : FN_TABLE_INSERT_COL_BEFORE;
@@ -1652,7 +1652,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, 
TransferableDataHelper& rData, RndSt
                     { &aCountItem, &aAfter });
             }
 
-            if ( eOld & RedlineFlags::On )
+            if ( eOld & RedlineFlags::On && bRowMode )
                 rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( 
eOld );
 
             // paste rows
@@ -1660,7 +1660,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, 
TransferableDataHelper& rData, RndSt
                                         nDestination, false, false, nullptr, 
0, false, nAnchorType, bIgnoreComments, &aPasteContext );
 
             // set tracked insertion, if it's not in a drag & drop action
-            if ( !rSh.ActionPend() && ( eOld & RedlineFlags::On) )
+            if ( !rSh.ActionPend() && ( eOld & RedlineFlags::On) && bRowMode )
             {
                 SvxPrintItem aTracked(RES_PRINT, false);
                 rSh.GetDoc()->SetRowNotTracked( *rSh.GetCursor(), aTracked );

Reply via email to