sw/inc/charfmt.hxx | 6 ++ sw/inc/cmdid.h | 1 sw/inc/docstyle.hxx | 3 + sw/inc/fmtcol.hxx | 6 ++ sw/inc/unoprnms.hxx | 1 sw/qa/core/unocore/unocore.cxx | 24 ++++++++++ sw/source/core/doc/fmtcol.cxx | 14 ++++++ sw/source/core/txtnode/chrfmt.cxx | 11 ++++ sw/source/core/unocore/unomap1.cxx | 1 sw/source/core/unocore/unomapproperties.hxx | 1 sw/source/core/unocore/unostyle.cxx | 36 +++++++++++++++- sw/source/uibase/app/docstyle.cxx | 63 ++++++++++++++++++++++++++++ 12 files changed, 165 insertions(+), 2 deletions(-)
New commits: commit e3227975c0f42ff23d528f5ab94b4538c8af764c Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Sep 24 16:01:12 2021 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Sep 24 19:57:47 2021 +0200 sw: paragraph styles: add doc model & UNO API for a linked character style And the same in the other direction: link a para style from a char style. Towards getting this info out of the grab-bag, so we can store it also in ODF, as currently this is only kept for DOCX -> DOCX conversions, via the style grab-bags. Change-Id: I21691dafce0bc216d041fc8ecb16b162d293739e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122595 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/inc/charfmt.hxx b/sw/inc/charfmt.hxx index bef023c9079a..45b03fc701fa 100644 --- a/sw/inc/charfmt.hxx +++ b/sw/inc/charfmt.hxx @@ -28,6 +28,8 @@ class SwCharFormat final : public SwFormat friend class SwDoc; friend class SwTextFormatColl; + SwTextFormatColl* mpLinkedParaFormat = nullptr; + SwCharFormat( SwAttrPool& rPool, const OUString &rFormatName, SwCharFormat *pDerivedFrom ) : SwFormat( rPool, rFormatName, aCharFormatSetRange, pDerivedFrom, RES_CHRFMT ) @@ -36,6 +38,10 @@ class SwCharFormat final : public SwFormat public: void dumpAsXml(xmlTextWriterPtr pWriter) const; + + void SetLinkedParaFormat(SwTextFormatColl& rLink); + + const SwTextFormatColl* GetLinkedParaFormat() const; }; namespace CharFormat diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h index 79b6ffc392ba..342f41cb949a 100644 --- a/sw/inc/cmdid.h +++ b/sw/inc/cmdid.h @@ -584,6 +584,7 @@ #define FN_INSERT_GLOSSARY (FN_EXTRA2 + 89) #define FN_NEW_GLOSSARY (FN_EXTRA2 + 90) #define FN_SET_ACT_GLOSSARY (FN_EXTRA2 + 91) +#define FN_UNO_LINK_STYLE (FN_EXTRA2 + 92) #define FN_UNO_CHARFMT_SEQUENCE (FN_EXTRA2 + 94) #define FN_UNO_CLSID (FN_EXTRA2 + 95) diff --git a/sw/inc/docstyle.hxx b/sw/inc/docstyle.hxx index 025bcc436413..1bc87e71c129 100644 --- a/sw/inc/docstyle.hxx +++ b/sw/inc/docstyle.hxx @@ -60,6 +60,7 @@ class SW_DLLPUBLIC SwDocStyleSheet final : public SfxStyleSheetBase SfxItemSet m_aCoreSet; bool m_bPhysical; + OUString m_aLink; /// Make empty shell a real StyleSheet (Core). SAL_DLLPRIVATE void Create(); @@ -109,6 +110,7 @@ public: void MergeIndentAttrsOfListStyle( SfxItemSet& rSet ); virtual const OUString& GetParent() const override; virtual const OUString& GetFollow() const override; + const OUString& GetLink() const; virtual sal_uLong GetHelpId( OUString& rFile ) override; virtual void SetHelpId( const OUString& r, sal_uLong nId ) override; @@ -123,6 +125,7 @@ public: virtual bool SetName(const OUString& rNewName, bool bReindexNow = true) override; virtual bool SetParent( const OUString& rStr) override; virtual bool SetFollow( const OUString& rStr) override; + void SetLink(const OUString& rStr); virtual bool HasFollowSupport() const override; virtual bool HasParentSupport() const override; diff --git a/sw/inc/fmtcol.hxx b/sw/inc/fmtcol.hxx index 17437a0d90eb..1b1bd7d2e46d 100644 --- a/sw/inc/fmtcol.hxx +++ b/sw/inc/fmtcol.hxx @@ -70,6 +70,8 @@ class SW_DLLPUBLIC SwTextFormatColl SwTextFormatColl *mpNextTextFormatColl; + SwCharFormat* mpLinkedCharFormat = nullptr; + protected: SwTextFormatColl( SwAttrPool& rPool, const char* pFormatCollName, SwTextFormatColl* pDerFrom = nullptr, @@ -101,6 +103,10 @@ public: inline void SetNextTextFormatColl(SwTextFormatColl& rNext); SwTextFormatColl& GetNextTextFormatColl() const { return *mpNextTextFormatColl; } + void SetLinkedCharFormat(SwCharFormat& rLink); + + const SwCharFormat* GetLinkedCharFormat() const; + bool IsAtDocNodeSet() const; void SetAttrOutlineLevel( int ); diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index a6fe2dba18df..a823d381e607 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -23,6 +23,7 @@ #include <sal/config.h> #define UNO_NAME_FOLLOW_STYLE "FollowStyle" +#define UNO_NAME_LINK_STYLE "LinkStyle" #define UNO_NAME_IS_PHYSICAL "IsPhysical" #define UNO_NAME_IS_AUTO_UPDATE "IsAutoUpdate" #define UNO_NAME_DISPLAY_NAME "DisplayName" diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index a1f74d46f5a6..36007fc7cd26 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -134,6 +134,30 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testBiblioLocalCopy) CPPUNIT_ASSERT_EQUAL(OUString("file:///home/me/test.pdf"), aActual); } +CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testLinkedStyles) +{ + // Given an empty document: + createSwDoc(); + + // When defining a linked style for a para style: + uno::Reference<container::XNameAccess> xParaStyles = getStyles("ParagraphStyles"); + uno::Reference<beans::XPropertySet> xParaStyle(xParaStyles->getByName("Caption"), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString(), getProperty<OUString>(xParaStyle, "LinkStyle")); + xParaStyle->setPropertyValue("LinkStyle", uno::makeAny(OUString("Emphasis"))); + // Then make sure we get the linked char style back: + CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xParaStyle, "LinkStyle")); + + // When defining a linked style for a char style: + uno::Reference<container::XNameAccess> xCharStyles = getStyles("CharacterStyles"); + uno::Reference<beans::XPropertySet> xCharStyle(xCharStyles->getByName("Emphasis"), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString(), getProperty<OUString>(xCharStyle, "LinkStyle")); + xCharStyle->setPropertyValue("LinkStyle", uno::makeAny(OUString("Caption"))); + // Then make sure we get the linked para style back: + CPPUNIT_ASSERT_EQUAL(OUString("Caption"), getProperty<OUString>(xCharStyle, "LinkStyle")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/fmtcol.cxx b/sw/source/core/doc/fmtcol.cxx index bf7a8f02f78d..e35e523b6a92 100644 --- a/sw/source/core/doc/fmtcol.cxx +++ b/sw/source/core/doc/fmtcol.cxx @@ -325,6 +325,10 @@ void SwTextFormatColl::SwClientNotify(const SwModify& rModify, const SfxHint& rH SwFormatColl::SwClientNotify(rModify, rHint); } +void SwTextFormatColl::SetLinkedCharFormat(SwCharFormat& rLink) { mpLinkedCharFormat = &rLink; } + +const SwCharFormat* SwTextFormatColl::GetLinkedCharFormat() const { return mpLinkedCharFormat; } + bool SwTextFormatColl::IsAtDocNodeSet() const { SwIterator<SwContentNode,SwFormatColl> aIter( *this ); @@ -475,6 +479,16 @@ void SwTextFormatColl::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr())); + if (mpNextTextFormatColl) + { + (void)xmlTextWriterWriteAttribute( + pWriter, BAD_CAST("next"), BAD_CAST(mpNextTextFormatColl->GetName().toUtf8().getStr())); + } + if (mpLinkedCharFormat) + { + (void)xmlTextWriterWriteAttribute( + pWriter, BAD_CAST("linked"), BAD_CAST(mpLinkedCharFormat->GetName().toUtf8().getStr())); + } GetAttrSet().dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } diff --git a/sw/source/core/txtnode/chrfmt.cxx b/sw/source/core/txtnode/chrfmt.cxx index ddae28a9b3ab..d2e01640071d 100644 --- a/sw/source/core/txtnode/chrfmt.cxx +++ b/sw/source/core/txtnode/chrfmt.cxx @@ -27,10 +27,21 @@ void SwCharFormat::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwCharFormat")); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr())); + + if (mpLinkedParaFormat) + { + (void)xmlTextWriterWriteAttribute( + pWriter, BAD_CAST("linked"), BAD_CAST(mpLinkedParaFormat->GetName().toUtf8().getStr())); + } + GetAttrSet().dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } +void SwCharFormat::SetLinkedParaFormat(SwTextFormatColl& rLink) { mpLinkedParaFormat = &rLink; } + +const SwTextFormatColl* SwCharFormat::GetLinkedParaFormat() const { return mpLinkedParaFormat; } + void SwCharFormats::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwCharFormats")); diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx index ee7b116d9716..34824a7cff32 100644 --- a/sw/source/core/unocore/unomap1.cxx +++ b/sw/source/core/unocore/unomap1.cxx @@ -233,6 +233,7 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetCharStylePropertyMa { u"" UNO_NAME_CHAR_TOP_BORDER_DISTANCE, RES_CHRATR_BOX, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE, TOP_BORDER_DISTANCE |CONVERT_TWIPS }, { u"" UNO_NAME_CHAR_BOTTOM_BORDER_DISTANCE, RES_CHRATR_BOX, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS }, { u"" UNO_NAME_CHAR_SHADOW_FORMAT, RES_CHRATR_SHADOW, cppu::UnoType<css::table::ShadowFormat>::get(), PROPERTY_NONE, CONVERT_TWIPS}, + { u"" UNO_NAME_LINK_STYLE, FN_UNO_LINK_STYLE, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0}, { u"", 0, css::uno::Type(), 0, 0 } }; diff --git a/sw/source/core/unocore/unomapproperties.hxx b/sw/source/core/unocore/unomapproperties.hxx index 1830ca2691de..1deefac3f660 100644 --- a/sw/source/core/unocore/unomapproperties.hxx +++ b/sw/source/core/unocore/unomapproperties.hxx @@ -455,6 +455,7 @@ { u"" UNO_NAME_CHAR_RELIEF, RES_CHRATR_RELIEF, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, MID_RELIEF },\ PROP_DIFF_FONTHEIGHT\ { u"" UNO_NAME_FOLLOW_STYLE, FN_UNO_FOLLOW_STYLE, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0},\ + { u"" UNO_NAME_LINK_STYLE, FN_UNO_LINK_STYLE, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0},\ { u"" UNO_NAME_IS_PHYSICAL, FN_UNO_IS_PHYSICAL, cppu::UnoType<bool>::get(), PropertyAttribute::READONLY, 0},\ { u"" UNO_NAME_IS_AUTO_UPDATE, FN_UNO_IS_AUTO_UPDATE, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0},\ { u"" UNO_NAME_DISPLAY_NAME, FN_UNO_DISPLAY_NAME, cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0},\ diff --git a/sw/source/core/unocore/unostyle.cxx b/sw/source/core/unocore/unostyle.cxx index 48510356b54c..a7ab270c6eb3 100644 --- a/sw/source/core/unocore/unostyle.cxx +++ b/sw/source/core/unocore/unostyle.cxx @@ -1789,6 +1789,21 @@ void SwXStyle::SetPropertyValue<FN_UNO_FOLLOW_STYLE>(const SfxItemPropertyMapEnt SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.m_aPoolId); o_rStyleBase.getNewBase()->SetFollow(aString); } + +template <> +void SwXStyle::SetPropertyValue<FN_UNO_LINK_STYLE>(const SfxItemPropertyMapEntry&, + const SfxItemPropertySet&, + const uno::Any& rValue, + SwStyleBase_Impl& o_rStyleBase) +{ + if (!rValue.has<OUString>()) + return; + const auto sValue(rValue.get<OUString>()); + OUString aString; + SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.m_aPoolId); + o_rStyleBase.getNewBase()->SetLink(aString); +} + template<> void SwXStyle::SetPropertyValue<sal_uInt16(RES_PAGEDESC)>(const SfxItemPropertyMapEntry& rEntry, const SfxItemPropertySet& rPropSet, const uno::Any& rValue, SwStyleBase_Impl& o_rStyleBase) { @@ -2013,6 +2028,7 @@ void SwXStyle::SetStyleProperty(const SfxItemPropertyMapEntry& rEntry, const Sfx { FN_UNO_NUM_RULES, std::mem_fn(&SwXStyle::SetPropertyValue<FN_UNO_NUM_RULES>) }, { RES_PARATR_OUTLINELEVEL, std::mem_fn(&SwXStyle::SetPropertyValue<sal_uInt16(RES_PARATR_OUTLINELEVEL)>) }, { FN_UNO_FOLLOW_STYLE, std::mem_fn(&SwXStyle::SetPropertyValue<FN_UNO_FOLLOW_STYLE>) }, + { FN_UNO_LINK_STYLE, std::mem_fn(&SwXStyle::SetPropertyValue<FN_UNO_LINK_STYLE>) }, { RES_PAGEDESC, std::mem_fn(&SwXStyle::SetPropertyValue<sal_uInt16(RES_PAGEDESC)>) }, { RES_TEXT_VERT_ADJUST, std::mem_fn(&SwXStyle::SetPropertyValue<sal_uInt16(RES_TEXT_VERT_ADJUST)>) }, { FN_UNO_IS_AUTO_UPDATE, std::mem_fn(&SwXStyle::SetPropertyValue<FN_UNO_IS_AUTO_UPDATE>) }, @@ -2187,6 +2203,19 @@ uno::Any SwXStyle::GetStyleProperty<FN_UNO_FOLLOW_STYLE>(const SfxItemPropertyMa SwStyleNameMapper::FillProgName(rBase.getNewBase()->GetFollow(), aString, lcl_GetSwEnumFromSfxEnum(GetFamily())); return uno::makeAny(aString); } + +template <> +uno::Any SwXStyle::GetStyleProperty<FN_UNO_LINK_STYLE>(const SfxItemPropertyMapEntry&, + const SfxItemPropertySet&, + SwStyleBase_Impl& rBase) +{ + PrepareStyleBase(rBase); + OUString aString; + SwStyleNameMapper::FillProgName(rBase.getNewBase()->GetLink(), aString, + lcl_GetSwEnumFromSfxEnum(GetFamily())); + return uno::makeAny(aString); +} + template<> uno::Any SwXStyle::GetStyleProperty<sal_uInt16(RES_PAGEDESC)>(const SfxItemPropertyMapEntry& rEntry, const SfxItemPropertySet& rPropSet, SwStyleBase_Impl& rBase) { @@ -2348,6 +2377,7 @@ uno::Any SwXStyle::GetStyleProperty_Impl(const SfxItemPropertyMapEntry& rEntry, { FN_UNO_NUM_RULES, std::mem_fn(&SwXStyle::GetStyleProperty<FN_UNO_NUM_RULES>) }, { RES_PARATR_OUTLINELEVEL, std::mem_fn(&SwXStyle::GetStyleProperty<sal_uInt16(RES_PARATR_OUTLINELEVEL)>) }, { FN_UNO_FOLLOW_STYLE, std::mem_fn(&SwXStyle::GetStyleProperty<FN_UNO_FOLLOW_STYLE>) }, + { FN_UNO_LINK_STYLE, std::mem_fn(&SwXStyle::GetStyleProperty<FN_UNO_LINK_STYLE>) }, { RES_PAGEDESC, std::mem_fn(&SwXStyle::GetStyleProperty<sal_uInt16(RES_PAGEDESC)>) }, { FN_UNO_IS_AUTO_UPDATE, std::mem_fn(&SwXStyle::GetStyleProperty<FN_UNO_IS_AUTO_UPDATE>) }, { FN_UNO_DISPLAY_NAME, std::mem_fn(&SwXStyle::GetStyleProperty<FN_UNO_DISPLAY_NAME>) }, @@ -2512,7 +2542,8 @@ uno::Sequence<beans::PropertyState> SwXStyle::getPropertyStates(const uno::Seque if(!pEntry) throw beans::UnknownPropertyException("Unknown property: " + sPropName, static_cast<cppu::OWeakObject*>(this)); - if(FN_UNO_NUM_RULES == pEntry->nWID || FN_UNO_FOLLOW_STYLE == pEntry->nWID) + if (FN_UNO_NUM_RULES == pEntry->nWID || FN_UNO_FOLLOW_STYLE == pEntry->nWID + || pEntry->nWID == FN_UNO_LINK_STYLE) { // handle NumRules first, done pStates[i] = beans::PropertyState_DIRECT_VALUE; @@ -2625,7 +2656,8 @@ void SAL_CALL SwXStyle::setPropertiesToDefault(const uno::Sequence<OUString>& aP const SfxItemPropertyMapEntry* pEntry = rMap.getByName(rName); if(!pEntry) throw beans::UnknownPropertyException("Unknown property: " + rName, static_cast<cppu::OWeakObject*>(this)); - if(pEntry->nWID == FN_UNO_FOLLOW_STYLE || pEntry->nWID == FN_UNO_NUM_RULES) + if (pEntry->nWID == FN_UNO_FOLLOW_STYLE || pEntry->nWID == FN_UNO_LINK_STYLE + || pEntry->nWID == FN_UNO_NUM_RULES) throw uno::RuntimeException("Cannot reset: " + rName, static_cast<cppu::OWeakObject*>(this)); if(pEntry->nFlags & beans::PropertyAttribute::READONLY) throw uno::RuntimeException("setPropertiesToDefault: property is read-only: " + rName, static_cast<cppu::OWeakObject*>(this)); diff --git a/sw/source/uibase/app/docstyle.cxx b/sw/source/uibase/app/docstyle.cxx index ae896be9a608..eafb1f159b46 100644 --- a/sw/source/uibase/app/docstyle.cxx +++ b/sw/source/uibase/app/docstyle.cxx @@ -733,6 +733,51 @@ const OUString& SwDocStyleSheet::GetFollow() const return aFollow; } +void SwDocStyleSheet::SetLink(const OUString& rStr) +{ + SwImplShellAction aTmpSh(m_rDoc); + switch (nFamily) + { + case SfxStyleFamily::Para: + { + if (m_pColl) + { + SwCharFormat* pLink = lcl_FindCharFormat(m_rDoc, rStr); + if (pLink) + { + m_pColl->SetLinkedCharFormat(*pLink); + } + } + break; + } + case SfxStyleFamily::Char: + { + if (m_pCharFormat) + { + SwTextFormatColl* pLink = lcl_FindParaFormat(m_rDoc, rStr); + if (pLink) + { + m_pCharFormat->SetLinkedParaFormat(*pLink); + } + } + break; + } + default: + break; + } +} + +const OUString& SwDocStyleSheet::GetLink() const +{ + if (!m_bPhysical) + { + SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this); + pThis->FillStyleSheet(FillAllInfo); + } + + return m_aLink; +} + // What Linkage is possible bool SwDocStyleSheet::HasFollowSupport() const { @@ -1849,6 +1894,7 @@ bool SwDocStyleSheet::FillStyleSheet( } pFormat = m_pCharFormat; + m_aLink.clear(); if( !bCreate && !pFormat ) { if( aName == SwResId(STR_POOLCHR_STANDARD)) @@ -1857,6 +1903,15 @@ bool SwDocStyleSheet::FillStyleSheet( nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::ChrFmt ); } + if (m_pCharFormat) + { + const SwTextFormatColl* pParaFormat = m_pCharFormat->GetLinkedParaFormat(); + if (pParaFormat) + { + m_aLink = pParaFormat->GetName(); + } + } + bRet = nullptr != m_pCharFormat || USHRT_MAX != nPoolId; if( bDeleteInfo ) @@ -1876,8 +1931,16 @@ bool SwDocStyleSheet::FillStyleSheet( } pFormat = m_pColl; + m_aLink.clear(); if( m_pColl ) + { PresetFollow( m_pColl->GetNextTextFormatColl().GetName() ); + const SwCharFormat* pCharFormat = m_pColl->GetLinkedCharFormat(); + if (pCharFormat) + { + m_aLink = pCharFormat->GetName(); + } + } else if( !bCreate ) nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::TxtColl );