sw/inc/SwStyleNameMapper.hxx | 2 - sw/qa/extras/layout/layout3.cxx | 2 - sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 4 +-- sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 2 - sw/qa/extras/rtfexport/rtfexport4.cxx | 3 -- sw/qa/extras/uiwriter/uiwriter2.cxx | 3 -- sw/source/core/doc/SwStyleNameMapper.cxx | 31 +++++++++++++++++++------ sw/source/core/unocore/unostyle.cxx | 37 +++++++++++++++++++----------- 8 files changed, 55 insertions(+), 29 deletions(-)
New commits: commit bd727654ec8cc339292072b42073e57d566cc220 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Thu Dec 5 12:22:14 2024 +0100 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Fri Dec 6 14:24:32 2024 +0100 tdf#159549 sw: fix ODF import of newly colliding Body Text styles Commit c83d241effbd09491e9f96d3e435ab91700f58b0 "tdf#154933 Rename "Text Body" para style to "Body Text"" introduced a regression when importing certain ODF documents, but the problem is actually pre-existing. What happens is that first the built-in "Text body" style is created, and then a non-built-in style with the same translated name as "Text body" is imported, and instead of creating a new style, the built-in one is found and used, and so its properties are overwritten. The root cause is that SwStyleNameMapper::FillProgName() and in particular SwStyleNameMapper::FillUIName() are defined poorly, ever since they were introduced in 2001 in commit 4fbc9dd48b7cebb304010e7337b1bbc3936c7923 It becomes obvious relatively quickly that the way style names work is that at the UNO API level, the "ProgName" (internal, non-localised) names are used, and at the core document level, the "UIName" (localised) names are used. This is in itself questionable - why is the translation from ProgName to UIName not done in the UI? - but also very expensive to change now. So then the UNO services are responsible for translating between ProgName and UIName. But the 2 functions don't do that properly; both need to check if the given name is a known ProgName *or* a known UIName, and rename it in case it collides with a known target name; also the 2 functions need to cancel each other out, not add " (user)" at the end in both directions. Fixing this causes numerous tests to fail, due to: 1. the UNO services calling themselves with already converted style names, which are then translated a second time, which fails now. (or calling the wrong function like SwXStyleFamily::getByIndex()) 2. many tests call the UNO API with UINames instead of ProgNames 3. somehow the writerfilter import is also changed, causing failures in e.g. testTdf113182 and testTdf104492 4. buggy code elsewhere (lcl_getUsedPageStyles()), problem similar to 1., for PageDescs 5. potentially more buggy code yet to be discovered (definitely table styles, forgot which test that was) So limit this fix for now to only paragraph styles, and don't do it in writerfilter import, now at least sw.check passes. Change-Id: I5cbdf3e174622e83f9af8787c3671b88c0e37bac Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177858 Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de> Tested-by: Jenkins diff --git a/sw/inc/SwStyleNameMapper.hxx b/sw/inc/SwStyleNameMapper.hxx index 0fdfb381711a..4a3b0f1a582b 100644 --- a/sw/inc/SwStyleNameMapper.hxx +++ b/sw/inc/SwStyleNameMapper.hxx @@ -89,7 +89,7 @@ public: // This gets the UI Name from the programmatic name static const OUString& GetUIName(const OUString& rName, SwGetPoolIdFromName); static void FillUIName(const OUString& rName, OUString& rFillName, - SwGetPoolIdFromName); + SwGetPoolIdFromName, bool bBugfix = false); // Get the programmatic Name from the UI name static const OUString& GetProgName(const OUString& rName, diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx index ef5e948d5abf..af6dac583f29 100644 --- a/sw/qa/extras/layout/layout3.cxx +++ b/sw/qa/extras/layout/layout3.cxx @@ -794,7 +794,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf155177) createSwDoc("tdf155177-1-min.odt"); uno::Reference<beans::XPropertySet> xStyle( - getStyles(u"ParagraphStyles"_ustr)->getByName(u"Body Text"_ustr), uno::UNO_QUERY_THROW); + getStyles(u"ParagraphStyles"_ustr)->getByName(u"Text body"_ustr), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(sal_Int32(210), getProperty<sal_Int32>(xStyle, u"ParaTopMargin"_ustr)); { diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index bf12d0178b62..c3e18bfbae48 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -481,7 +481,7 @@ DECLARE_OOXMLEXPORT_TEST(testKern, "kern.docx") // This failed: kerning was also enabled for the second paragraph. CPPUNIT_ASSERT(!getProperty<bool>(getRun(getParagraph(2), 1), u"CharAutoKerning"_ustr)); - uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Default Paragraph Style"_ustr), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); //tdf107801: kerning normally isn't enabled by default for .docx CPPUNIT_ASSERT_EQUAL_MESSAGE("AutoKern should be false", false, getProperty<bool>(xStyle, u"CharAutoKerning"_ustr)); } @@ -491,7 +491,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf89377, "tdf89377_tableWithBreakBeforeParaStyle.d // the paragraph style should set table's text-flow break-before-page CPPUNIT_ASSERT_EQUAL( 3, getPages() ); - uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Default Paragraph Style"_ustr), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); //tdf107801: kerning info wasn't exported previously. CPPUNIT_ASSERT_EQUAL_MESSAGE("AutoKern should be true", true, getProperty<bool>(xStyle, u"CharAutoKerning"_ustr)); } diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index a30a29d397d7..13490dff0ffe 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -734,7 +734,7 @@ CPPUNIT_TEST_FIXTURE(Test, testN820504) uno::Reference<style::XStyleFamiliesSupplier> xFamiliesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference<container::XNameAccess> xFamiliesAccess = xFamiliesSupplier->getStyleFamilies(); uno::Reference<container::XNameAccess> xStylesAccess(xFamiliesAccess->getByName(u"ParagraphStyles"_ustr), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xStyle(xStylesAccess->getByName(u"Default Paragraph Style"_ustr), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(xStylesAccess->getByName(u"Standard"_ustr), uno::UNO_QUERY); // The problem was that the CharColor was set to AUTO (-1) even if we have some default char color set CPPUNIT_ASSERT_EQUAL(Color(0x3da7bb), getProperty<Color>(xStyle, u"CharColor"_ustr)); diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx b/sw/qa/extras/rtfexport/rtfexport4.cxx index 29e3d4201860..adc6c8d0aa89 100644 --- a/sw/qa/extras/rtfexport/rtfexport4.cxx +++ b/sw/qa/extras/rtfexport/rtfexport4.cxx @@ -681,8 +681,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf136587_noStyleName) getProperty<sal_Int16>(xStyleProps, u"ParaAdjust"_ustr)); // The problem was that the default style wasn't imported at all, so the fontsize was only 12. - xStyleProps.set(paragraphStyles->getByName(u"Default Paragraph Style"_ustr), - uno::UNO_QUERY_THROW); + xStyleProps.set(paragraphStyles->getByName(u"Standard"_ustr), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(32.0f, getProperty<float>(xStyleProps, u"CharHeight"_ustr)); }; createSwDoc("tdf136587_noStyleName.rtf"); diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 59320a62709d..b70fea7ce62a 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -2578,8 +2578,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRTLparaStyle_LocaleArabic) saveAndReload(u"Office Open XML Text"_ustr); uno::Reference<beans::XPropertySet> xPageStyle( - getStyles(u"ParagraphStyles"_ustr)->getByName(u"Default Paragraph Style"_ustr), - uno::UNO_QUERY_THROW); + getStyles(u"ParagraphStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY_THROW); // Test the text Direction value for the -none- based paragraph styles CPPUNIT_ASSERT_EQUAL_MESSAGE("RTL Writing Mode", sal_Int32(1), getProperty<sal_Int32>(xPageStyle, u"WritingMode"_ustr)); diff --git a/sw/source/core/doc/SwStyleNameMapper.cxx b/sw/source/core/doc/SwStyleNameMapper.cxx index b047782a4221..554ab750fe49 100644 --- a/sw/source/core/doc/SwStyleNameMapper.cxx +++ b/sw/source/core/doc/SwStyleNameMapper.cxx @@ -263,10 +263,18 @@ void SwStyleNameMapper::FillProgName( rFillName = rName; if (nId == USHRT_MAX ) { - // It isn't ...make sure the suffix isn't already " (user)"...if it is, - // we need to add another one - if (lcl_SuffixIsUser(rFillName)) - rFillName += " (user)"; + if (eFlags == SwGetPoolIdFromName::TxtColl) + { + // check if it has a " (user)" suffix, if so remove it + lcl_CheckSuffixAndDelete(rFillName); + } + else // FIXME don't do this + { + // It isn't ...make sure the suffix isn't already " (user)"...if it is, + // we need to add another one + if (lcl_SuffixIsUser(rFillName)) + rFillName += " (user)"; + } } else { @@ -287,7 +295,7 @@ void SwStyleNameMapper::FillProgName( // Get the UI name from the programmatic name in rName and put it into rFillName void SwStyleNameMapper::FillUIName( const OUString& rName, OUString& rFillName, - SwGetPoolIdFromName const eFlags) + SwGetPoolIdFromName const eFlags, bool const bBugfix) { OUString aName = rName; if (eFlags == SwGetPoolIdFromName::ChrFmt && rName == "Standard") @@ -297,8 +305,17 @@ void SwStyleNameMapper::FillUIName( if ( nId == USHRT_MAX ) { rFillName = aName; - // aName isn't in our Prog name table...check if it has a " (user)" suffix, if so remove it - lcl_CheckSuffixAndDelete ( rFillName ); + if (eFlags != SwGetPoolIdFromName::TxtColl || // FIXME do it for all ids + !bBugfix || // TODO why does it change DOCX imports + GetPoolIdFromUIName(aName, eFlags) == USHRT_MAX) + { + // aName isn't in our Prog name table...check if it has a " (user)" suffix, if so remove it + lcl_CheckSuffixAndDelete(rFillName); + } + else + { + rFillName += " (user)"; + } } else { diff --git a/sw/source/core/unocore/unostyle.cxx b/sw/source/core/unocore/unostyle.cxx index 2dfb37aa7a12..67facb9fcf58 100644 --- a/sw/source/core/unocore/unostyle.cxx +++ b/sw/source/core/unocore/unostyle.cxx @@ -915,7 +915,7 @@ uno::Any SwXStyleFamily::getByIndex(sal_Int32 nIndex) OUString sStyleName; try { - SwStyleNameMapper::FillUIName(m_rEntry.translateIndex(nIndex), sStyleName); + SwStyleNameMapper::FillProgName(m_rEntry.translateIndex(nIndex), sStyleName); } catch(...) {} if (sStyleName.isEmpty()) GetCountOrName(&sStyleName, nIndex); @@ -957,7 +957,8 @@ rtl::Reference<SwXBaseStyle> SwXStyleFamily::getStyleByName(const OUString& rNam { SolarMutexGuard aGuard; OUString sStyleName; - SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(), + m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport()); if(!m_pBasePool) throw uno::RuntimeException(); SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, m_rEntry.family()); @@ -1012,7 +1013,8 @@ sal_Bool SwXStyleFamily::hasByName(const OUString& rName) if(!m_pBasePool) throw uno::RuntimeException(); OUString sStyleName; - SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(), + m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport()); SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, m_rEntry.family()); return nullptr != pBase; } @@ -1023,7 +1025,8 @@ void SwXStyleFamily::insertStyleByName(const OUString& rName, const rtl::Referen if(!m_pBasePool) throw uno::RuntimeException(); OUString sStyleName; - SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(), + m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport()); SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, m_rEntry.family()); if (pBase) throw container::ElementExistException(); @@ -1036,7 +1039,8 @@ void SwXStyleFamily::insertByName(const OUString& rName, const uno::Any& rElemen if(!m_pBasePool) throw uno::RuntimeException(); OUString sStyleName; - SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(), + m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport()); SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, m_rEntry.family()); if (pBase) throw container::ElementExistException(); @@ -1099,7 +1103,8 @@ void SwXStyleFamily::replaceByName(const OUString& rName, const uno::Any& rEleme if(!m_pBasePool) throw uno::RuntimeException(); OUString sStyleName; - SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(), + m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport()); SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, m_rEntry.family()); // replacements only for userdefined styles if(!pBase) @@ -1160,7 +1165,8 @@ void SwXStyleFamily::removeByName(const OUString& rName) if(!m_pBasePool) throw uno::RuntimeException(); OUString sName; - SwStyleNameMapper::FillUIName(rName, sName, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(rName, sName, m_rEntry.poolId(), + m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport()); SfxStyleSheetBase* pBase = m_pBasePool->Find(sName, m_rEntry.family()); if(!pBase) throw container::NoSuchElementException(); @@ -1447,7 +1453,8 @@ void SwXStyle::setParentStyle(const OUString& rParentStyle) { SolarMutexGuard aGuard; OUString sParentStyle; - SwStyleNameMapper::FillUIName(rParentStyle, sParentStyle, lcl_GetSwEnumFromSfxEnum ( m_rEntry.family()) ); + SwStyleNameMapper::FillUIName(rParentStyle, sParentStyle, lcl_GetSwEnumFromSfxEnum ( m_rEntry.family()), + m_pDoc && !m_pDoc->IsInWriterfilterImport()); if(!m_pBasePool) { if(!m_bIsDescriptor) @@ -1455,7 +1462,7 @@ void SwXStyle::setParentStyle(const OUString& rParentStyle) m_sParentStyleName = sParentStyle; try { - const auto aAny = m_xStyleFamily->getByName(sParentStyle); + const auto aAny = m_xStyleFamily->getByName(rParentStyle); m_xStyleData = aAny.get<decltype(m_xStyleData)>(); } catch(...) @@ -1753,7 +1760,8 @@ void SwXStyle::SetPropertyValue<FN_UNO_FOLLOW_STYLE>(const SfxItemPropertyMapEnt return; const auto sValue(rValue.get<OUString>()); OUString aString; - SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId(), + m_pDoc && !m_pDoc->IsInWriterfilterImport()); o_rStyleBase.getNewBase()->SetFollow(aString); } @@ -1767,7 +1775,8 @@ void SwXStyle::SetPropertyValue<FN_UNO_LINK_STYLE>(const SfxItemPropertyMapEntry return; const auto sValue(rValue.get<OUString>()); OUString aString; - SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId()); + SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId(), + m_pDoc && !m_pDoc->IsInWriterfilterImport()); o_rStyleBase.getNewBase()->SetLink(aString); } @@ -1849,7 +1858,8 @@ void SwXStyle::SetPropertyValue<FN_UNO_PARA_STYLE_CONDITIONS>(const SfxItemPrope const OUString sValue(rNamedValue.Value.get<OUString>()); // get UI style name from programmatic style name OUString aStyleName; - SwStyleNameMapper::FillUIName(sValue, aStyleName, lcl_GetSwEnumFromSfxEnum(m_rEntry.family())); + SwStyleNameMapper::FillUIName(sValue, aStyleName, lcl_GetSwEnumFromSfxEnum(m_rEntry.family()), + m_pDoc && !m_pDoc->IsInWriterfilterImport()); // check for correct context and style name const auto nIdx(GetCommandContextIndex(rNamedValue.Name)); @@ -1893,7 +1903,8 @@ void SwXStyle::SetPropertyValue<SID_SWREGISTER_COLLECTION>(const SfxItemProperty aReg.SetWhich(SID_SWREGISTER_MODE); o_rStyleBase.GetItemSet().Put(aReg); OUString aString; - SwStyleNameMapper::FillUIName(sName, aString, SwGetPoolIdFromName::TxtColl); + SwStyleNameMapper::FillUIName(sName, aString, SwGetPoolIdFromName::TxtColl, + m_pDoc && !m_pDoc->IsInWriterfilterImport()); o_rStyleBase.GetItemSet().Put(SfxStringItem(SID_SWREGISTER_COLLECTION, aString ) ); } template<>