diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2019-09-03 13:49:57 +0200 |
---|---|---|
committer | Michael Stahl <Michael.Stahl@cib.de> | 2019-09-04 10:40:26 +0200 |
commit | 7992bd73a2307edce96a145e954f8e4c3ab9f57d (patch) | |
tree | 0a32009be41014940f66fca0f4f6e899f6fcbbd1 | |
parent | a9e098aa4e66c771642b26527e3e48c48c428574 (diff) |
tdf#95848 writerfilter: DOCX import: fix mapping of w:abstractNum
The problem is that the bugdoc has multiple w:num numbering definitions
that refer to the same w:abstractNum abstract numbering definition.
Apparently (and i can't find this documented anywhere) w:abstractNum
corresponds to a SwList in Writer, i.e. all w:num that refer to the same
w:abstractNum share the same numbering tree, but they may have different
numbering properties via w:lvlOverride.
So i think this should be imported as a single SwList per w:abstractNum,
and every use of w:lvlOverride should create a new SwNumRule, but still
share the same SwList; the previous situation was a SwNumRule + SwList
per w:num element.
This implements simply a SwNumRule per w:num (regardless of
w:lvlOverride) because that was easy; the AbstractListDef class gets a
member to store the ListId of the created SwList when any of its
associated w:num / ListDef is used first, and the non-first ones get
this ListId set to force them into the same SwList.
Unfortunately it turns out the export has the same
SwNumRule->w:abstractNum problem, which remains to be fixed.
Change-Id: I92ce989afd15f24e36b6be6ccaf67ba3e0128963
Reviewed-on: https://gerrit.libreoffice.org/78556
Tested-by: Jenkins
Reviewed-by: Michael Stahl <Michael.Stahl@cib.de>
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf95848.docx | bin | 0 -> 34087 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 34 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 6 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 27 | ||||
-rw-r--r-- | writerfilter/source/dmapper/NumberingManager.cxx | 9 | ||||
-rw-r--r-- | writerfilter/source/dmapper/NumberingManager.hxx | 5 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyMap.cxx | 3 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyMap.hxx | 8 | ||||
-rw-r--r-- | writerfilter/source/dmapper/StyleSheetTable.hxx | 2 |
9 files changed, 86 insertions, 8 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf95848.docx b/sw/qa/extras/ooxmlexport/data/tdf95848.docx Binary files differnew file mode 100644 index 000000000000..3bf17f6928c1 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf95848.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index 804ec41a4bed..295177486228 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -66,6 +66,40 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121374_sectionHF2, "tdf121374_sectionHF2.doc") CPPUNIT_ASSERT( xHeaderText->getString().startsWith("virkamatka-anomus") ); } +// TODO export has the same wrong assumption that abstractNum = SwNumRule +DECLARE_SW_EXPORT_TEST(testTdf95848, "tdf95848.docx", nullptr, Test) +{ + OUString listId; + OUString listStyle; + { + uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel")); + CPPUNIT_ASSERT(xPara->getPropertyValue("NumberingStyleName") >>= listStyle); + CPPUNIT_ASSERT(listStyle.startsWith("WWNum")); + CPPUNIT_ASSERT(xPara->getPropertyValue("ListId") >>= listId); + CPPUNIT_ASSERT_EQUAL(OUString("1.1.1"), getProperty<OUString>(xPara, "ListLabelString")); + } + { + uno::Reference<beans::XPropertySet> xPara(getParagraph(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel")); + CPPUNIT_ASSERT_EQUAL(listStyle, getProperty<OUString>(xPara, "NumberingStyleName")); + CPPUNIT_ASSERT_EQUAL(listId, getProperty<OUString>(xPara, "ListId")); + CPPUNIT_ASSERT_EQUAL(OUString("1.1.2"), getProperty<OUString>(xPara, "ListLabelString")); + } + { + uno::Reference<beans::XPropertySet> xPara(getParagraph(3), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel")); + // different numbering style + OUString listStyle3; + CPPUNIT_ASSERT(xPara->getPropertyValue("NumberingStyleName") >>= listStyle3); + CPPUNIT_ASSERT(listStyle3.startsWith("WWNum")); + CPPUNIT_ASSERT(listStyle3 != listStyle); + // but same list + CPPUNIT_ASSERT_EQUAL(OUString("1.1.3"), getProperty<OUString>(xPara, "ListLabelString")); + CPPUNIT_ASSERT_EQUAL(listId, getProperty<OUString>(xPara, "ListId")); + } +} + DECLARE_OOXMLEXPORT_TEST(testTdf126723, "tdf126723.docx") { CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraph(2), "ParaLeftMargin")); diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index f2cd94906405..6fff9546f18b 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1257,6 +1257,12 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) { uno::Any aRules = uno::makeAny( pList->GetNumberingRules( ) ); rContext->Insert( PROP_NUMBERING_RULES, aRules ); + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH); + if (pContext) + { + assert(dynamic_cast<ParagraphPropertyMap*>(pContext.get())); + static_cast<ParagraphPropertyMap*>(pContext.get())->SetListId(pList->GetId()); + } // erase numbering from pStyle if already set rContext->Erase(PROP_NUMBERING_STYLE_NAME); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 86656009a108..bf88f1e699ca 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1228,15 +1228,17 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con const StyleSheetEntryPtr pEntry = GetStyleSheetTable()->FindStyleSheetByConvertedStyleName( GetCurrentParaStyleName() ); OSL_ENSURE( pEntry.get(), "no style sheet found" ); const StyleSheetPropertyMap* pStyleSheetProperties = dynamic_cast<const StyleSheetPropertyMap*>(pEntry ? pEntry->pProperties.get() : nullptr); + bool isNumberingViaStyle(false); //apply numbering to paragraph if it was set at the style, but only if the paragraph itself //does not specify the numbering if ( !bRemove && pStyleSheetProperties && pParaContext && !pParaContext->isSet(PROP_NUMBERING_RULES) ) { sal_Int32 nListId = pEntry ? lcl_getListId(pEntry, GetStyleSheetTable()) : -1; - if ( nListId >= 0 ) + if (nListId >= 0 && !pParaContext->isSet(PROP_NUMBERING_STYLE_NAME)) { pParaContext->Insert( PROP_NUMBERING_STYLE_NAME, uno::makeAny( ListDef::GetStyleName( nListId ) ), false); + isNumberingViaStyle = true; // Indent properties from the paragraph style have priority // over the ones from the numbering styles in Word @@ -1493,6 +1495,29 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con xTextRange = xTextAppend->finishParagraph( comphelper::containerToSequence(aProperties) ); m_xPreviousParagraph.set(xTextRange, uno::UNO_QUERY); + if (isNumberingViaStyle || itNumberingRules != aProperties.end()) + { + assert(dynamic_cast<ParagraphPropertyMap*>(pPropertyMap.get())); + sal_Int32 const nListId( isNumberingViaStyle + ? pStyleSheetProperties->GetListId() + : static_cast<ParagraphPropertyMap*>(pPropertyMap.get())->GetListId()); + if (ListDef::Pointer const& pList = m_pListTable->GetList(nListId)) + { // styles could refer to non-existing lists... + if (AbstractListDef::Pointer const& pAbsList = + pList->GetAbstractDefinition()) + { + OUString paraId; + m_xPreviousParagraph->getPropertyValue("ListId") >>= paraId; + assert(!paraId.isEmpty()); // must be on some list? + OUString const listId = pAbsList->MapListId(paraId); + if (listId != paraId) + { + m_xPreviousParagraph->setPropertyValue("ListId", uno::makeAny(listId)); + } + } + } + } + if (!rAppendContext.m_aAnchoredObjects.empty() && !IsInHeaderFooter()) { // Remember what objects are anchored to this paragraph. diff --git a/writerfilter/source/dmapper/NumberingManager.cxx b/writerfilter/source/dmapper/NumberingManager.cxx index 659bbed2bb90..1b8a8b283f99 100644 --- a/writerfilter/source/dmapper/NumberingManager.cxx +++ b/writerfilter/source/dmapper/NumberingManager.cxx @@ -428,6 +428,15 @@ uno::Sequence<uno::Sequence<beans::PropertyValue>> AbstractListDef::GetPropertyV return result; } +OUString AbstractListDef::MapListId(OUString const& rId) +{ + if (!m_oListId) + { + m_oListId = rId; + } + return *m_oListId; +} + //---------------------------------------------- ListDef implementation ListDef::ListDef( ) : AbstractListDef( ) diff --git a/writerfilter/source/dmapper/NumberingManager.hxx b/writerfilter/source/dmapper/NumberingManager.hxx index f8e67f0fd638..c484b7bd9803 100644 --- a/writerfilter/source/dmapper/NumberingManager.hxx +++ b/writerfilter/source/dmapper/NumberingManager.hxx @@ -131,6 +131,9 @@ private: // The style name linked to. OUString m_sNumStyleLink; + /// list id to use for all derived numbering definitions + boost::optional<OUString> m_oListId; + public: typedef tools::SvRef< AbstractListDef > Pointer; @@ -154,6 +157,8 @@ public: void SetNumStyleLink(const OUString& sValue) { m_sNumStyleLink = sValue; }; const OUString& GetNumStyleLink() { return m_sNumStyleLink; }; + + OUString MapListId(OUString const& rId); }; class ListDef : public AbstractListDef diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx index c59b13e7378c..8755cfa20970 100644 --- a/writerfilter/source/dmapper/PropertyMap.cxx +++ b/writerfilter/source/dmapper/PropertyMap.cxx @@ -1775,8 +1775,7 @@ sal_Int32 SectionPropertyMap::GetPageWidth() } StyleSheetPropertyMap::StyleSheetPropertyMap() - : mnListId( -1 ) - , mnListLevel( -1 ) + : mnListLevel( -1 ) , mnOutlineLevel( -1 ) , mnNumId( -1 ) { diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx index af8bb6842e38..359cc665f74c 100644 --- a/writerfilter/source/dmapper/PropertyMap.hxx +++ b/writerfilter/source/dmapper/PropertyMap.hxx @@ -408,6 +408,7 @@ private: css::uno::Reference< css::text::XTextRange > m_xStartingRange; // start of a frame css::uno::Reference< css::text::XTextRange > m_xEndingRange; // end of the frame + sal_Int32 m_nListId = -1; public: ParagraphProperties(); @@ -420,6 +421,9 @@ public: // Does not compare the starting/ending range, m_sParaStyleName and m_nDropCapLength bool operator==( const ParagraphProperties& ); + sal_Int32 GetListId() const { return m_nListId; } + void SetListId( sal_Int32 nId ) { m_nListId = nId; } + bool IsFrameMode() const { return m_bFrameMode; } void SetFrameMode( bool set = true ) { m_bFrameMode = set; } @@ -496,7 +500,6 @@ class StyleSheetPropertyMap , public ParagraphProperties { private: - sal_Int32 mnListId; sal_Int16 mnListLevel; sal_Int16 mnOutlineLevel; sal_Int32 mnNumId; @@ -504,9 +507,6 @@ private: public: explicit StyleSheetPropertyMap(); - sal_Int32 GetListId() const { return mnListId; } - void SetListId( sal_Int32 nId ) { mnListId = nId; } - sal_Int16 GetListLevel() const { return mnListLevel; } void SetListLevel( sal_Int16 nLevel ) { mnListLevel = nLevel; } diff --git a/writerfilter/source/dmapper/StyleSheetTable.hxx b/writerfilter/source/dmapper/StyleSheetTable.hxx index 960651394955..9cd35b48ec3c 100644 --- a/writerfilter/source/dmapper/StyleSheetTable.hxx +++ b/writerfilter/source/dmapper/StyleSheetTable.hxx @@ -63,7 +63,7 @@ public: OUString sBaseStyleIdentifier; OUString sNextStyleIdentifier; OUString sStyleName; - PropertyMapPtr pProperties; + const PropertyMapPtr pProperties; ///< always StyleSheetPropertyMap OUString sConvertedStyleName; std::vector<css::beans::PropertyValue> aLatentStyles; ///< Attributes of latentStyles std::vector<css::beans::PropertyValue> aLsdExceptions; ///< List of lsdException attribute lists |