From 35fc5ef0a759884b24ed8b83cd05702a0fab64cc Mon Sep 17 00:00:00 2001 From: Justin Luth Date: Sat, 11 Apr 2020 12:05:03 +0300 Subject: tdf#131321 writerfilter: ApplyNumberingStyleNameToParaStyles() Prior to this commit, numbering on paragraph styles was lost on import. This didn't affect layout at all, but it did affect user editing. DOCX: export already was fine, just import was missing. RTF: export is explicitly ignored for non-paragraphs, (ParaNumRule_Impl), so I am ignoring RTF, since this fix is meaningless unless both import and export are working. This is a bit tricky because styles.xml is loaded before numbering.xml, so the names are not known until after numbering.xml has finished. So this helper function runs at the end of the numbering.xml import process. Several existing unit tests nicely confirmed a few things. -tdf95377.docx: numId 0 overrides an inherited numbering -chtoutline.docx proves that outlineLevel styles are exempt. -fdo61343.docx actually has nothing in numbering.xml, so it is possible to have a numbering with no name. Of course, it is a really messed up document, too... Change-Id: I270a581f08704c2595d861ce5c5b546f9d6ba6b6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92058 Tested-by: Jenkins Reviewed-by: Justin Luth Reviewed-by: Miklos Vajna --- sw/qa/extras/ooxmlexport/ooxmlexport10.cxx | 4 +++ writerfilter/source/dmapper/DomainMapper.cxx | 5 +++ writerfilter/source/dmapper/DomainMapper.hxx | 1 + writerfilter/source/dmapper/DomainMapper_Impl.cxx | 6 ++++ writerfilter/source/dmapper/DomainMapper_Impl.hxx | 1 + writerfilter/source/dmapper/NumberingManager.cxx | 1 + writerfilter/source/dmapper/StyleSheetTable.cxx | 42 +++++++++++++++++++++++ writerfilter/source/dmapper/StyleSheetTable.hxx | 1 + 8 files changed, 61 insertions(+) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx index 09a232ae5773..3e0d3752187f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx @@ -1022,6 +1022,10 @@ DECLARE_OOXMLEXPORT_TEST(testTdf95376, "tdf95376.docx") // did not have priority over indentation-from-paragraph-style, due to a // filter workaround that's not correct here. CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DEFAULT_VALUE, xParagraph->getPropertyState("ParaFirstLineIndent")); + + //tdf#131321 - paragraph styles lost their numbering. Bullet+space inherits WWNum1 from Bullet + uno::Reference xStyle(getStyles("ParagraphStyles")->getByName("Bullet+space"), uno::UNO_QUERY); + CPPUNIT_ASSERT(!(getProperty(xStyle, "NumberingStyleName")).isEmpty()); } DECLARE_OOXMLEXPORT_TEST(testTdf92124, "tdf92124.docx") diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 6eb00b1c8d29..12fa4f26090a 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -3903,6 +3903,11 @@ bool DomainMapper::IsInTable() const return m_pImpl->hasTableManager() && m_pImpl->getTableManager().isInCell(); } +OUString DomainMapper::GetListStyleName(sal_Int32 nListId) const +{ + return m_pImpl->GetListStyleName( nListId ); +} + bool DomainMapper::IsStyleSheetImport() const { return m_pImpl->IsStyleSheetImport(); diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx index 0fbd2eaf7455..6fdb44e5c9c0 100644 --- a/writerfilter/source/dmapper/DomainMapper.hxx +++ b/writerfilter/source/dmapper/DomainMapper.hxx @@ -95,6 +95,7 @@ public: void PushListProperties( const ::tools::SvRef& pListProperties ); void PopListProperties(); + OUString GetListStyleName(sal_Int32 nListId) const; bool IsOOXMLImport() const; bool IsRTFImport() const; diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 98e9e77d6c34..6428155d85ce 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -914,6 +914,12 @@ uno::Any DomainMapper_Impl::GetAnyProperty(PropertyIds eId, const PropertyMapPtr return GetPropertyFromParaStyleSheet(eId); } +OUString DomainMapper_Impl::GetListStyleName(sal_Int32 nListId) +{ + auto const pList(GetListTable()->GetList( nListId )); + return pList ? pList->GetStyleName() : OUString(); +} + ListsManager::Pointer const & DomainMapper_Impl::GetListTable() { if(!m_pListTable) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index e6654a1ce0a1..c96a68b00bbd 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -718,6 +718,7 @@ public: m_pStyleSheetTable = new StyleSheetTable( m_rDMapper, m_xTextDocument, m_bIsNewDoc ); return m_pStyleSheetTable; } + OUString GetListStyleName(sal_Int32 nListId); ListsManager::Pointer const & GetListTable(); ThemeTablePtr const & GetThemeTable() { diff --git a/writerfilter/source/dmapper/NumberingManager.cxx b/writerfilter/source/dmapper/NumberingManager.cxx index 93ba4859ba6b..e0922b41a7af 100644 --- a/writerfilter/source/dmapper/NumberingManager.cxx +++ b/writerfilter/source/dmapper/NumberingManager.cxx @@ -1221,6 +1221,7 @@ void ListsManager::CreateNumberingRules( ) { rList->CreateNumberingRules( m_rDMapper, m_xFactory ); } + m_rDMapper.GetStyleSheetTable()->ApplyNumberingStyleNameToParaStyles(); } } diff --git a/writerfilter/source/dmapper/StyleSheetTable.cxx b/writerfilter/source/dmapper/StyleSheetTable.cxx index 864149a66cb4..f0524e71ed32 100644 --- a/writerfilter/source/dmapper/StyleSheetTable.cxx +++ b/writerfilter/source/dmapper/StyleSheetTable.cxx @@ -887,6 +887,48 @@ uno::Sequence< OUString > PropValVector::getNames() return comphelper::containerToSequence(aRet); } +void StyleSheetTable::ApplyNumberingStyleNameToParaStyles() +{ + try + { + uno::Reference< style::XStyleFamiliesSupplier > xStylesSupplier( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW ); + uno::Reference< lang::XMultiServiceFactory > xDocFactory( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW ); + uno::Reference< container::XNameAccess > xStyleFamilies = xStylesSupplier->getStyleFamilies(); + uno::Reference xParaStyles; + xStyleFamilies->getByName(getPropertyName( PROP_PARAGRAPH_STYLES )) >>= xParaStyles; + + if ( !xParaStyles.is() ) + return; + + for ( auto& pEntry : m_pImpl->m_aStyleSheetEntries ) + { + StyleSheetPropertyMap* pStyleSheetProperties = nullptr; + if ( pEntry->nStyleTypeCode == STYLE_TYPE_PARA && (pStyleSheetProperties = dynamic_cast(pEntry->pProperties.get())) ) + { + // ListId 0 means turn off numbering - to cancel inheritance - so make sure that can be set. + // Ignore the special "chapter numbering" outline styles as they are handled internally. + if ( pStyleSheetProperties->GetListId() > -1 && pStyleSheetProperties->GetOutlineLevel() == -1 ) + { + uno::Reference< style::XStyle > xStyle; + xParaStyles->getByName( ConvertStyleName(pEntry->sStyleName) ) >>= xStyle; + + if ( !xStyle.is() ) + break; + + uno::Reference xPropertySet( xStyle, uno::UNO_QUERY_THROW ); + const OUString sNumberingStyleName = m_pImpl->m_rDMapper.GetListStyleName( pStyleSheetProperties->GetListId() ); + if ( !sNumberingStyleName.isEmpty() || !pStyleSheetProperties->GetListId() ) + xPropertySet->setPropertyValue( getPropertyName(PROP_NUMBERING_STYLE_NAME), uno::makeAny(sNumberingStyleName) ); + } + } + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("writerfilter", "Failed applying numbering style name to Paragraph styles"); + } +} + void StyleSheetTable::ApplyStyleSheets( const FontTablePtr& rFontTable ) { try diff --git a/writerfilter/source/dmapper/StyleSheetTable.hxx b/writerfilter/source/dmapper/StyleSheetTable.hxx index c192449eb388..a2062303f7d7 100644 --- a/writerfilter/source/dmapper/StyleSheetTable.hxx +++ b/writerfilter/source/dmapper/StyleSheetTable.hxx @@ -92,6 +92,7 @@ public: StyleSheetTable(DomainMapper& rDMapper, css::uno::Reference const& xTextDocument, bool bIsNewDoc); virtual ~StyleSheetTable() override; + void ApplyNumberingStyleNameToParaStyles(); void ApplyStyleSheets( const FontTablePtr& rFontTable ); StyleSheetEntryPtr FindStyleSheetByISTD(const OUString& sIndex); StyleSheetEntryPtr FindStyleSheetByConvertedStyleName(const OUString& rIndex); -- cgit v1.2.3