summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Krot <Serge.Krot@cib.de>2018-11-22 10:05:47 +0100
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2018-12-05 16:56:43 +0100
commit1575b46276a44fe0566fec8910188a781589dd75 (patch)
treed1efdea2299e176ec8cfd9de30fdf0676db82e43
parentf84f5b0a0cdb82f444de572f9d8554a96056f874 (diff)
tdf#121561: sw: DOCX: add std/stdPr/stdContent around TOC
During export into DOCX from ODT we need to do it because in this case the TOC title will be recognized inside MS Word as part of the TOC. Later we could add support of these keywords in LO import in order to detect TOC title from DOCX input. Added unit test for export. Change-Id: I7135e91dc04d4c0501e6074a046fc473e041f014 Reviewed-on: https://gerrit.libreoffice.org/63786 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport11.cxx13
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport5.cxx2
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx8
-rw-r--r--sw/source/filter/ww8/wrtw8nds.cxx95
-rw-r--r--sw/source/filter/ww8/wrtww8.hxx1
5 files changed, 114 insertions, 5 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index d7fd52d87b6d..3b005e198b87 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -131,6 +131,19 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121456_tabsOffset, "tdf121456_tabsOffset.odt")
}
}
+// tdf#121561: make sure w:sdt/w:sdtContent around TOC is written during ODT->DOCX conversion
+DECLARE_OOXMLEXPORT_TEST(testTdf121561_tocTitle, "tdf121456_tabsOffset.odt")
+{
+ xmlDocPtr pXmlDoc = parseExport();
+ if (!pXmlDoc)
+ return;
+
+ assertXPathContent(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtContent/w:p/w:r/w:t", "Inhaltsverzeichnis");
+ assertXPathContent(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtContent/w:p/w:r/w:instrText", " TOC \\f \\o \"1-9\" \\h");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:docPartObj/w:docPartGallery", "val", "Table of Contents");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:docPartObj/w:docPartUnique", 1);
+}
+
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/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
index be20dd24b246..bd662172ae0c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
@@ -693,7 +693,7 @@ DECLARE_OOXMLEXPORT_TEST(testFdo77129, "fdo77129.docx")
return;
// Data was lost from this paragraph.
- assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[5]/w:r[1]/w:t", "Abstract");
+ assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[4]/w:r[1]/w:t", "Abstract");
}
DECLARE_OOXMLEXPORT_TEST(testfdo79969_xlsm, "fdo79969_xlsm.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
index 277f8b71ce22..84b38fc0a26a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
@@ -143,7 +143,7 @@ DECLARE_OOXMLEXPORT_TEST(testFieldFlagO,"TOC_field_f.docx")
// FIXME "p[2]" will have to be "p[1]", once the TOC import code is fixed
// not to insert an empty paragraph before TOC.
- assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:instrText", " TOC \\z \\f \\o \"1-3\" \\u \\h");
+ assertXPathContent(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtContent/w:p[1]/w:r[2]/w:instrText", " TOC \\z \\f \\o \"1-3\" \\u \\h");
}
DECLARE_OOXMLEXPORT_TEST(testTOCFlag_f, "toc_doc.docx")
@@ -160,7 +160,7 @@ DECLARE_OOXMLEXPORT_TEST(testTOCFlag_f, "toc_doc.docx")
// FIXME "p[2]" will have to be "p[1]", once the TOC import code is fixed
// not to insert an empty paragraph before TOC.
- assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:instrText", " TOC \\z \\o \"1-3\" \\u \\h");
+ assertXPathContent(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtContent/w:p[1]/w:r[2]/w:instrText", " TOC \\z \\o \"1-3\" \\u \\h");
}
DECLARE_OOXMLEXPORT_TEST(testPreserveZfield,"preserve_Z_field_TOC.docx")
@@ -190,7 +190,7 @@ DECLARE_OOXMLEXPORT_TEST(testFieldFlagB,"TOC_field_b.docx")
// FIXME "p[2]" will have to be "p[1]", once the TOC import code is fixed
// not to insert an empty paragraph before TOC.
- assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:instrText", " TOC \\b \"bookmark111\" \\o \"1-9\" \\h");
+ assertXPathContent(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtContent/w:p[1]/w:r[2]/w:instrText", " TOC \\b \"bookmark111\" \\o \"1-9\" \\h");
}
DECLARE_OOXMLEXPORT_TEST(testPreserveXfieldTOC, "PreserveXfieldTOC.docx")
@@ -448,7 +448,7 @@ DECLARE_OOXMLEXPORT_TEST(testFDO78654 , "fdo78654.docx")
return;
// In case of two "Hyperlink" tags in one paragraph and one of them
// contains "PAGEREF" field then field end tag was missing from hyperlink.
- assertXPath ( pXmlDoc, "/w:document/w:body/w:sdt/w:sdtContent/w:p[2]/w:hyperlink[3]/w:r[5]/w:fldChar", "fldCharType", "end" );
+ assertXPath ( pXmlDoc, "/w:document/w:body/w:p[2]/w:hyperlink[3]/w:r[5]/w:fldChar", "fldCharType", "end" );
}
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index bc64e2a4362c..6f87279690f0 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -92,6 +92,7 @@
#include <oox/export/vmlexport.hxx>
#include <sfx2/docfile.hxx>
#include <sal/log.hxx>
+#include <comphelper/propertysequence.hxx>
#include "sprmids.hxx"
@@ -3055,7 +3056,101 @@ void MSWordExportBase::OutputSectionNode( const SwSectionNode& rSectionNode )
}
}
if ( TOX_CONTENT_SECTION == rSection.GetType() )
+ {
m_bStartTOX = true;
+ UpdateTocSectionNodeProperties(rSectionNode);
+ }
+}
+
+// tdf#121561: During export of the ODT file with TOC inside into DOCX format,
+// the TOC title is being exported as regular paragraph. We should surround it
+// with <w:sdt><w:sdtPr><w:sdtContent> to make it (TOC title) recognizable
+// by MS Word as part of the TOC.
+void MSWordExportBase::UpdateTocSectionNodeProperties(const SwSectionNode& rSectionNode)
+{
+ // check section type
+ {
+ const SwSection& rSection = rSectionNode.GetSection();
+ if (TOX_CONTENT_SECTION != rSection.GetType())
+ return;
+
+ const SwTOXBase* pTOX = rSection.GetTOXBase();
+ if (pTOX)
+ {
+ TOXTypes type = pTOX->GetType();
+ if (type != TOXTypes::TOX_CONTENT)
+ return;
+ }
+ }
+
+ // get section node, skip toc-header node
+ const SwSectionNode* pSectNd = &rSectionNode;
+ {
+ SwNodeIndex aIdxNext( *pSectNd, 1 );
+ const SwNode& rNdNext = aIdxNext.GetNode();
+
+ if (rNdNext.IsSectionNode())
+ {
+ const SwSectionNode* pSectNdNext = static_cast<const SwSectionNode*>(&rNdNext);
+ if (TOX_HEADER_SECTION == pSectNdNext->GetSection().GetType() &&
+ pSectNdNext->StartOfSectionNode()->IsSectionNode())
+ {
+ pSectNd = pSectNdNext;
+ }
+ }
+ }
+
+ // get node of the first paragraph inside TOC
+ SwNodeIndex aIdxNext( *pSectNd, 1 );
+ const SwNode& rNdTocPara = aIdxNext.GetNode();
+ const SwContentNode* pNode = rNdTocPara.GetContentNode();
+ if (!pNode)
+ return;
+
+ // put required flags into grab bag of the first node in TOC
+ {
+ uno::Sequence<beans::PropertyValue> aDocPropertyValues(comphelper::InitPropertySequence(
+ {
+ {"ooxml:CT_SdtDocPart_docPartGallery", uno::makeAny(OUString("Table of Contents"))},
+ {"ooxml:CT_SdtDocPart_docPartUnique", uno::makeAny(OUString("true"))},
+ }));
+
+ uno::Sequence<beans::PropertyValue> aSdtPrPropertyValues(comphelper::InitPropertySequence(
+ {
+ {"ooxml:CT_SdtPr_docPartObj", uno::makeAny(aDocPropertyValues)},
+ }));
+
+ SfxGrabBagItem aGrabBag(RES_PARATR_GRABBAG);
+ aGrabBag.GetGrabBag()["SdtPr"] <<= aSdtPrPropertyValues;
+
+ // create temp attr set
+ SwAttrSet aSet(pNode->GetSwAttrSet());
+ aSet.Put(aGrabBag);
+
+ // set new attr to node
+ const_cast<SwContentNode*>(pNode)->SetAttr(aSet);
+ }
+
+ // set flag for the next node after TOC
+ // in order to indicate that std area has been finished
+ // see, DomainMapper::lcl_startParagraphGroup() for the same functionality during load
+ {
+ SwNodeIndex aEndTocNext( *rSectionNode.EndOfSectionNode(), 1 );
+ const SwNode& rEndTocNextNode = aEndTocNext.GetNode();
+ const SwContentNode* pNodeAfterToc = rEndTocNextNode.GetContentNode();
+ if (pNodeAfterToc)
+ {
+ SfxGrabBagItem aGrabBag(RES_PARATR_GRABBAG);
+ aGrabBag.GetGrabBag()["ParaSdtEndBefore"] <<= true;
+
+ // create temp attr set
+ SwAttrSet aSet(pNodeAfterToc->GetSwAttrSet());
+ aSet.Put(aGrabBag);
+
+ // set new attr to node
+ const_cast<SwContentNode*>(pNodeAfterToc)->SetAttr(aSet);
+ }
+ }
}
void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFormat* pFormat, sal_uLong nLnNum )
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 90e1a815a140..9ad0d0bfb1c5 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -843,6 +843,7 @@ protected:
/// Output SwSectionNode
void OutputSectionNode( const SwSectionNode& );
+ static void UpdateTocSectionNodeProperties(const SwSectionNode& rSectionNode);
virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFormat* pFormat, sal_uLong nLnNum ) = 0;