summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2023-04-12 13:27:25 +0200
committerLászló Németh <nemeth@numbertext.org>2023-04-12 19:08:06 +0200
commit1bf651f34b1e3abb5cbaf6b810aa0b0d9ee86368 (patch)
treecdabe9e08f6fa6fcf6d09890c46a341babd73b07
parenttdf#153923: In ReqIF case, avoid fake dl/dd used to emulate indentation (diff)
downloadcore-1bf651f34b1e3abb5cbaf6b810aa0b0d9ee86368.tar.gz
core-1bf651f34b1e3abb5cbaf6b810aa0b0d9ee86368.zip
tdf#154771 sw: fix drag & drop moving of table columns
Only first selected column was moved, the other ones were copied during drag & drop moving of table columns. Regression from commit 5e8aa259e48d5602b932353bb146ebb523982cf2 "tdf#146967 sw table: fix freezing in Hide Changes mode". Follow-up to commit 912336f3c85d9a631fa0ac0f270bab04b204f619 "tdf#154599 sw: fix crash at drag & drop table columns". Change-Id: I31ca5b3d6004ed53c11a951fa184b9db48f21041 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150280 Tested-by: Jenkins Reviewed-by: László Németh <nemeth@numbertext.org> (cherry picked from commit 49f80aedf3f2dff70aa410319e80e8622dfa31a1) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150207 Tested-by: László Németh <nemeth@numbertext.org>
-rw-r--r--sw/qa/extras/uiwriter/uiwriter6.cxx56
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx64
2 files changed, 100 insertions, 20 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx
index eeae8a5387d4..c1fe8f97984a 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -992,6 +992,62 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf154599_MovingColumn)
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1->getColumns()->getCount());
}
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf154771_MovingMultipleColumns)
+{
+ createSwDoc();
+ SwDoc* pDoc = getSwDoc();
+ CPPUNIT_ASSERT(pDoc);
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+
+ // Create a table with less columns than rows
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ (void)&pWrtShell->InsertTable(TableOpt, 5, 4);
+
+ uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
+ 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(5), xTable1->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1->getColumns()->getCount());
+
+ // without redlining
+ CPPUNIT_ASSERT_MESSAGE("redlining should be off",
+ !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+
+ // Move first two columns of the table before column D 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* pCellB1 = pCellA1->GetNext();
+ SwFrame* pCellD1 = pCellB1->GetNext()->GetNext();
+ const SwRect& rCellA1Rect = pCellA1->getFrameArea();
+ const SwRect& rCellB1Rect = pCellB1->getFrameArea();
+ const SwRect& rCellD1Rect = pCellD1->getFrameArea();
+ Point ptTo(rCellD1Rect.Left() + rCellD1Rect.Width() / 2,
+ rCellD1Rect.Top() + rCellD1Rect.Height() / 2);
+ // select first two table columns by using
+ // the middle point of the top border of column A
+ // and middle point of the top border of column B
+ Point ptColumnA(rCellA1Rect.Left() + rCellA1Rect.Width() / 2, rCellA1Rect.Top() - 5);
+ const Point ptColumnB(rCellB1Rect.Left() + rCellB1Rect.Width() / 2, rCellB1Rect.Top() - 5);
+ pWrtShell->SelectTableRowCol(ptColumnA, &ptColumnB);
+
+ rtl::Reference<SwTransferable> xTransfer = new SwTransferable(*pWrtShell);
+ xTransfer->PrivateDrop(*pWrtShell, ptTo, /*bMove=*/true, /*bXSelection=*/true);
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable1->getRows()->getCount());
+ // This was 5 before the fix (only the first selected column was moved, the
+ // other ones were copied instead of moving)
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1->getColumns()->getCount());
+}
+
CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf115132)
{
createSwDoc();
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index 57615aa40a7e..ee8bec1e1060 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -3978,10 +3978,37 @@ bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
// up to down, if the cursor is there in its last table row
const SwSelBoxes& rBoxes = rSrcSh.GetTableCursor()->GetSelectedBoxes();
const SwTableNode* pTableNd = rSh.IsCursorInTable();
- sal_Int32 nSelRows = !rBoxes.back()
- ? 0
- : pTableNd->GetTable().GetTabLines().GetPos( rBoxes.back()->GetUpper() ) -
- pTableNd->GetTable().GetTabLines().GetPos( rBoxes.front()->GetUpper() ) + 1;
+ const SwTableLines& rLines = pTableNd->GetTable().GetTabLines();
+ const SwStartNode& rDelPos = rBoxes.back()
+ ? *rBoxes.front()->GetSttNd()
+ : *pTableNd->GetStartNode();
+
+ // count selected rows or columns
+ sal_Int32 nSelRowOrCols = 0;
+ if ( rBoxes.back() )
+ {
+ if ( bTableCol )
+ {
+ // selected column count is the count of the cells
+ // in the first row of the selection
+ auto nLine = rLines.GetPos( rBoxes.front()->GetUpper() );
+ for (auto pBox : rBoxes)
+ {
+ // cell is in the next row
+ if ( nLine != rLines.GetPos( pBox->GetUpper() ) )
+ break;
+ ++nSelRowOrCols;
+ }
+ }
+ else
+ {
+ // selected row count is the difference of the row number of the
+ // first and the last cell of the selection
+ nSelRowOrCols = rLines.GetPos( rBoxes.back()->GetUpper() ) -
+ rLines.GetPos( rBoxes.front()->GetUpper() ) + 1;
+ }
+ }
+
bool bSelUpToDown = rBoxes.back() && rBoxes.back()->GetUpper() ==
rSh.GetCursor()->GetPointNode().GetTableBox()->GetUpper();
@@ -4038,7 +4065,7 @@ bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
const SwTableBox* pBoxStt = rSh.GetCursor()->GetPointNode().GetTableBox();
SwTableLine* pLine = pBoxStt ? const_cast<SwTableLine*>( pBoxStt->GetUpper()): nullptr;
- for (sal_Int32 nDeleted = 0; bNeedTrack && nDeleted < nSelRows;)
+ for (sal_Int32 nDeleted = 0; bNeedTrack && nDeleted < nSelRowOrCols;)
{
// move up text cursor (note: "true" is important for the layout level)
if ( !rSh.Up(false) )
@@ -4072,12 +4099,14 @@ bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
rSh.getIDocumentMarkAccess()->deleteMark( pMarkMoveFrom );
}
- // set all row as tracked deletion, otherwise go to the first moved row
- if ( bNeedTrack || ( bSelUpToDown && nSelRows > 1 ) )
+ // tracked table row moving: set original rows as tracked deletion,
+ // otherwise delete original rows/columns (tracking column deletion
+ // and insertion is not supported yet)
+ if ( !bTableCol && bNeedTrack )
{
pLine = nullptr;
- for (sal_Int32 nDeleted = 0; nDeleted < nSelRows - int(!bNeedTrack);)
+ for (sal_Int32 nDeleted = 0; nDeleted < nSelRowOrCols;)
{
const SwTableBox* pBox = rSh.GetCursor()->GetPointNode().GetTableBox();
@@ -4087,10 +4116,7 @@ bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
if ( pBox->GetUpper() != pLine )
{
pLine = const_cast<SwTableLine*>(pBox->GetUpper());
- if (bNeedTrack)
- pDispatch->Execute(bTableCol
- ? FN_TABLE_DELETE_COL
- : FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
+ pDispatch->Execute(FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
++nDeleted;
}
@@ -4103,19 +4129,17 @@ bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
break;
}
}
-
- // delete original rows/columns, except in track changes mode
- // TODO remove all the columns, not only the first one
- if ( !bNeedTrack )
+ else
{
- for (sal_Int32 nDeleted = 0; nDeleted < nSelRows; ++nDeleted)
+ // set cursor in the first cell of the original selection
+ rSh.GetCursor()->DeleteMark();
+ rSh.GetCursor()->GetPoint()->Assign( rDelPos.GetIndex() + 1);
+
+ for (sal_Int32 nDeleted = 0; nDeleted < nSelRowOrCols; ++nDeleted)
{
pDispatch->Execute(bTableCol
? FN_TABLE_DELETE_COL
: FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
-
- if ( bTableCol )
- break;
}
}
}