diff options
-rw-r--r-- | offapi/com/sun/star/text/CellProperties.idl | 6 | ||||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter5.cxx | 103 | ||||
-rw-r--r-- | sw/source/core/bastyp/init.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentRedlineManager.cxx | 28 | ||||
-rw-r--r-- | sw/source/core/frmedt/fetab.cxx | 49 | ||||
-rw-r--r-- | sw/source/core/unocore/unomap.cxx | 1 |
6 files changed, 185 insertions, 6 deletions
diff --git a/offapi/com/sun/star/text/CellProperties.idl b/offapi/com/sun/star/text/CellProperties.idl index 2448c25c8439..58c9718c0dc2 100644 --- a/offapi/com/sun/star/text/CellProperties.idl +++ b/offapi/com/sun/star/text/CellProperties.idl @@ -130,6 +130,12 @@ published service CellProperties @since LibreOffice 6.3 */ [optional, readonly, property] com::sun::star::text::XText ParentText; + + /** If TRUE, the table cell wasn't deleted or inserted with its tracked cell content + + @since LibreOffice 7.6 + */ + [optional, property, maybevoid] boolean HasTextChangesOnly; }; diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx b/sw/qa/extras/uiwriter/uiwriter5.cxx index ee7c041b78c5..38fe2143a992 100644 --- a/sw/qa/extras/uiwriter/uiwriter5.cxx +++ b/sw/qa/extras/uiwriter/uiwriter5.cxx @@ -2453,6 +2453,109 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180_empty_rows) CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletion) +{ + // load a table, and delete the first column with enabled change tracking: + // now the column is not deleted silently, but keeps the deleted cell content, + // and only accepting it will result the deletion of the table column. + createSwDoc("tdf118311.fodt"); + SwDoc* pDoc = getSwDoc(); + + // turn on red-lining and show changes + pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete + | RedlineFlags::ShowInsert); + CPPUNIT_ASSERT_MESSAGE("redlining should be on", + pDoc->getIDocumentRedlineAccess().IsRedlineOn()); + CPPUNIT_ASSERT_MESSAGE( + "redlines should be visible", + IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); + + // check table + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2); + + // delete table column with enabled change tracking + // (HasTextChangesOnly property of the cell will be false) + dispatchCommand(mxComponent, ".uno:DeleteColumns", {}); + + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + // This was 1 (deleted cell without change tracking) + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2); + + // accept the deletion + SwEditShell* const pEditShell(pDoc->GetEditShell()); + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount()); + pEditShell->AcceptRedline(0); + + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + // deleted column + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1); + + // Undo, and repeat the previous test, but only with deletion of the text content of the cells + // (HasTextChangesOnly property will be removed by Undo) + + dispatchCommand(mxComponent, ".uno:Undo", {}); + dispatchCommand(mxComponent, ".uno:Undo", {}); + + // first column exists again + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2); + + // delete table column with enabled change tracking + dispatchCommand(mxComponent, ".uno:SelectColumn", {}); + dispatchCommand(mxComponent, ".uno:Delete", {}); + + // Table column still exists + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2); + + // accept the deletion of the content of the first cell + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount()); + pEditShell->AcceptRedline(0); + + // table column was still not deleted + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2); + + // Undo, and delete the column without change tracking + + dispatchCommand(mxComponent, ".uno:Undo", {}); + dispatchCommand(mxComponent, ".uno:Undo", {}); + + // table exists again + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2); + + // disable change tracking + pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete + | RedlineFlags::ShowInsert); + + CPPUNIT_ASSERT_MESSAGE("redlining should be off", + !pDoc->getIDocumentRedlineAccess().IsRedlineOn()); + + // delete table column without change tracking + dispatchCommand(mxComponent, ".uno:DeleteColumns", {}); + + // the table column was deleted + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335) { // Load the bugdoc, which has 3 textboxes. diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx index a5bcd736966e..f2a4d974cfa1 100644 --- a/sw/source/core/bastyp/init.cxx +++ b/sw/source/core/bastyp/init.cxx @@ -204,8 +204,8 @@ WhichRangesContainer const aTableSetRange(svl::Items< WhichRangesContainer const aTableLineSetRange(svl::Items< RES_FILL_ORDER, RES_FRM_SIZE, - // HasTextChangesOnly RES_LR_SPACE, RES_UL_SPACE, + // HasTextChangesOnly RES_PRINT, RES_PRINT, RES_PROTECT, RES_PROTECT, RES_VERT_ORIENT, RES_VERT_ORIENT, @@ -218,6 +218,8 @@ WhichRangesContainer const aTableLineSetRange(svl::Items< WhichRangesContainer const aTableBoxSetRange(svl::Items< RES_FILL_ORDER, RES_FRM_SIZE, RES_LR_SPACE, RES_UL_SPACE, + // HasTextChangesOnly + RES_PRINT, RES_PRINT, RES_PROTECT, RES_PROTECT, RES_VERT_ORIENT, RES_VERT_ORIENT, RES_BACKGROUND, RES_SHADOW, diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 4e9176cc340a..8ce8a4873aab 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -457,6 +457,30 @@ namespace if ( !pBox ) return; + // tracked column deletion + + const SvxPrintItem *pHasBoxTextChangesOnlyProp = + pBox->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT); + // empty table cell with property "HasTextChangesOnly" = false + if ( pHasBoxTextChangesOnlyProp && !pHasBoxTextChangesOnlyProp->GetValue() ) + { + SwCursor aCursor( *pPos, nullptr ); + if ( pBox->IsEmpty() ) + { + // TODO check the other cells of the column + // before removing the column + pPos->GetDoc().DeleteCol( aCursor ); + return; + } + else + { + SvxPrintItem aHasTextChangesOnly(RES_PRINT, false); + pPos->GetDoc().SetBoxAttr( aCursor, aHasTextChangesOnly ); + } + } + + // tracked row deletion + const SwTableLine* pLine = pBox->GetUpper(); const SvxPrintItem *pHasTextChangesOnlyProp = pLine->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT); @@ -2330,9 +2354,9 @@ DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCall { if ( aSttIdx.GetNode().IsTableNode() ) { - SvxPrintItem aNotTracked(RES_PRINT, false); + SvxPrintItem aHasTextChangesOnly(RES_PRINT, false); SwCursor aCursor( SwPosition(aSttIdx), nullptr ); - m_rDoc.SetRowNotTracked( aCursor, aNotTracked, /*bAll=*/true ); + m_rDoc.SetRowNotTracked( aCursor, aHasTextChangesOnly, /*bAll=*/true ); } ++aSttIdx; } diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx index c51413e3ba9b..daca7b86bc9c 100644 --- a/sw/source/core/frmedt/fetab.cxx +++ b/sw/source/core/frmedt/fetab.cxx @@ -276,6 +276,49 @@ bool SwFEShell::DeleteCol() } CurrShell aCurr( this ); + + // tracked deletion: remove only textbox content, + // and set IsNoTracked table box property to false + if ( GetDoc()->GetDocShell()->IsChangeRecording() ) + { + StartUndo(SwUndoId::COL_DELETE); + StartAllAction(); + + if ( SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(this) ) + pWrtShell->SelectTableCol(); + + // search boxes via the layout + SwSelBoxes aBoxes; + GetTableSel( *this, aBoxes, SwTableSearchType::Col ); + + TableWait aWait( 20, pFrame, *GetDoc()->GetDocShell(), aBoxes.size() ); + + for (size_t i = 0; i < aBoxes.size(); ++i) + { + SwTableBox *pBox = aBoxes[i]; + if ( pBox->GetSttNd() ) + { + SwNodeIndex aIdx( *pBox->GetSttNd(), 1 ); + SwCursor aCursor( SwPosition(aIdx), nullptr ); + SvxPrintItem aHasTextChangesOnly(RES_PRINT, false); + GetDoc()->SetBoxAttr( aCursor, aHasTextChangesOnly ); + } + } + + SwEditShell* pEditShell = GetDoc()->GetEditShell(); + SwRedlineTable::size_type nPrev = pEditShell->GetRedlineCount(); + pEditShell->Delete(); + + EndAllActionAndCall(); + EndUndo(SwUndoId::COL_DELETE); + + // track column deletion only if there were tracked text changes + // FIXME redline count can be the same in special cases, e.g. adding a + // new tracked deletion with removing an own tracked insertion... + if ( nPrev != pEditShell->GetRedlineCount() ) + return true; + } + StartAllAction(); // search boxes via the layout @@ -349,11 +392,11 @@ bool SwFEShell::DeleteRow(bool bCompleteTable) StartAllAction(); // tracked deletion: remove only textbox content, - // and set IsNoTracked table line property to false + // and set HasTextChangesOnly table line property to false if ( bRecordChanges ) { - SvxPrintItem aNotTracked(RES_PRINT, false); - GetDoc()->SetRowNotTracked( *getShellCursor( false ), aNotTracked ); + SvxPrintItem aHasTextChangesOnly(RES_PRINT, false); + GetDoc()->SetRowNotTracked( *getShellCursor( false ), aHasTextChangesOnly ); if ( SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(this) ) pWrtShell->SelectTableRow(); diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx index 40223b34e474..68565eadaf6f 100644 --- a/sw/source/core/unocore/unomap.cxx +++ b/sw/source/core/unocore/unomap.cxx @@ -186,6 +186,7 @@ o3tl::span<const SfxItemPropertyMapEntry> SwUnoPropertyMapProvider::GetPropertyM { UNO_NAME_ROW_SPAN, FN_UNO_CELL_ROW_SPAN, cppu::UnoType<sal_Int32>::get(), 0, 0 }, { UNO_NAME_CELL_INTEROP_GRAB_BAG, RES_FRMATR_GRABBAG, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), PROPERTY_NONE, 0 }, { UNO_NAME_PARENT_TEXT, FN_UNO_PARENT_TEXT, cppu::UnoType<text::XText>::get(), PropertyAttribute::MAYBEVOID | PropertyAttribute::READONLY, 0 }, + { UNO_NAME_HAS_TEXT_CHANGES_ONLY, RES_PRINT, cppu::UnoType<bool>::get() , PropertyAttribute::MAYBEVOID, 0}, REDLINE_NODE_PROPERTIES }; m_aMapEntriesArr[nPropertyId] = aCellMap_Impl; |