From 84f4f7f99f92c0ecec0dd9d754fdfa8c652a7ec0 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Sat, 24 Jul 2021 19:01:52 +0200 Subject: [PATCH] simplify SvFontSubst in the process, needed to expose some functionality in ConfigManager and ConfigItem, to avoid repeating code Change-Id: Ic0256a010070a79cd649dfd11267bec2f77e5221 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119470 Tested-by: Jenkins Reviewed-by: Noel Grandin --- cui/source/options/fontsubs.cxx | 24 +- cui/source/options/fontsubs.hxx | 1 - desktop/source/app/app.cxx | 2 +- include/svtools/fontsubstconfig.hxx | 33 +- include/unotools/configitem.hxx | 35 +- include/unotools/configmgr.hxx | 4 + svtools/source/config/fontsubstconfig.cxx | 166 ++++---- unotools/source/config/configitem.cxx | 472 +++++++++++++--------- unotools/source/config/configmgr.cxx | 13 + 9 files changed, 426 insertions(+), 324 deletions(-) diff --git a/cui/source/options/fontsubs.cxx b/cui/source/options/fontsubs.cxx index c438061bea90..05e540a44221 100644 --- a/cui/source/options/fontsubs.cxx +++ b/cui/source/options/fontsubs.cxx @@ -34,7 +34,6 @@ SvxFontSubstTabPage::SvxFontSubstTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) : SfxTabPage(pPage, pController, "cui/ui/optfontspage.ui", "OptFontsPage", &rSet) - , m_xConfig(new SvtFontSubstConfig) , m_xUseTableCB(m_xBuilder->weld_check_button("usetable")) , m_xFont1CB(m_xBuilder->weld_combo_box("font1")) , m_xFont2CB(m_xBuilder->weld_combo_box("font2")) @@ -146,23 +145,21 @@ std::unique_ptr SvxFontSubstTabPage::Create( weld::Container* pPage, bool SvxFontSubstTabPage::FillItemSet( SfxItemSet* ) { - m_xConfig->ClearSubstitutions();// remove all entries + std::vector aNewFontSubs; - m_xConfig->Enable(m_xUseTableCB->get_active()); - - m_xCheckLB->all_foreach([this](weld::TreeIter& rIter) { + m_xCheckLB->all_foreach([this, &aNewFontSubs](weld::TreeIter& rIter) { SubstitutionStruct aAdd; aAdd.sFont = m_xCheckLB->get_text(rIter, 2); aAdd.sReplaceBy = m_xCheckLB->get_text(rIter, 3); aAdd.bReplaceAlways = m_xCheckLB->get_toggle(rIter, 0); aAdd.bReplaceOnScreenOnly = m_xCheckLB->get_toggle(rIter, 1); - m_xConfig->AddSubstitution(aAdd); + aNewFontSubs.push_back(aAdd); return false; }); - if(m_xConfig->IsModified()) - m_xConfig->Commit(); - m_xConfig->Apply(); + svtools::SetFontSubstitutions(m_xUseTableCB->get_active(), aNewFontSubs); + svtools::ApplyFontSubstitutionsToVcl(); + std::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create()); if (m_xFontHeightLB->get_value_changed_from_saved()) @@ -206,15 +203,14 @@ void SvxFontSubstTabPage::Reset( const SfxItemSet* ) m_xFont2CB->thaw(); m_xFont1CB->thaw(); - sal_Int32 nCount = m_xConfig->SubstitutionCount(); - if (nCount) - m_xUseTableCB->set_active(m_xConfig->IsEnabled()); + m_xUseTableCB->set_active(svtools::IsFontSubstitutionsEnabled()); + std::vector aFontSubs = svtools::GetFontSubstitutions(); std::unique_ptr xIter(m_xCheckLB->make_iterator()); - for (sal_Int32 i = 0; i < nCount; ++i) + for (sal_Int32 i = 0; i < static_cast(aFontSubs.size()); ++i) { m_xCheckLB->append(xIter.get()); - const SubstitutionStruct* pSubs = m_xConfig->GetSubstitution(i); + const SubstitutionStruct* pSubs = &aFontSubs[i]; m_xCheckLB->set_toggle(*xIter, pSubs->bReplaceAlways ? TRISTATE_TRUE : TRISTATE_FALSE, 0); m_xCheckLB->set_toggle(*xIter, pSubs->bReplaceOnScreenOnly ? TRISTATE_TRUE : TRISTATE_FALSE, 1); m_xCheckLB->set_text(*xIter, pSubs->sFont, 2); diff --git a/cui/source/options/fontsubs.hxx b/cui/source/options/fontsubs.hxx index 600af4cf4fa1..dc55d9434ba9 100644 --- a/cui/source/options/fontsubs.hxx +++ b/cui/source/options/fontsubs.hxx @@ -26,7 +26,6 @@ class SvtFontSubstConfig; class SvxFontSubstTabPage : public SfxTabPage { OUString m_sAutomatic; - std::unique_ptr m_xConfig; std::unique_ptr m_xUseTableCB; std::unique_ptr m_xFont1CB; diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index 86bec9a11c51..dec1fbe150c5 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -1528,7 +1528,7 @@ int Desktop::Main() SetSplashScreenProgress(55); - SvtFontSubstConfig().Apply(); + svtools::ApplyFontSubstitutionsToVcl(); SvtTabAppearanceCfg aAppearanceCfg; SvtTabAppearanceCfg::SetInitialized(); diff --git a/include/svtools/fontsubstconfig.hxx b/include/svtools/fontsubstconfig.hxx index 8399203dfb8f..06097cf3b78b 100644 --- a/include/svtools/fontsubstconfig.hxx +++ b/include/svtools/fontsubstconfig.hxx @@ -19,11 +19,8 @@ #pragma once #include -#include -#include - -struct SvtFontSubstConfig_Impl; - +#include +#include struct SubstitutionStruct { @@ -33,28 +30,12 @@ struct SubstitutionStruct bool bReplaceOnScreenOnly; }; -class SVT_DLLPUBLIC SvtFontSubstConfig final : public utl::ConfigItem +namespace svtools { -private: - bool bIsEnabled; - std::unique_ptr pImpl; - - virtual void ImplCommit() override; - -public: - SvtFontSubstConfig(); - virtual ~SvtFontSubstConfig() override; - - virtual void Notify( const css::uno::Sequence< OUString >& _rPropertyNames) override; - - bool IsEnabled() const {return bIsEnabled;} - void Enable(bool bSet) {bIsEnabled = bSet; SetModified();} - - sal_Int32 SubstitutionCount() const; - void ClearSubstitutions(); - const SubstitutionStruct* GetSubstitution(sal_Int32 nPos); - void AddSubstitution(const SubstitutionStruct& rToAdd); - void Apply(); + SVT_DLLPUBLIC bool IsFontSubstitutionsEnabled(); + SVT_DLLPUBLIC std::vector GetFontSubstitutions(); + SVT_DLLPUBLIC void SetFontSubstitutions(bool bIsEnabled, std::vector const &); + SVT_DLLPUBLIC void ApplyFontSubstitutionsToVcl(); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/unotools/configitem.hxx b/include/unotools/configitem.hxx index e14aaf0f2418..20612d401ab8 100644 --- a/include/unotools/configitem.hxx +++ b/include/unotools/configitem.hxx @@ -93,13 +93,14 @@ namespace utl // LOCALE VALUE // "de" "Mein Name" // "en-US" "my name" - void impl_packLocalizedProperties ( const css::uno::Sequence< OUString >& lInNames , + static void impl_packLocalizedProperties ( const css::uno::Sequence< OUString >& lInNames , const css::uno::Sequence< css::uno::Any >& lInValues , css::uno::Sequence< css::uno::Any >& lOutValues ); - void impl_unpackLocalizedProperties ( const css::uno::Sequence< OUString >& lInNames , - const css::uno::Sequence< css::uno::Any >& lInValues , - css::uno::Sequence< OUString >& lOutNames , - css::uno::Sequence< css::uno::Any >& lOutValues ); + static void impl_unpackLocalizedProperties ( + const css::uno::Sequence< OUString >& lInNames , + const css::uno::Sequence< css::uno::Any >& lInValues , + css::uno::Sequence< OUString >& lOutNames , + css::uno::Sequence< css::uno::Any >& lOutValues); css::uno::Reference< css::container::XHierarchicalNameAccess> GetTree(); @@ -178,6 +179,30 @@ namespace utl void Commit(); ConfigItemMode GetMode() const { return m_nMode;} + + //returns all members of a node in a specific format + static css::uno::Sequence< OUString > GetNodeNames( + css::uno::Reference const & xHierarchyAccess, + const OUString& rNode, ConfigNameFormat eFormat); + static css::uno::Sequence< css::uno::Any> GetProperties( + css::uno::Reference const & xHierarchyAccess, + const css::uno::Sequence< OUString >& rNames, + bool bAllLocales); + static bool PutProperties( + css::uno::Reference const & xHierarchyAccess, + const css::uno::Sequence< OUString >& rNames, + const css::uno::Sequence< css::uno::Any>& rValues, + bool bAllLocales); + // remove all members of a set + static bool ClearNodeSet( + css::uno::Reference const & xHierarchyAccess, + const OUString& rNode); + // remove, change or add members of a set + static bool ReplaceSetProperties( + css::uno::Reference const & xHierarchyAccess, + const OUString& rNode, + const css::uno::Sequence< css::beans::PropertyValue >& rValues, + bool bAllLocales); }; }//namespace utl #endif // INCLUDED_UNOTOOLS_CONFIGITEM_HXX diff --git a/include/unotools/configmgr.hxx b/include/unotools/configmgr.hxx index a4d46cb8e19e..e8d42a28fd7e 100644 --- a/include/unotools/configmgr.hxx +++ b/include/unotools/configmgr.hxx @@ -22,6 +22,7 @@ #include +#include #include #include @@ -62,6 +63,9 @@ public: SAL_DLLPRIVATE static css::uno::Reference< css::container::XHierarchicalNameAccess> acquireTree(utl::ConfigItem const & item); + static css::uno::Reference< css::container::XHierarchicalNameAccess> + acquireTree(std::u16string_view rSubTreeName); + SAL_DLLPRIVATE ConfigManager(); SAL_DLLPRIVATE ~ConfigManager(); diff --git a/svtools/source/config/fontsubstconfig.cxx b/svtools/source/config/fontsubstconfig.cxx index a77f2e59b775..3028e76c9ae0 100644 --- a/svtools/source/config/fontsubstconfig.cxx +++ b/svtools/source/config/fontsubstconfig.cxx @@ -19,14 +19,16 @@ #include #include +#include #include #include #include #include +#include +#include #include -using namespace utl; using namespace com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::beans; @@ -40,41 +42,41 @@ constexpr OUStringLiteral cSubstituteFont= u"SubstituteFont"; constexpr OUStringLiteral cOnScreenOnly = u"OnScreenOnly"; constexpr OUStringLiteral cAlways = u"Always"; -typedef std::vector SubstitutionStructArr; - -struct SvtFontSubstConfig_Impl +namespace svtools { - SubstitutionStructArr aSubstArr; -}; -SvtFontSubstConfig::SvtFontSubstConfig() : - ConfigItem("Office.Common/Font/Substitution"), - bIsEnabled(false), - pImpl(new SvtFontSubstConfig_Impl) +bool IsFontSubstitutionsEnabled() { - Sequence aNames { cReplacement }; - Sequence aValues = GetProperties(aNames); - DBG_ASSERT(aValues.getConstArray()[0].hasValue(), "no value available"); - if(aValues.getConstArray()[0].hasValue()) - bIsEnabled = *o3tl::doAccess(aValues.getConstArray()[0]); + bool bIsEnabled = false; + Reference xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution"); + Any aVal = xHierarchyAccess->getByHierarchicalName(cReplacement); - OUString sPropPrefix(cFontPairs); - const Sequence aNodeNames = GetNodeNames(sPropPrefix, ConfigNameFormat::LocalPath); + DBG_ASSERT(aVal.hasValue(), "no value available"); + if(aVal.hasValue()) + bIsEnabled = *o3tl::doAccess(aVal); + return bIsEnabled; +} + +std::vector GetFontSubstitutions() +{ + Reference xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution"); + + const Sequence aNodeNames = utl::ConfigItem::GetNodeNames(xHierarchyAccess, cFontPairs, utl::ConfigNameFormat::LocalPath); Sequence aPropNames(aNodeNames.getLength() * 4); OUString* pNames = aPropNames.getArray(); sal_Int32 nName = 0; - sPropPrefix += "/"; for(const OUString& rNodeName : aNodeNames) { - OUString sStart = sPropPrefix + rNodeName + "/"; + OUString sStart = cFontPairs + "/" + rNodeName + "/"; pNames[nName++] = sStart + cReplaceFont; pNames[nName++] = sStart + cSubstituteFont; pNames[nName++] = sStart + cAlways; pNames[nName++] = sStart + cOnScreenOnly; } - Sequence aNodeValues = GetProperties(aPropNames); + Sequence aNodeValues = utl::ConfigItem::GetProperties(xHierarchyAccess, aPropNames, /*bAllLocales*/false); const Any* pNodeValues = aNodeValues.getConstArray(); nName = 0; + std::vector aSubstArr; for(sal_Int32 nNode = 0; nNode < aNodeNames.getLength(); nNode++) { SubstitutionStruct aInsert; @@ -82,100 +84,74 @@ SvtFontSubstConfig::SvtFontSubstConfig() : pNodeValues[nName++] >>= aInsert.sReplaceBy; aInsert.bReplaceAlways = *o3tl::doAccess(pNodeValues[nName++]); aInsert.bReplaceOnScreenOnly = *o3tl::doAccess(pNodeValues[nName++]); - pImpl->aSubstArr.push_back(aInsert); + aSubstArr.push_back(aInsert); } + return aSubstArr; } -SvtFontSubstConfig::~SvtFontSubstConfig() +void SetFontSubstitutions(bool bIsEnabled, std::vector const & aSubstArr) { -} - -void SvtFontSubstConfig::Notify( const css::uno::Sequence< OUString >& ) -{ -} - -void SvtFontSubstConfig::ImplCommit() -{ - PutProperties({cReplacement}, {css::uno::Any(bIsEnabled)}); + Reference xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution"); + utl::ConfigItem::PutProperties(xHierarchyAccess, {cReplacement}, {css::uno::Any(bIsEnabled)}, /*bAllLocales*/false); OUString sNode(cFontPairs); - if(pImpl->aSubstArr.empty()) - ClearNodeSet(sNode); - else + if(aSubstArr.empty()) { - Sequence aSetValues(4 * pImpl->aSubstArr.size()); - PropertyValue* pSetValues = aSetValues.getArray(); - sal_Int32 nSetValue = 0; - - const OUString sReplaceFont(cReplaceFont); - const OUString sSubstituteFont(cSubstituteFont); - const OUString sAlways(cAlways); - const OUString sOnScreenOnly(cOnScreenOnly); - - for(size_t i = 0; i < pImpl->aSubstArr.size(); i++) - { - OUString sPrefix = sNode + "/_" + OUString::number(i) + "/"; - - SubstitutionStruct& rSubst = pImpl->aSubstArr[i]; - pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sReplaceFont; - pSetValues[nSetValue++].Value <<= rSubst.sFont; - pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sSubstituteFont; - pSetValues[nSetValue++].Value <<= rSubst.sReplaceBy; - pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sAlways; - pSetValues[nSetValue++].Value <<= rSubst.bReplaceAlways; - pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sOnScreenOnly; - pSetValues[nSetValue++].Value <<= rSubst.bReplaceOnScreenOnly; - } - ReplaceSetProperties(sNode, aSetValues); + utl::ConfigItem::ClearNodeSet(xHierarchyAccess, sNode); + return; } + + Sequence aSetValues(4 * aSubstArr.size()); + PropertyValue* pSetValues = aSetValues.getArray(); + sal_Int32 nSetValue = 0; + + const OUString sReplaceFont(cReplaceFont); + const OUString sSubstituteFont(cSubstituteFont); + const OUString sAlways(cAlways); + const OUString sOnScreenOnly(cOnScreenOnly); + + for(size_t i = 0; i < aSubstArr.size(); i++) + { + OUString sPrefix = sNode + "/_" + OUString::number(i) + "/"; + + const SubstitutionStruct& rSubst = aSubstArr[i]; + pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sReplaceFont; + pSetValues[nSetValue++].Value <<= rSubst.sFont; + pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sSubstituteFont; + pSetValues[nSetValue++].Value <<= rSubst.sReplaceBy; + pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sAlways; + pSetValues[nSetValue++].Value <<= rSubst.bReplaceAlways; + pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sOnScreenOnly; + pSetValues[nSetValue++].Value <<= rSubst.bReplaceOnScreenOnly; + } + utl::ConfigItem::ReplaceSetProperties(xHierarchyAccess, sNode, aSetValues, /*bAllLocales*/false); } -sal_Int32 SvtFontSubstConfig::SubstitutionCount() const -{ - return pImpl->aSubstArr.size(); -} - -void SvtFontSubstConfig::ClearSubstitutions() -{ - pImpl->aSubstArr.clear(); -} - -const SubstitutionStruct* SvtFontSubstConfig::GetSubstitution(sal_Int32 nPos) -{ - sal_Int32 nCount = static_cast(pImpl->aSubstArr.size()); - DBG_ASSERT(nPos >= 0 && nPos < nCount, "illegal array index"); - if(nPos >= 0 && nPos < nCount) - return &pImpl->aSubstArr[nPos]; - return nullptr; -} - -void SvtFontSubstConfig::AddSubstitution(const SubstitutionStruct& rToAdd) -{ - pImpl->aSubstArr.push_back(rToAdd); -} - -void SvtFontSubstConfig::Apply() +void ApplyFontSubstitutionsToVcl() { OutputDevice::BeginFontSubstitution(); // remove old substitutions OutputDevice::RemoveFontsSubstitute(); - // read new substitutions - sal_Int32 nCount = IsEnabled() ? SubstitutionCount() : 0; + const bool bIsEnabled = IsFontSubstitutionsEnabled(); + std::vector aSubst = GetFontSubstitutions(); - for (sal_Int32 i = 0; i < nCount; i++) - { - AddFontSubstituteFlags nFlags = AddFontSubstituteFlags::NONE; - const SubstitutionStruct* pSubs = GetSubstitution(i); - if(pSubs->bReplaceAlways) - nFlags |= AddFontSubstituteFlags::ALWAYS; - if(pSubs->bReplaceOnScreenOnly) - nFlags |= AddFontSubstituteFlags::ScreenOnly; - OutputDevice::AddFontSubstitute( pSubs->sFont, pSubs->sReplaceBy, nFlags ); - } + // read new substitutions + if (bIsEnabled) + for (const SubstitutionStruct & rSub : aSubst) + { + AddFontSubstituteFlags nFlags = AddFontSubstituteFlags::NONE; + if(rSub.bReplaceAlways) + nFlags |= AddFontSubstituteFlags::ALWAYS; + if(rSub.bReplaceOnScreenOnly) + nFlags |= AddFontSubstituteFlags::ScreenOnly; + OutputDevice::AddFontSubstitute( rSub.sFont, rSub.sReplaceBy, nFlags ); + } OutputDevice::EndFontSubstitution(); } +} // namespace svtools + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotools/source/config/configitem.cxx b/unotools/source/config/configitem.cxx index 60ded67dc837..28c4159e21ad 100644 --- a/unotools/source/config/configitem.cxx +++ b/unotools/source/config/configitem.cxx @@ -172,9 +172,7 @@ void ConfigItem::impl_packLocalizedProperties( const Sequence< OUString >& const Sequence< Any >& lInValues , Sequence< Any >& lOutValues ) { - // Safe impossible cases. - // This method should be called for special ConfigItem-mode only! - OSL_ENSURE( ((m_nMode & ConfigItemMode::AllLocales ) == ConfigItemMode::AllLocales), "ConfigItem::impl_packLocalizedProperties() Wrong call of this method detected!" ); + // This method should be called for special AllLocales ConfigItem-mode only! sal_Int32 nSourceCounter; // used to step during input lists sal_Int32 nSourceSize; // marks end of loop over input lists @@ -238,11 +236,9 @@ void ConfigItem::impl_packLocalizedProperties( const Sequence< OUString >& void ConfigItem::impl_unpackLocalizedProperties( const Sequence< OUString >& lInNames , const Sequence< Any >& lInValues , Sequence< OUString >& lOutNames , - Sequence< Any >& lOutValues ) + Sequence< Any >& lOutValues) { - // Safe impossible cases. - // This method should be called for special ConfigItem-mode only! - OSL_ENSURE( ((m_nMode & ConfigItemMode::AllLocales ) == ConfigItemMode::AllLocales), "ConfigItem::impl_unpackLocalizedProperties() Wrong call of this method detected!" ); + // This method should be called for special AllLocales ConfigItem-mode only! sal_Int32 nSourceSize; // marks end of loop over input lists sal_Int32 nDestinationCounter; // actual position in output lists @@ -388,35 +384,42 @@ Sequence< sal_Bool > ConfigItem::GetReadOnlyStates(const css::uno::Sequence< OUS } Sequence< Any > ConfigItem::GetProperties(const Sequence< OUString >& rNames) +{ + Reference xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + return GetProperties(xHierarchyAccess, rNames, + (m_nMode & ConfigItemMode::AllLocales ) == ConfigItemMode::AllLocales); + return Sequence< Any >(rNames.getLength()); +} + +Sequence< Any > ConfigItem::GetProperties( + css::uno::Reference const & xHierarchyAccess, + const Sequence< OUString >& rNames, + bool bAllLocales) { Sequence< Any > aRet(rNames.getLength()); const OUString* pNames = rNames.getConstArray(); Any* pRet = aRet.getArray(); - Reference xHierarchyAccess = GetTree(); - if(xHierarchyAccess.is()) + for(int i = 0; i < rNames.getLength(); i++) { - for(int i = 0; i < rNames.getLength(); i++) + try { - try - { - pRet[i] = xHierarchyAccess->getByHierarchicalName(pNames[i]); - } - catch (const Exception&) - { - TOOLS_WARN_EXCEPTION( - "unotools.config", - "ignoring XHierarchicalNameAccess to /org.openoffice." - << sSubTree << "/" << pNames[i]); - } + pRet[i] = xHierarchyAccess->getByHierarchicalName(pNames[i]); } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( + "unotools.config", + "ignoring XHierarchicalNameAccess " << pNames[i]); + } + } - // In special mode "ALL_LOCALES" we must convert localized values to Sequence< PropertyValue >. - if((m_nMode & ConfigItemMode::AllLocales ) == ConfigItemMode::AllLocales) - { - Sequence< Any > lValues; - impl_packLocalizedProperties( rNames, aRet, lValues ); - aRet = lValues; - } + // In special mode "ALL_LOCALES" we must convert localized values to Sequence< PropertyValue >. + if(bAllLocales) + { + Sequence< Any > lValues; + impl_packLocalizedProperties( rNames, aRet, lValues ); + aRet = lValues; } return aRet; } @@ -501,6 +504,87 @@ bool ConfigItem::PutProperties( const Sequence< OUString >& rNames, return bRet; } +bool ConfigItem::PutProperties( + css::uno::Reference const & xHierarchyAccess, + const Sequence< OUString >& rNames, + const Sequence< Any>& rValues, + bool bAllLocales) +{ + Reference xTopNodeReplace(xHierarchyAccess, UNO_QUERY); + bool bRet = xTopNodeReplace.is(); + if(bRet) + { + Sequence< OUString > lNames; + Sequence< Any > lValues; + const OUString* pNames = nullptr; + const Any* pValues = nullptr; + sal_Int32 nNameCount; + if(bAllLocales) + { + // If ConfigItem works in "ALL_LOCALES"-mode ... we must support a Sequence< PropertyValue > + // as value of a localized configuration entry! + // How we can do that? + // We must split all PropertyValues to "Sequence< OUString >" AND "Sequence< Any >"! + impl_unpackLocalizedProperties( rNames, rValues, lNames, lValues ); + pNames = lNames.getConstArray (); + pValues = lValues.getConstArray (); + nNameCount = lNames.getLength (); + } + else + { + // This is the normal mode ... + // Use given input lists directly. + pNames = rNames.getConstArray (); + pValues = rValues.getConstArray (); + nNameCount = rNames.getLength (); + } + for(int i = 0; i < nNameCount; i++) + { + try + { + OUString sNode, sProperty; + if (splitLastFromConfigurationPath(pNames[i],sNode, sProperty)) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(sNode); + + Reference xNodeAcc; + aNode >>= xNodeAcc; + Reference xNodeReplace(xNodeAcc, UNO_QUERY); + Reference xNodeCont (xNodeAcc, UNO_QUERY); + + bool bExist = (xNodeAcc.is() && xNodeAcc->hasByName(sProperty)); + if (bExist && xNodeReplace.is()) + xNodeReplace->replaceByName(sProperty, pValues[i]); + else + if (!bExist && xNodeCont.is()) + xNodeCont->insertByName(sProperty, pValues[i]); + else + bRet = false; + } + else //direct value + { + xTopNodeReplace->replaceByName(sProperty, pValues[i]); + } + } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from PutProperties"); + } + } + try + { + Reference xBatch(xHierarchyAccess, UNO_QUERY); + xBatch->commitChanges(); + } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from commitChanges"); + } + } + + return bRet; +} + void ConfigItem::DisableNotification() { OSL_ENSURE( xChangeLstnr.is(), "ConfigItem::DisableNotification: notifications not enabled currently!" ); @@ -597,31 +681,38 @@ Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode) Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode, ConfigNameFormat eFormat) { - Sequence< OUString > aRet; Reference xHierarchyAccess = GetTree(); if(xHierarchyAccess.is()) - { - try - { - Reference xCont; - if(!rNode.isEmpty()) - { - Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); - aNode >>= xCont; - } - else - xCont.set(xHierarchyAccess, UNO_QUERY); - if(xCont.is()) - { - aRet = xCont->getElementNames(); - lcl_normalizeLocalNames(aRet,eFormat,xCont); - } + return GetNodeNames(xHierarchyAccess, rNode, eFormat); + return Sequence< OUString >(); +} - } - catch (css::uno::Exception &) +Sequence< OUString > ConfigItem::GetNodeNames( + css::uno::Reference const & xHierarchyAccess, + const OUString& rNode, + ConfigNameFormat eFormat) +{ + Sequence< OUString > aRet; + try + { + Reference xCont; + if(!rNode.isEmpty()) { - TOOLS_WARN_EXCEPTION("unotools.config", "Exception from GetNodeNames"); + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; } + else + xCont.set(xHierarchyAccess, UNO_QUERY); + if(xCont.is()) + { + aRet = xCont->getElementNames(); + lcl_normalizeLocalNames(aRet,eFormat,xCont); + } + + } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from GetNodeNames"); } return aRet; } @@ -632,39 +723,46 @@ bool ConfigItem::ClearNodeSet(const OUString& rNode) bool bRet = false; Reference xHierarchyAccess = GetTree(); if(xHierarchyAccess.is()) + bRet = ClearNodeSet(xHierarchyAccess, rNode); + return bRet; +} + +bool ConfigItem::ClearNodeSet( + css::uno::Reference const & xHierarchyAccess, + const OUString& rNode) +{ + bool bRet = false; + try { - try + Reference xCont; + if(!rNode.isEmpty()) { - Reference xCont; - if(!rNode.isEmpty()) - { - Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); - aNode >>= xCont; - } - else - xCont.set(xHierarchyAccess, UNO_QUERY); - if(!xCont.is()) - return false; - const Sequence< OUString > aNames = xCont->getElementNames(); - Reference xBatch(xHierarchyAccess, UNO_QUERY); - for(const OUString& rName : aNames) - { - try - { - xCont->removeByName(rName); - } - catch (css::uno::Exception &) - { - TOOLS_WARN_EXCEPTION("unotools.config", "Exception from removeByName"); - } - } - xBatch->commitChanges(); - bRet = true; + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; } - catch (css::uno::Exception &) + else + xCont.set(xHierarchyAccess, UNO_QUERY); + if(!xCont.is()) + return false; + const Sequence< OUString > aNames = xCont->getElementNames(); + Reference xBatch(xHierarchyAccess, UNO_QUERY); + for(const OUString& rName : aNames) { - TOOLS_WARN_EXCEPTION("unotools.config", "Exception from ClearNodeSet"); + try + { + xCont->removeByName(rName); + } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from removeByName"); + } } + xBatch->commitChanges(); + bRet = true; + } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from ClearNodeSet"); } return bRet; } @@ -848,124 +946,134 @@ bool ConfigItem::ReplaceSetProperties( bool bRet = true; Reference xHierarchyAccess = GetTree(); if(xHierarchyAccess.is()) + bRet = ReplaceSetProperties(xHierarchyAccess, rNode, rValues, + ( m_nMode & ConfigItemMode::AllLocales ) == ConfigItemMode::AllLocales); + return bRet; +} + +bool ConfigItem::ReplaceSetProperties( + css::uno::Reference const & xHierarchyAccess, + const OUString& rNode, + const Sequence< PropertyValue >& rValues, + bool bAllLocales) +{ + bool bRet = true; + Reference xBatch(xHierarchyAccess, UNO_QUERY); + try { - Reference xBatch(xHierarchyAccess, UNO_QUERY); - try + Reference xCont; + if(!rNode.isEmpty()) { - Reference xCont; - if(!rNode.isEmpty()) + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; + } + else + xCont.set(xHierarchyAccess, UNO_QUERY); + if(!xCont.is()) + return false; + + // JB: Change: now the same name handling for sets of simple values + const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode); + + Reference xFac(xCont, UNO_QUERY); + const bool isSimpleValueSet = !xFac.is(); + + //remove unknown members first + { + const Sequence aContainerSubNodes = xCont->getElementNames(); + + for(const OUString& rContainerSubNode : aContainerSubNodes) { - Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); - aNode >>= xCont; - } - else - xCont.set(xHierarchyAccess, UNO_QUERY); - if(!xCont.is()) - return false; - - // JB: Change: now the same name handling for sets of simple values - const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode); - - Reference xFac(xCont, UNO_QUERY); - const bool isSimpleValueSet = !xFac.is(); - - //remove unknown members first - { - const Sequence aContainerSubNodes = xCont->getElementNames(); - - for(const OUString& rContainerSubNode : aContainerSubNodes) - { - bool bFound = comphelper::findValue(aSubNodeNames, rContainerSubNode) != -1; - if(!bFound) - try - { - xCont->removeByName(rContainerSubNode); - } - catch (const Exception&) - { - if (isSimpleValueSet) - { - try - { - // #i37322#: fallback action: replace with - xCont->replaceByName(rContainerSubNode, Any()); - // fallback successful: continue looping - continue; - } - catch (Exception &) - {} // propagate original exception, if fallback fails - } - throw; - } - } - try { xBatch->commitChanges(); } - catch (css::uno::Exception &) - { - TOOLS_WARN_EXCEPTION("unotools.config", "Exception from commitChanges"); - } - } - - if(xFac.is()) // !isSimpleValueSet - { - for(const OUString& rSubNodeName : aSubNodeNames) - { - if(!xCont->hasByName(rSubNodeName)) - { - //create if not available - Reference xInst = xFac->createInstance(); - Any aVal; aVal <<= xInst; - xCont->insertByName(rSubNodeName, aVal); - } - } - try { xBatch->commitChanges(); } - catch (css::uno::Exception &) - { - TOOLS_WARN_EXCEPTION("unotools.config", "Exception from commitChanges"); - } - - const PropertyValue* pProperties = rValues.getConstArray(); - - Sequence< OUString > aSetNames(rValues.getLength()); - OUString* pSetNames = aSetNames.getArray(); - - Sequence< Any> aSetValues(rValues.getLength()); - Any* pSetValues = aSetValues.getArray(); - - bool bEmptyNode = rNode.isEmpty(); - for(sal_Int32 k = 0; k < rValues.getLength(); k++) - { - pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0); - pSetValues[k] = pProperties[k].Value; - } - bRet = PutProperties(aSetNames, aSetValues); - } - else - { - //if no factory is available then the node contains basic data elements - for(const PropertyValue& rValue : rValues) - { + bool bFound = comphelper::findValue(aSubNodeNames, rContainerSubNode) != -1; + if(!bFound) try { - OUString sSubNode = lcl_extractSetPropertyName( rValue.Name, rNode ); - - if(xCont->hasByName(sSubNode)) - xCont->replaceByName(sSubNode, rValue.Value); - else - xCont->insertByName(sSubNode, rValue.Value); + xCont->removeByName(rContainerSubNode); } - catch (css::uno::Exception &) + catch (const Exception&) { - TOOLS_WARN_EXCEPTION("unotools.config", "Exception from insert/replaceByName"); + if (isSimpleValueSet) + { + try + { + // #i37322#: fallback action: replace with + xCont->replaceByName(rContainerSubNode, Any()); + // fallback successful: continue looping + continue; + } + catch (Exception &) + {} // propagate original exception, if fallback fails + } + throw; } - } - xBatch->commitChanges(); + } + try { xBatch->commitChanges(); } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from commitChanges"); } } - catch (const Exception& ) + + if(xFac.is()) // !isSimpleValueSet { - TOOLS_WARN_EXCEPTION("unotools.config", "Exception from ReplaceSetProperties"); - bRet = false; + for(const OUString& rSubNodeName : aSubNodeNames) + { + if(!xCont->hasByName(rSubNodeName)) + { + //create if not available + Reference xInst = xFac->createInstance(); + Any aVal; aVal <<= xInst; + xCont->insertByName(rSubNodeName, aVal); + } + } + try { xBatch->commitChanges(); } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from commitChanges"); + } + + const PropertyValue* pProperties = rValues.getConstArray(); + + Sequence< OUString > aSetNames(rValues.getLength()); + OUString* pSetNames = aSetNames.getArray(); + + Sequence< Any> aSetValues(rValues.getLength()); + Any* pSetValues = aSetValues.getArray(); + + bool bEmptyNode = rNode.isEmpty(); + for(sal_Int32 k = 0; k < rValues.getLength(); k++) + { + pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0); + pSetValues[k] = pProperties[k].Value; + } + bRet = PutProperties(xHierarchyAccess, aSetNames, aSetValues, bAllLocales); } + else + { + //if no factory is available then the node contains basic data elements + for(const PropertyValue& rValue : rValues) + { + try + { + OUString sSubNode = lcl_extractSetPropertyName( rValue.Name, rNode ); + + if(xCont->hasByName(sSubNode)) + xCont->replaceByName(sSubNode, rValue.Value); + else + xCont->insertByName(sSubNode, rValue.Value); + } + catch (css::uno::Exception &) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from insert/replaceByName"); + } + } + xBatch->commitChanges(); + } + } + catch (const Exception& ) + { + TOOLS_WARN_EXCEPTION("unotools.config", "Exception from ReplaceSetProperties"); + bRet = false; } return bRet; } diff --git a/unotools/source/config/configmgr.cxx b/unotools/source/config/configmgr.cxx index 610246295d55..f1a897a6edab 100644 --- a/unotools/source/config/configmgr.cxx +++ b/unotools/source/config/configmgr.cxx @@ -134,6 +134,19 @@ utl::ConfigManager::acquireTree(utl::ConfigItem const & item) { css::uno::UNO_QUERY_THROW); } +css::uno::Reference< css::container::XHierarchicalNameAccess > +utl::ConfigManager::acquireTree(std::u16string_view rSubTreeName) { + css::uno::Sequence< css::uno::Any > args(1); + args[0] <<= css::beans::NamedValue( + "nodepath", + css::uno::makeAny(OUString::Concat(u"/org.openoffice.") + rSubTreeName)); + return css::uno::Reference< css::container::XHierarchicalNameAccess >( + getConfigurationProvider()->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", + args), + css::uno::UNO_QUERY_THROW); +} + utl::ConfigManager::ConfigManager() {} utl::ConfigManager::~ConfigManager() {