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 );