[Libreoffice-commits] core.git: sw/qa writerfilter/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Wed Sep 4 08:41:23 UTC 2019


 sw/qa/extras/ooxmlexport/data/tdf95848.docx       |binary
 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx        |   34 ++++++++++++++++++++++
 writerfilter/source/dmapper/DomainMapper.cxx      |    6 +++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   27 ++++++++++++++++-
 writerfilter/source/dmapper/NumberingManager.cxx  |    9 +++++
 writerfilter/source/dmapper/NumberingManager.hxx  |    5 +++
 writerfilter/source/dmapper/PropertyMap.cxx       |    3 -
 writerfilter/source/dmapper/PropertyMap.hxx       |    8 ++---
 writerfilter/source/dmapper/StyleSheetTable.hxx   |    2 -
 9 files changed, 86 insertions(+), 8 deletions(-)

New commits:
commit 7992bd73a2307edce96a145e954f8e4c3ab9f57d
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Sep 3 13:49:57 2019 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Sep 4 10:40:26 2019 +0200

    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 at cib.de>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf95848.docx b/sw/qa/extras/ooxmlexport/data/tdf95848.docx
new file mode 100644
index 000000000000..3bf17f6928c1
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf95848.docx differ
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


More information about the Libreoffice-commits mailing list