diff options
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter2.cxx | 59 | ||||
-rw-r--r-- | sw/source/core/unocore/unocrsrhelper.cxx | 16 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 59 |
3 files changed, 132 insertions, 2 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index d91c89848495..de0c06f5d6bb 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -3822,6 +3822,65 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineTableRowDeletionWithExport) assertXPath(pXmlDoc, "//page[1]//body/tab", 0); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineTableRowDeletionWithDOCXExport) +{ + // load a 1-row table, and delete the row with enabled change tracking: + // now the row is not deleted silently, but keeps the deleted cell contents, + // and only accepting all of them will result the deletion of the table row. + SwDoc* pDoc = createDoc("tdf118311.fodt"); + + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + + // 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"); + + // delete table row with enabled change tracking + // (HasTextChangesOnly property of the row will be false) + dispatchCommand(mxComponent, ".uno:DeleteRows", {}); + + // Deleted text content with change tracking, + // but not table deletion + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + + // Save it to a DOCX and load it back. + // Exporting change tracking of the row wasn't supported. + // Also Manage Changes for the import. + reload("Office Open XML Text", "tdf79069_tracked_table_deletion.docx"); + pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + pDoc = pTextDoc->GetDocShell()->GetWrtShell()->GetDoc(); + + // accept the deletion of the content of the first cell + SwEditShell* const pEditShell(pDoc->GetEditShell()); + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount()); + pEditShell->AcceptRedline(0); + + // table row was still not deleted + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab"); + + // accept last redline + pEditShell->AcceptRedline(0); + + // table row (and the 1-row table) was deleted finally + // (working export/import of HasTextChangesOnly) + discardDumpedLayout(); + pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page[1]//body/tab", 0); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf128335) { // Load the bugdoc, which has 3 textboxes. diff --git a/sw/source/core/unocore/unocrsrhelper.cxx b/sw/source/core/unocore/unocrsrhelper.cxx index 32b449b97403..58d5dbf6b11e 100644 --- a/sw/source/core/unocore/unocrsrhelper.cxx +++ b/sw/source/core/unocore/unocrsrhelper.cxx @@ -72,6 +72,7 @@ #include <fchrfmt.hxx> #include <editeng/editids.hrc> #include <editeng/flstitem.hxx> +#include <editeng/prntitem.hxx> #include <vcl/metric.hxx> #include <svtools/ctrltool.hxx> #include <sfx2/docfilt.hxx> @@ -1388,7 +1389,8 @@ void makeTableRowRedline( SwTableLine& rTableLine, std::u16string_view rRedlineType, const uno::Sequence< beans::PropertyValue >& rRedlineProperties ) { - IDocumentRedlineAccess* pRedlineAccess = &rTableLine.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess(); + SwDoc* pDoc = rTableLine.GetFrameFormat()->GetDoc(); + IDocumentRedlineAccess* pRedlineAccess = &pDoc->getIDocumentRedlineAccess(); RedlineType eType; if ( rRedlineType == u"TableRowInsert" ) @@ -1398,6 +1400,18 @@ void makeTableRowRedline( SwTableLine& rTableLine, else if ( rRedlineType == u"TableRowDelete" ) { eType = RedlineType::TableRowDelete; + + // set table row property "HasTextChangesOnly" to false + // to handle tracked deletion of the table row on the UI + const SvxPrintItem *pHasTextChangesOnlyProp = + rTableLine.GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT); + if ( !pHasTextChangesOnlyProp || pHasTextChangesOnlyProp->GetValue() ) + { + SvxPrintItem aSetTracking(RES_PRINT, false); + SwPosition aPos( *rTableLine.GetTabBoxes()[0]->GetSttNd() ); + SwCursor aCursor( aPos, nullptr ); + pDoc->SetRowNotTracked( aCursor, aSetTracking ); + } } else { diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 1690e567fd7e..c0faa7a00fff 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -90,6 +90,7 @@ #include <editeng/editobj.hxx> #include <editeng/keepitem.hxx> #include <editeng/borderline.hxx> +#include <editeng/prntitem.hxx> #include <sax/tools/converter.hxx> #include <svx/xdef.hxx> #include <svx/xfillit0.hxx> @@ -4348,7 +4349,63 @@ void DocxAttributeOutput::TableRowRedline( ww8::WW8TableNodeInfoInner::Pointer_t const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox(); const SwTableLine * pTabLine = pTabBox->GetUpper(); - // search next Redline + // check table row property "HasTextChangesOnly" (used only for tracked deletion, yet) + const SwRedlineTable& aRedlineTable = m_rExport.m_rDoc.getIDocumentRedlineAccess().GetRedlineTable(); + const SvxPrintItem *pHasTextChangesOnlyProp = + pTabLine->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT); + if ( !aRedlineTable.empty() && pHasTextChangesOnlyProp && !pHasTextChangesOnlyProp->GetValue() ) + { + // Tracked row deletion is associated to the newest redline range in the row. + // Search it to get the date and the mandatory author. + const SwTableBoxes & rBoxes = pTabLine->GetTabBoxes(); + SwPosition aRowStart( SwNodeIndex( *rBoxes[0]->GetSttNd(), 0 ) ); + SwPosition aRowEnd( SwNodeIndex( *rBoxes[rBoxes.size() - 1]->GetSttNd()->EndOfSectionNode(), -1 ) ); + SwNodeIndex pEndNodeIndex(aRowEnd.nNode.GetNode()); + + SwRedlineTable::size_type nLastDeletion = SwRedlineTable::npos; + for( SwRedlineTable::size_type n = 0; n < aRedlineTable.size(); ++n ) + { + const SwRangeRedline* pRedline = aRedlineTable[ n ]; + + if ( pRedline->Start()->nNode > pEndNodeIndex ) + break; + + if( RedlineType::Delete != pRedline->GetType() ) + continue; + + // redline is in the table row, and newer, than the previous + if ( aRowStart <= *pRedline->Start() ) + { + if ( nLastDeletion == SwRedlineTable::npos || + aRedlineTable [ nLastDeletion ]->GetRedlineData().GetTimeStamp() < + pRedline->GetRedlineData().GetTimeStamp() ) + { + nLastDeletion = n; + } + } + } + + if ( nLastDeletion != SwRedlineTable::npos ) + { + const SwRedlineData& aRedlineData = aRedlineTable[ nLastDeletion ]->GetRedlineData(); + // Note: all redline ranges and table row redline (with the same author and timestamp) + // use the same redline id in OOXML exported by MSO, but it seems, the recent solution + // (different IDs for different ranges, also row changes) is also portable. + OString aId( OString::number( m_nRedlineId++ ) ); + const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( aRedlineData.GetAuthor() ) ); + OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) ); + + OString aDate( DateTimeToOString( aRedlineData.GetTimeStamp() ) ); + + m_pSerializer->singleElementNS( XML_w, XML_del, + FSNS( XML_w, XML_id ), aId, + FSNS( XML_w, XML_author ), aAuthor, + FSNS( XML_w, XML_date ), aDate ); + return; + } + } + + // search next Redline (only deletion of empty rows and all insertions imported from a DOCX) const SwExtraRedlineTable& aExtraRedlineTable = m_rExport.m_rDoc.getIDocumentRedlineAccess().GetExtraRedlineTable(); for(sal_uInt16 nCurRedlinePos = 0; nCurRedlinePos < aExtraRedlineTable.GetSize(); ++nCurRedlinePos ) { |