summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2019-09-03 13:49:57 +0200
committerMichael Stahl <Michael.Stahl@cib.de>2019-09-04 10:40:26 +0200
commit7992bd73a2307edce96a145e954f8e4c3ab9f57d (patch)
tree0a32009be41014940f66fca0f4f6e899f6fcbbd1
parenta9e098aa4e66c771642b26527e3e48c48c428574 (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.docxbin0 -> 34087 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport13.cxx34
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx6
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx27
-rw-r--r--writerfilter/source/dmapper/NumberingManager.cxx9
-rw-r--r--writerfilter/source/dmapper/NumberingManager.hxx5
-rw-r--r--writerfilter/source/dmapper/PropertyMap.cxx3
-rw-r--r--writerfilter/source/dmapper/PropertyMap.hxx8
-rw-r--r--writerfilter/source/dmapper/StyleSheetTable.hxx2
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
new file mode 100644
index 000000000000..3bf17f6928c1
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf95848.docx
Binary files 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