sw/inc/doc.hxx | 2 sw/inc/swtable.hxx | 4 - sw/qa/extras/uiwriter/uiwriter6.cxx | 79 +++++++++++++++++++++++++++++++++++ sw/source/core/doc/tblrwcl.cxx | 9 ++- sw/source/core/docnode/ndtbl.cxx | 4 - sw/source/core/frmedt/fetab.cxx | 5 +- sw/source/core/table/swnewtable.cxx | 8 +-- sw/source/uibase/dochdl/swdtflvr.cxx | 16 ------- 8 files changed, 98 insertions(+), 29 deletions(-)
New commits: commit 2886d09892220058d34112968d4788bc3acc08da Author: László Németh <nem...@numbertext.org> AuthorDate: Thu Sep 28 17:32:24 2023 +0200 Commit: László Németh <nem...@numbertext.org> CommitDate: Fri Sep 29 09:03:58 2023 +0200 tdf#157492 sw: fix tracked drag & drop of table row Selecting table rows by the left row border, and moving them via drag & drop resulted only tracked deletion, but not tracked insertion. See also commit 3e6125c72f8c07c14df42d45571cab44f24e9f70 "tdf#155846 sw tracked table column: fix drag & drop". This reverts also commit 5a1c19624eda0c8b847af0dcee70b82502578ceb "tdf#146965 sw track changes: fix tracked table row moving". Change-Id: I7287e46188eee123b5fd36a5ec7ac5311699840b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157382 Tested-by: László Németh <nem...@numbertext.org> Reviewed-by: László Németh <nem...@numbertext.org> (cherry picked from commit 65efbf64cfa30ba96bc9f0ba539eb1414b861c49) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157323 Tested-by: Jenkins diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 86fd5a67c8ca..04e12b2a4967 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -1208,7 +1208,7 @@ public: void InsertRow( const SwCursor& rCursor, sal_uInt16 nCnt = 1, bool bBehind = true ); bool InsertRow( const SwSelBoxes& rBoxes, - sal_uInt16 nCnt = 1, bool bBehind = true ); + sal_uInt16 nCnt = 1, bool bBehind = true, bool bInsertDummy = true ); // Delete Columns/Rows in table. enum class RowColMode { DeleteRow = 0, DeleteColumn = 1, DeleteProtected = 2 }; diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx index a7d1bd87d4d4..3d0a5732d188 100644 --- a/sw/inc/swtable.hxx +++ b/sw/inc/swtable.hxx @@ -167,7 +167,7 @@ private: bool NewSplitRow( SwDoc&, const SwSelBoxes&, sal_uInt16, bool ); 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 InsertRow_( SwDoc*, const SwSelBoxes&, sal_uInt16 nCnt, bool bBehind, bool bInsertDummy ); 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 ); @@ -254,7 +254,7 @@ public: bool InsertCol( SwDoc&, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind, bool bInsertDummy ); bool InsertRow( SwDoc*, const SwSelBoxes& rBoxes, - sal_uInt16 nCnt, bool bBehind ); + sal_uInt16 nCnt, bool bBehind, bool bInsertDummy = true ); void PrepareDelBoxes( const SwSelBoxes& rBoxes ); bool DeleteSel( SwDoc*, const SwSelBoxes& rBoxes, const SwSelBoxes* pMerged, SwUndo* pUndo, const bool bDelMakeFrames, const bool bCorrBorder ); diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx index 716b995ec5ac..73178363b8fb 100644 --- a/sw/qa/extras/uiwriter/uiwriter6.cxx +++ b/sw/qa/extras/uiwriter/uiwriter6.cxx @@ -930,6 +930,85 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf147181_TrackedMovingOfMultipleTable CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b->getRows()->getCount()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf157492_TrackedMovingRow) +{ + 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 < 3; ++i) + { + pWrtShell->Insert("x"); + pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RIGHT); + } + + Scheduler::ProcessEventsToIdle(); + + uno::Reference<text::XTextRange> xCellA1(xTable1->getCellByName("A1"), uno::UNO_QUERY); + xCellA1->setString("A1"); + uno::Reference<text::XTextRange> xCellB1(xTable1->getCellByName("B1"), uno::UNO_QUERY); + xCellB1->setString("B1"); + uno::Reference<text::XTextRange> xCellC1(xTable1->getCellByName("C1"), uno::UNO_QUERY); + xCellC1->setString("C1"); + + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPathContent(pXmlDoc, "/root/page/body/tab/row[1]/cell[1]/txt", "A1"); + assertXPathContent(pXmlDoc, "/root/page/body/tab/row[1]/cell[2]/txt", "B1"); + assertXPathContent(pXmlDoc, "/root/page/body/tab/row[1]/cell[3]/txt", "C1"); + + // 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* pRow3 = pRow1->GetNext()->GetNext(); + SwFrame* pCellA3 = pRow3->GetLower(); + const SwRect& rCellA1Rect = pCellA1->getFrameArea(); + const SwRect& rCellA3Rect = pCellA3->getFrameArea(); + Point ptTo(rCellA3Rect.Left() + rCellA3Rect.Width() / 2, + rCellA3Rect.Top() + rCellA3Rect.Height() / 2); + // select first table row by using the middle point of the left border of row 1 + Point ptRow(rCellA1Rect.Left() - 5, rCellA1Rect.Top() + rCellA1Rect.Height() / 2); + pWrtShell->SelectTableRowCol(ptRow); + + rtl::Reference<SwTransferable> xTransfer = new SwTransferable(*pWrtShell); + + xTransfer->PrivateDrop(*pWrtShell, ptTo, /*bMove=*/true, /*bXSelection=*/true); + + // reject changes results 4 rows again, not 5 + 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(3), xTable2->getColumns()->getCount()); + // This was 5 (moving row without change tracking) + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable2->getRows()->getCount()); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf154599_MovingColumn) { createSwDoc(); diff --git a/sw/source/core/doc/tblrwcl.cxx b/sw/source/core/doc/tblrwcl.cxx index c12efb06b7a0..2b5192804856 100644 --- a/sw/source/core/doc/tblrwcl.cxx +++ b/sw/source/core/doc/tblrwcl.cxx @@ -514,7 +514,7 @@ bool SwTable::InsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, } bool SwTable::InsertRow_( SwDoc* pDoc, const SwSelBoxes& rBoxes, - sal_uInt16 nCnt, bool bBehind ) + sal_uInt16 nCnt, bool bBehind, bool bInsertDummy ) { OSL_ENSURE( pDoc && !rBoxes.empty() && nCnt, "No valid Box List" ); SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode()); @@ -597,9 +597,12 @@ bool SwTable::InsertRow_( SwDoc* pDoc, const SwSelBoxes& rBoxes, SvxPrintItem aSetTracking(RES_PRINT, false); SwPosition aPos(*pNewTableLine->GetTabBoxes()[0]->GetSttNd()); SwCursor aCursor( aPos, nullptr ); - SwPaM aPaM(*pNewTableLine->GetTabBoxes()[0]->GetSttNd(), SwNodeOffset(1)); - pDoc->getIDocumentContentOperations().InsertString( aPaM, + if ( bInsertDummy ) + { + SwPaM aPaM(*pNewTableLine->GetTabBoxes()[0]->GetSttNd(), SwNodeOffset(1)); + pDoc->getIDocumentContentOperations().InsertString( aPaM, OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) ); + } pDoc->SetRowNotTracked( aCursor, aSetTracking, /*bAll=*/false, /*bIns=*/true ); } } diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx index a4158813e916..cec3e7df57c4 100644 --- a/sw/source/core/docnode/ndtbl.cxx +++ b/sw/source/core/docnode/ndtbl.cxx @@ -1757,7 +1757,7 @@ void SwDoc::InsertRow( const SwCursor& rCursor, sal_uInt16 nCnt, bool bBehind ) InsertRow( aBoxes, nCnt, bBehind ); } -bool SwDoc::InsertRow( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind ) +bool SwDoc::InsertRow( 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()); @@ -1782,7 +1782,7 @@ bool SwDoc::InsertRow( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind ) ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); rTable.SwitchFormulasToInternalRepresentation(); - bRet = rTable.InsertRow( this, rBoxes, nCnt, bBehind ); + bRet = rTable.InsertRow( 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 b53d6666c8ea..93e20fab036e 100644 --- a/sw/source/core/frmedt/fetab.cxx +++ b/sw/source/core/frmedt/fetab.cxx @@ -186,6 +186,9 @@ void SwFEShell::InsertRow( sal_uInt16 nCnt, bool bBehind ) return; } + // pending drag & drop? + bool bAction = ActionPend(); + CurrShell aCurr( this ); StartAllAction(); @@ -205,7 +208,7 @@ void SwFEShell::InsertRow( sal_uInt16 nCnt, bool bBehind ) TableWait aWait( nCnt, pFrame, *GetDoc()->GetDocShell(), aBoxes.size() ); if ( !aBoxes.empty() ) - GetDoc()->InsertRow( aBoxes, nCnt, bBehind ); + GetDoc()->InsertRow( aBoxes, nCnt, bBehind, /*bInsertDummy=*/!bAction ); EndAllActionAndCall(); } diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx index 70765843388c..4e1386f4e21a 100644 --- a/sw/source/core/table/swnewtable.cxx +++ b/sw/source/core/table/swnewtable.cxx @@ -1205,7 +1205,7 @@ void SwTable::InsertSpannedRow( SwDoc& rDoc, sal_uInt16 nRowIdx, sal_uInt16 nCnt aFSz.SetHeight( nNewHeight ); pFrameFormat->SetFormatAttr( aFSz ); } - InsertRow_( &rDoc, aBoxes, nCnt, true ); + InsertRow_( &rDoc, aBoxes, nCnt, true, true ); const size_t nBoxCount = rLine.GetTabBoxes().size(); for( sal_uInt16 n = 0; n < nCnt; ++n ) { @@ -1510,7 +1510,7 @@ bool SwTable::NewSplitRow( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCn */ bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, - sal_uInt16 nCnt, bool bBehind ) + sal_uInt16 nCnt, bool bBehind, bool bInsertDummy ) { bool bRet = false; if( IsNewModel() ) @@ -1527,7 +1527,7 @@ bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, SwTableLine *pLine = GetTabLines()[ nRowIdx ]; SwSelBoxes aLineBoxes; lcl_FillSelBoxes( aLineBoxes, *pLine ); - InsertRow_( pDoc, aLineBoxes, nCnt, bBehind ); + InsertRow_( pDoc, aLineBoxes, nCnt, bBehind, bInsertDummy ); const size_t nBoxCount = pLine->GetTabBoxes().size(); sal_uInt16 nOfs = bBehind ? 0 : 1; for( sal_uInt16 n = 0; n < nCnt; ++n ) @@ -1577,7 +1577,7 @@ bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, CHECK_TABLE( *this ) } else - bRet = InsertRow_( pDoc, rBoxes, nCnt, bBehind ); + bRet = InsertRow_( pDoc, rBoxes, nCnt, bBehind, bInsertDummy ); return bRet; } diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx index 9e0440a71f17..a885f28cf6ed 100644 --- a/sw/source/uibase/dochdl/swdtflvr.cxx +++ b/sw/source/uibase/dochdl/swdtflvr.cxx @@ -1632,12 +1632,6 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt IDocumentMarkAccess::MarkType::UNO_BOOKMARK ); // add a new empty row/column before the actual table row/column and go there - // (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 && bRowMode ) - rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld | RedlineFlags::Ignore ); - const sal_uInt16 nDispatchSlot = bRowMode ? FN_TABLE_INSERT_ROW_BEFORE : FN_TABLE_INSERT_COL_BEFORE; pDispatch->Execute(nDispatchSlot, SfxCallMode::SYNCHRON); pDispatch->Execute(bRowMode ? FN_LINE_UP : FN_CHAR_LEFT, SfxCallMode::SYNCHRON); @@ -1652,20 +1646,10 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt { &aCountItem, &aAfter }); } - if ( eOld & RedlineFlags::On && bRowMode ) - rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld ); - // paste rows bool bResult = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat, 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) && bRowMode ) - { - SvxPrintItem aTracked(RES_PRINT, false); - rSh.GetDoc()->SetRowNotTracked( *rSh.GetCursor(), aTracked ); - } - // restore cursor position if (pMark != nullptr) {