sd/inc/stlsheet.hxx | 2 ++ sd/source/core/stlsheet.cxx | 29 +++++++++++++++++++++++++++++ sd/source/ui/table/TableDesignPane.cxx | 16 +++++++++------- 3 files changed, 40 insertions(+), 7 deletions(-)
New commits: commit 423c2a6ac74cd30c6576e6794f67fda4fb685c11 Author: Maxim Monastirsky <momonas...@gmail.com> AuthorDate: Thu Nov 24 21:22:42 2022 +0200 Commit: Maxim Monastirsky <momonas...@gmail.com> CommitDate: Fri Nov 25 14:17:22 2022 +0100 sd: better detection of user defined cell styles Cell style might be used for several table roles at once, or even in several table styles (esp. after new/clone actions). But when we're editing a style, we want just a single place to be changed. The initial solution was to check if the style is user defined. The problem is that if we change the built-in styles set, then documents created with the old styles will have their once built-in styles turned into user defined. In such case we might still attempt to edit a shared style, which is unintended. So try harder, and check also that the style isn't used twice and that there is no other styles inheriting from it. Change-Id: I67d8c61b15161c9d839e97f7a31a1349a7e2613c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143288 Tested-by: Jenkins Reviewed-by: Maxim Monastirsky <momonas...@gmail.com> diff --git a/sd/inc/stlsheet.hxx b/sd/inc/stlsheet.hxx index 645259e9e8fc..9080c3b8805b 100644 --- a/sd/inc/stlsheet.hxx +++ b/sd/inc/stlsheet.hxx @@ -63,6 +63,8 @@ public: virtual bool HasClearParentSupport() const override; virtual void SetHelpId( const OUString& r, sal_uLong nId ) override; + bool IsEditable(); + void AdjustToFontHeight(SfxItemSet& rSet, bool bOnlyMissingItems = true); SdStyleSheet* GetRealStyleSheet() const; diff --git a/sd/source/core/stlsheet.cxx b/sd/source/core/stlsheet.cxx index 1c11e5fea39d..4d72cf0915c6 100644 --- a/sd/source/core/stlsheet.cxx +++ b/sd/source/core/stlsheet.cxx @@ -325,6 +325,35 @@ bool SdStyleSheet::IsUsed() const return bResult; } +/** + * Checks if a cell style is used in two places at once. + * Typically we modify the formatting of a single place, + * so such style shouldn't be edited directly. + */ +bool SdStyleSheet::IsEditable() +{ + if (GetFamily() != SfxStyleFamily::Frame) + return true; + + if (!IsUserDefined()) + return false; + + const size_t nListenerCount = GetSizeOfVector(); + for (size_t n = 0; n < nListenerCount; ++n) + { + SfxListener* pListener = GetListener(n); + if (pListener == this) + continue; + if (dynamic_cast<SdStyleSheet*>(pListener)) + return false; + } + + MutexGuard aGuard(mrBHelper.rMutex); + + auto pContainer = mrBHelper.getContainer(cppu::UnoType<XModifyListener>::get()); + return !pContainer || pContainer->getLength() <= 1; +} + /** * Determine the style sheet for which this dummy is for. */ diff --git a/sd/source/ui/table/TableDesignPane.cxx b/sd/source/ui/table/TableDesignPane.cxx index dd7749db7e79..aa331c3dcda1 100644 --- a/sd/source/ui/table/TableDesignPane.cxx +++ b/sd/source/ui/table/TableDesignPane.cxx @@ -303,8 +303,10 @@ void TableDesignWidget::ResetStyle() for (sal_Int32 i = 0; i < xTableStyle->getCount(); ++i) { Reference<XStyle> xCellStyle(xTableStyle->getByIndex(i), UNO_QUERY); - if (xCellStyle && xCellStyle->isUserDefined()) - xTableStyle->replaceByIndex(i, mxCellFamily->getByName(xCellStyle->getParentStyle())); + while (xCellStyle && xCellStyle->isUserDefined() && !xCellStyle->getParentStyle().isEmpty()) + xCellStyle.set(mxCellFamily->getByName(xCellStyle->getParentStyle()), UNO_QUERY); + + xTableStyle->replaceByIndex(i, Any(xCellStyle)); } endTextEditForStyle(xTableStyle); @@ -353,17 +355,17 @@ void TableDesignWidget::EditStyle(std::string_view rCommand) { Reference<XNameReplace> xTableStyle(mxTableFamily->getByIndex(m_xValueSet->GetSelectedItemId() - 1), UNO_QUERY_THROW); Reference<XStyle> xCellStyle(xTableStyle->getByName(OUString::fromUtf8(rCommand)), UNO_QUERY_THROW); + rtl::Reference xStyleSheet = static_cast<SdStyleSheet*>(xCellStyle.get()); - bool bUserDefined = xCellStyle->isUserDefined(); + bool bUserDefined = xStyleSheet->IsEditable(); if (!bUserDefined) { Reference<XSingleServiceFactory> xFactory(mxCellFamily, UNO_QUERY_THROW); - Reference<XStyle> xNewStyle(xFactory->createInstance(), UNO_QUERY_THROW); - xNewStyle->setParentStyle(xCellStyle->getName()); - xCellStyle = xNewStyle; + xCellStyle.set(xFactory->createInstance(), UNO_QUERY_THROW); + xCellStyle->setParentStyle(xStyleSheet->getName()); + xStyleSheet = static_cast<SdStyleSheet*>(xCellStyle.get()); } - rtl::Reference xStyleSheet = static_cast<SdStyleSheet*>(xCellStyle.get()); SfxItemSet aNewAttr(xStyleSheet->GetItemSet()); // merge drawing layer text distance items into SvxBoxItem used by the dialog