diff options
author | Serge Krot <Serge.Krot@cib.de> | 2018-12-06 19:11:58 +0100 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2019-01-09 22:30:08 +0100 |
commit | ff4f2ba3242d303f7f238a7a142440f1f4b1f288 (patch) | |
tree | e26084095041d94378b9189ea026da22b8e456b6 | |
parent | f22f28e722a8a2efdc42bddba80a3a43025a61fd (diff) |
sw: DOCX: recognize TOC title during import
Change-Id: Ifa4fb59858d61580f76e3d104aa4caa6b5902d1b
Reviewed-on: https://gerrit.libreoffice.org/64735
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r-- | sw/inc/doc.hxx | 5 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport11.cxx | 14 | ||||
-rw-r--r-- | sw/source/core/doc/doctxm.cxx | 17 | ||||
-rw-r--r-- | sw/source/core/unocore/unoidx.cxx | 6 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.cxx | 5 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 159 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 5 |
7 files changed, 176 insertions, 35 deletions
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 3878c4299b89..4d1cf10c9010 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -917,6 +917,11 @@ public: const SfxItemSet* pSet = nullptr, bool bExpand = false, SwRootFrame const* pLayout = nullptr); + SwTOXBaseSection* InsertTableOf( const SwPaM& aPam, + const SwTOXBase& rTOX, + const SfxItemSet* pSet = nullptr, + bool bExpand = false, + SwRootFrame const* pLayout = nullptr ); void InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd, const SwTOXBase& rTOX, const SfxItemSet* pSet ); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx index b36fe833dcc3..90c7566e30d3 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx @@ -24,6 +24,7 @@ #include <com/sun/star/graphic/XGraphic.hpp> #include <com/sun/star/text/RubyAdjust.hpp> #include <com/sun/star/text/RubyPosition.hpp> +#include <com/sun/star/text/XDocumentIndex.hpp> #include <sfx2/docfile.hxx> @@ -144,6 +145,19 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121561_tocTitle, "tdf121456_tabsOffset.odt") assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:docPartObj/w:docPartUnique", 1); } +DECLARE_OOXMLEXPORT_TEST(testTdf121561_tocTitleDocx, "tdf121456_tabsOffset.odt") +{ + xmlDocPtr pXmlDoc = parseExport(); + if (!pXmlDoc) + return; + + uno::Reference<text::XDocumentIndexesSupplier> xIndexSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xIndexes(xIndexSupplier->getDocumentIndexes( ), uno::UNO_QUERY); + uno::Reference<text::XDocumentIndex> xTOCIndex(xIndexes->getByIndex(0), uno::UNO_QUERY); + + CPPUNIT_ASSERT_EQUAL(OUString("Inhaltsverzeichnis"), getProperty<OUString>(xTOCIndex, "Title")); +} + DECLARE_OOXMLEXPORT_TEST(testTdf106174_rtlParaAlign, "tdf106174_rtlParaAlign.docx") { CPPUNIT_ASSERT_EQUAL(sal_Int16(style::ParagraphAdjust_CENTER), getProperty<sal_Int16>(getParagraph(1), "ParaAdjust")); diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx index 4e7ab4507e06..923cd9b1084f 100644 --- a/sw/source/core/doc/doctxm.cxx +++ b/sw/source/core/doc/doctxm.cxx @@ -347,15 +347,24 @@ const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark, } SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos, - const SwTOXBase& rTOX, - const SfxItemSet* pSet, - bool bExpand, + const SwTOXBase& rTOX, + const SfxItemSet* pSet, + bool bExpand, SwRootFrame const*const pLayout) { + SwPaM aPam( rPos ); + return InsertTableOf( aPam, rTOX, pSet, bExpand, pLayout ); +} + +SwTOXBaseSection* SwDoc::InsertTableOf( const SwPaM& aPam, + const SwTOXBase& rTOX, + const SfxItemSet* pSet, + bool bExpand, + SwRootFrame const*const pLayout ) +{ GetIDocumentUndoRedo().StartUndo( SwUndoId::INSTOX, nullptr ); OUString sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), rTOX.GetTOXName() ); - SwPaM aPam( rPos ); SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm ); SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>( InsertSwSection( aPam, aSectionData, & rTOX, pSet, false )); diff --git a/sw/source/core/unocore/unoidx.cxx b/sw/source/core/unocore/unoidx.cxx index 7e40304a6f2a..c7f3397b62b0 100644 --- a/sw/source/core/unocore/unoidx.cxx +++ b/sw/source/core/unocore/unoidx.cxx @@ -1340,10 +1340,6 @@ SwXDocumentIndex::attach(const uno::Reference< text::XTextRange > & xTextRange) } UnoActionContext aAction(pDoc); - if (aPam.HasMark()) - { - pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam); - } SwTOXBase & rTOXBase = m_pImpl->m_pProps->GetTOXBase(); SwTOXType const*const pTOXType = rTOXBase.GetTOXType(); @@ -1354,7 +1350,7 @@ SwXDocumentIndex::attach(const uno::Reference< text::XTextRange > & xTextRange) } //TODO: apply Section attributes (columns and background) SwTOXBaseSection *const pTOX = - pDoc->InsertTableOf( *aPam.GetPoint(), rTOXBase, nullptr, false, + pDoc->InsertTableOf( aPam, rTOXBase, nullptr, false, m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()); pDoc->SetTOXBaseName(*pTOX, m_pImpl->m_pProps->GetTOXBase().GetTOXName()); diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 097195c9cc20..79717e24761c 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -1442,6 +1442,11 @@ void DocxExport::WriteMainText() // setup the namespaces m_pDocumentFS->startElementNS( XML_w, XML_document, MainXmlNamespaces()); + if ( getenv("SW_DEBUG_DOM") ) + { + m_pDoc->dumpAsXml(); + } + // reset the incrementing linked-textboxes chain ID before re-saving. m_nLinkedTextboxesChainId=0; m_aLinkedTextboxesHelper.clear(); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 6e2fc620fc93..a0d79ac26554 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -514,6 +514,15 @@ void DomainMapper_Impl::SetParaSectpr(bool bParaSectpr) void DomainMapper_Impl::SetSdt(bool bSdt) { m_bSdt = bSdt; + + if (m_bSdt) + { + m_xStdEntryStart = GetTopTextAppend()->getEnd(); + } + else + { + m_xStdEntryStart = uno::Reference< text::XTextRange >(); + } } @@ -3680,6 +3689,42 @@ static uno::Sequence< beans::PropertyValues > lcl_createTOXLevelHyperlinks( bool return aNewLevel; } +/// Returns title of the TOC placed in paragraph(s) before TOC field inside STD-frame +OUString DomainMapper_Impl::extractTocTitle() +{ + if (!m_xStdEntryStart.is()) + return OUString(); + + uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend; + if(!xTextAppend.is()) + return OUString(); + + // try-catch was added in the same way as inside appendTextSectionAfter() + try + { + uno::Reference< text::XParagraphCursor > xCursor( xTextAppend->createTextCursorByRange( m_xStdEntryStart ), uno::UNO_QUERY_THROW); + if (!xCursor.is()) + return OUString(); + + //the cursor has been moved to the end of the paragraph because of the appendTextPortion() calls + xCursor->gotoStartOfParagraph( false ); + if (m_aTextAppendStack.top().xInsertPosition.is()) + xCursor->gotoRange( m_aTextAppendStack.top().xInsertPosition, true ); + else + xCursor->gotoEnd( true ); + + //the paragraph after this new section is already inserted + xCursor->goLeft(1, true); + + return xCursor->getString(); + } + catch(const uno::Exception&) + { + } + + return OUString(); +} + void DomainMapper_Impl::handleToc (const FieldContextPtr& pContext, const OUString & sTOCServiceName) @@ -3799,16 +3844,57 @@ void DomainMapper_Impl::handleToc if( !bFromOutline && !bFromEntries && sTemplate.isEmpty() ) bFromOutline = true; + const OUString aTocTitle = extractTocTitle(); + + if (m_xTextFactory.is() && ! m_aTextAppendStack.empty()) + { + if (aTocTitle.isEmpty() || bTableOfFigures) + { + xTOC.set( + m_xTextFactory->createInstance + ( bTableOfFigures ? + "com.sun.star.text.IllustrationsIndex" + : sTOCServiceName), + uno::UNO_QUERY_THROW); + + OUString const sMarker("Y"); + //insert index + uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY ); + uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend; + if (xTextAppend.is()) + { + uno::Reference< text::XTextCursor > xCrsr = xTextAppend->getText()->createTextCursor(); + uno::Reference< text::XText > xText = xTextAppend->getText(); + if(xCrsr.is() && xText.is()) + { + xCrsr->gotoEnd(false); + xText->insertString(xCrsr, sMarker, false); + xText->insertTextContent(uno::Reference< text::XTextRange >( xCrsr, uno::UNO_QUERY_THROW ), xToInsert, false); + xTOCMarkerCursor = xCrsr; + } + } + } + else + { + // create TOC section + css::uno::Reference<css::text::XTextRange> xTextRangeEndOfTocHeader = GetTopTextAppend()->getEnd(); + xTOC = createSectionForRange(m_xStdEntryStart, xTextRangeEndOfTocHeader, sTOCServiceName, false); + + // init [xTOCMarkerCursor] + uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend; + uno::Reference< text::XText > xText = xTextAppend->getText(); + uno::Reference< text::XTextCursor > xCrsr = xText->createTextCursor(); + xTOCMarkerCursor = xCrsr; + + // create header of the TOC with the TOC title inside + const OUString aObjectType("com.sun.star.text.IndexHeaderSection"); + uno::Reference<beans::XPropertySet> xIfc = createSectionForRange(m_xStdEntryStart, xTextRangeEndOfTocHeader, aObjectType, true); + } + } - if (m_xTextFactory.is()) - xTOC.set( - m_xTextFactory->createInstance - ( bTableOfFigures ? - "com.sun.star.text.IllustrationsIndex" - : sTOCServiceName), - uno::UNO_QUERY_THROW); if (xTOC.is()) - xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), uno::makeAny(OUString())); + xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), uno::makeAny(aTocTitle)); + if (!aBookmarkName.isEmpty()) xTOC->setPropertyValue(getPropertyName(PROP_TOC_BOOKMARK), uno::makeAny(aBookmarkName)); if( !bTableOfFigures && xTOC.is() ) @@ -3898,27 +3984,45 @@ void DomainMapper_Impl::handleToc } pContext->SetTOC( xTOC ); m_bParaHadField = false; +} - if (m_aTextAppendStack.empty()) - return; +uno::Reference<beans::XPropertySet> DomainMapper_Impl::createSectionForRange( + uno::Reference< css::text::XTextRange > xStart, + uno::Reference< css::text::XTextRange > xEnd, + const OUString & sObjectType, + bool stepLeft) +{ + if (!xStart.is()) + return uno::Reference<beans::XPropertySet>(); + if (!xEnd.is()) + return uno::Reference<beans::XPropertySet>(); - OUString const sMarker("Y"); - //insert index - uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xRet; + if (m_aTextAppendStack.empty()) + return xRet; uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend; - if (xTextAppend.is()) + if(xTextAppend.is()) { - uno::Reference< text::XTextCursor > xCrsr = xTextAppend->getText()->createTextCursor(); - - uno::Reference< text::XText > xText = xTextAppend->getText(); - if(xCrsr.is() && xText.is()) + try + { + uno::Reference< text::XParagraphCursor > xCursor( + xTextAppend->createTextCursorByRange( xStart ), uno::UNO_QUERY_THROW); + //the cursor has been moved to the end of the paragraph because of the appendTextPortion() calls + xCursor->gotoStartOfParagraph( false ); + xCursor->gotoRange( xEnd, true ); + //the paragraph after this new section is already inserted + if (stepLeft) + xCursor->goLeft(1, true); + uno::Reference< text::XTextContent > xSection( m_xTextFactory->createInstance(sObjectType), uno::UNO_QUERY_THROW ); + xSection->attach( uno::Reference< text::XTextRange >( xCursor, uno::UNO_QUERY_THROW) ); + xRet.set(xSection, uno::UNO_QUERY ); + } + catch(const uno::Exception&) { - xCrsr->gotoEnd(false); - xText->insertString(xCrsr, sMarker, false); - xText->insertTextContent(uno::Reference< text::XTextRange >( xCrsr, uno::UNO_QUERY_THROW ), xToInsert, false); - xTOCMarkerCursor = xCrsr; } } + + return xRet; } void DomainMapper_Impl::handleBibliography @@ -5005,10 +5109,13 @@ void DomainMapper_Impl::PopFieldContext() } else { - xTOCMarkerCursor->goLeft(1,true); - xTOCMarkerCursor->setString(OUString()); - xTOCMarkerCursor->goLeft(1,true); - xTOCMarkerCursor->setString(OUString()); + if (!m_xStdEntryStart.is()) + { + xTOCMarkerCursor->goLeft(1,true); + xTOCMarkerCursor->setString(OUString()); + xTOCMarkerCursor->goLeft(1,true); + xTOCMarkerCursor->setString(OUString()); + } } } if (m_bStartedTOC || m_bStartIndex || m_bStartBibliography) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index c20912dabdd5..6006d2465f13 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -542,6 +542,7 @@ private: SmartTagHandler m_aSmartTagHandler; css::uno::Reference<css::text::XTextRange> m_xGlossaryEntryStart; + css::uno::Reference<css::text::XTextRange> m_xStdEntryStart; public: css::uno::Reference<css::text::XTextRange> m_xInsertTextRange; @@ -795,6 +796,10 @@ public: /// The end of field is reached (cFieldEnd appeared) - the command might still be open. void PopFieldContext(); + /// Returns title of the TOC placed in paragraph(s) before TOC field inside STD-frame + OUString extractTocTitle(); + css::uno::Reference<css::beans::XPropertySet> createSectionForRange(css::uno::Reference< css::text::XTextRange > xStart, css::uno::Reference< css::text::XTextRange > xEnd, const OUString & sObjectType, bool stepLeft); + void SetBookmarkName( const OUString& rBookmarkName ); void StartOrEndBookmark( const OUString& rId ); |