writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx | 35 ++++++++++ writerfilter/qa/cppunittests/dmapper/data/para-style-lost-numbering.docx |binary writerfilter/source/dmapper/DomainMapper_Impl.cxx | 12 +++ 3 files changed, 46 insertions(+), 1 deletion(-)
New commits: commit 8de8bf654d6a0146a7153b4b07f84167fc51a898 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Jun 17 13:27:13 2024 +0200 Commit: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> CommitDate: Thu Jun 27 16:51:44 2024 +0200 tdf#161570 DOCX import: fix lost numbering in paragraph style Regression from commit ca71482237d31703454062b8b2f544a8bacd2831 (tdf#153083 writerfilter: import locale-dependent TOC style names, 2, 2023-01-31), open the doc, apply 'Level 2 Heading' on the first para, then switch back to 'Signature' again using e.g. the sidebar, the numbering of the first paragraph is gone. This was initially a wider problem, but since commit ab1697cb4c17fd7a2fbf8d374ac95fc03b4d00be (tdf#160402 filter,writerfilter: import locale-dependent STYLEREF names, 2024-05-06), the problem only affects built-in styles. There were two remaining problems: 1) the separator for the TOC field can contain whitespace, which resulted in a style named ' Signature' and 2) the style was always cloned, even if the name was not localized. Fix the problem by first trimming the style name in DomainMapper_Impl::handleToc() and then only cloning in DomainMapper_Impl::ConvertTOCStyleName() if we see that the style name is localized. A localized style name can be observed when opening e.g. sw/qa/extras/ooxmlexport/data/custom-styles-TOC-semicolon.docx that has Intensives Zitat vs Intense Quote. One remaining question is why the numbering is lost when the cloning happens, that's not addressed here, as the cloning should not happen for this document in the first place. (cherry picked from commit 4e5dd2c0774242e44ac6edf2bd5ada220541b06b) Change-Id: Ibc2ea20cc3c9ec6bec9bdcdabce1469a0457317a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169073 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169115 Tested-by: Jenkins Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> diff --git a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx index 16aa5cbfb2df..547577e54cfd 100644 --- a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx @@ -411,6 +411,41 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlinedShapeThenSdt) CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, xPortion->getPropertyValue("TextPortionType").get<OUString>()); } + +CPPUNIT_TEST_FIXTURE(Test, testParaStyleLostNumbering) +{ + // Given a document with a first paragraph, its paragraph style has a numbering: + // When loading the document: + loadFromFile(u"para-style-lost-numbering.docx"); + + // Then make sure that the paragraph style name has no unexpected leading whitespace: + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + uno::Reference<beans::XPropertySet> xPara(xParaEnum->nextElement(), uno::UNO_QUERY); + OUString aParaStyleName; + xPara->getPropertyValue("ParaStyleName") >>= aParaStyleName; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: Signature + // - Actual : Signature + // i.e. there was an unwanted space at the start. + CPPUNIT_ASSERT_EQUAL(u"Signature"_ustr, aParaStyleName); + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent, + uno::UNO_QUERY); + // Also make sure the paragraph style has a numbering associated with it: + uno::Reference<container::XNameAccess> xStyleFamilies + = xStyleFamiliesSupplier->getStyleFamilies(); + uno::Reference<container::XNameAccess> xStyleFamily( + xStyleFamilies->getByName(u"ParagraphStyles"_ustr), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(xStyleFamily->getByName(u"Signature"_ustr), + uno::UNO_QUERY); + OUString aNumberingStyleName; + // Without the accompanying fix in place, this test would have failed, the WWNum14 list was set + // only as direct formatting, not at a style level. + xStyle->getPropertyValue("NumberingStyleName") >>= aNumberingStyleName; + CPPUNIT_ASSERT(!aNumberingStyleName.isEmpty()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/qa/cppunittests/dmapper/data/para-style-lost-numbering.docx b/writerfilter/qa/cppunittests/dmapper/data/para-style-lost-numbering.docx new file mode 100644 index 000000000000..0ab96d2a41d4 Binary files /dev/null and b/writerfilter/qa/cppunittests/dmapper/data/para-style-lost-numbering.docx differ diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 869e90a4c287..bc1eae82a01e 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -6927,7 +6927,12 @@ OUString DomainMapper_Impl::ConvertTOCStyleName(OUString const& rTOCStyleName) { // practical case: Word wrote i18n name to TOC field, but it doesn't // exist in styles.xml; tdf#153083 clone it for best roundtrip assert(convertedStyleName == pStyle->m_sConvertedStyleName); - return GetStyleSheetTable()->CloneTOCStyle(GetFontTable(), pStyle, rTOCStyleName); + if (rTOCStyleName != pStyle->m_sStyleName) + { + // rTOCStyleName is localized, pStyle->m_sStyleName is not. They don't match, so + // make sense to clone the style. + return GetStyleSheetTable()->CloneTOCStyle(GetFontTable(), pStyle, rTOCStyleName); + } } } // theoretical case: what OOXML says @@ -7124,6 +7129,11 @@ void DomainMapper_Impl::handleToc nLevel = o3tl::toInt32(o3tl::getToken(sTemplate, 0, tsep, nPosition )); if( !nLevel ) nLevel = 1; + + // The separator can be ',' or ', ': make sure the leading space doesn't end up in + // the style name. + sStyleName = sStyleName.trim(); + if( !sStyleName.isEmpty() ) aMap.emplace(nLevel, sStyleName); }