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 <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin 2021-07-24 19:01:52 +02:00 committed by Noel Grandin
parent e192e1542a
commit 84f4f7f99f
9 changed files with 426 additions and 324 deletions

View file

@ -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<SfxTabPage> SvxFontSubstTabPage::Create( weld::Container* pPage,
bool SvxFontSubstTabPage::FillItemSet( SfxItemSet* )
{
m_xConfig->ClearSubstitutions();// remove all entries
std::vector<SubstitutionStruct> 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<SubstitutionStruct> aFontSubs = svtools::GetFontSubstitutions();
std::unique_ptr<weld::TreeIter> xIter(m_xCheckLB->make_iterator());
for (sal_Int32 i = 0; i < nCount; ++i)
for (sal_Int32 i = 0; i < static_cast<sal_Int32>(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);

View file

@ -26,7 +26,6 @@ class SvtFontSubstConfig;
class SvxFontSubstTabPage : public SfxTabPage
{
OUString m_sAutomatic;
std::unique_ptr<SvtFontSubstConfig> m_xConfig;
std::unique_ptr<weld::CheckButton> m_xUseTableCB;
std::unique_ptr<weld::ComboBox> m_xFont1CB;

View file

@ -1528,7 +1528,7 @@ int Desktop::Main()
SetSplashScreenProgress(55);
SvtFontSubstConfig().Apply();
svtools::ApplyFontSubstitutionsToVcl();
SvtTabAppearanceCfg aAppearanceCfg;
SvtTabAppearanceCfg::SetInitialized();

View file

@ -19,11 +19,8 @@
#pragma once
#include <svtools/svtdllapi.h>
#include <unotools/configitem.hxx>
#include <memory>
struct SvtFontSubstConfig_Impl;
#include <rtl/ustring.hxx>
#include <vector>
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<SvtFontSubstConfig_Impl> 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<SubstitutionStruct> GetFontSubstitutions();
SVT_DLLPUBLIC void SetFontSubstitutions(bool bIsEnabled, std::vector<SubstitutionStruct> const &);
SVT_DLLPUBLIC void ApplyFontSubstitutionsToVcl();
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -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<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const OUString& rNode, ConfigNameFormat eFormat);
static css::uno::Sequence< css::uno::Any> GetProperties(
css::uno::Reference<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const css::uno::Sequence< OUString >& rNames,
bool bAllLocales);
static bool PutProperties(
css::uno::Reference<css::container::XHierarchicalNameAccess> 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<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const OUString& rNode);
// remove, change or add members of a set
static bool ReplaceSetProperties(
css::uno::Reference<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const OUString& rNode,
const css::uno::Sequence< css::beans::PropertyValue >& rValues,
bool bAllLocales);
};
}//namespace utl
#endif // INCLUDED_UNOTOOLS_CONFIGITEM_HXX

View file

@ -22,6 +22,7 @@
#include <sal/config.h>
#include <string_view>
#include <vector>
#include <com/sun/star/uno/Reference.hxx>
@ -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();

View file

@ -19,14 +19,16 @@
#include <svtools/fontsubstconfig.hxx>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <o3tl/any.hxx>
#include <tools/debug.hxx>
#include <vcl/outdev.hxx>
#include <unotools/configmgr.hxx>
#include <unotools/configitem.hxx>
#include <vector>
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<SubstitutionStruct> SubstitutionStructArr;
struct SvtFontSubstConfig_Impl
namespace svtools
{
SubstitutionStructArr aSubstArr;
};
SvtFontSubstConfig::SvtFontSubstConfig() :
ConfigItem("Office.Common/Font/Substitution"),
bIsEnabled(false),
pImpl(new SvtFontSubstConfig_Impl)
bool IsFontSubstitutionsEnabled()
{
Sequence<OUString> aNames { cReplacement };
Sequence<Any> aValues = GetProperties(aNames);
DBG_ASSERT(aValues.getConstArray()[0].hasValue(), "no value available");
if(aValues.getConstArray()[0].hasValue())
bIsEnabled = *o3tl::doAccess<bool>(aValues.getConstArray()[0]);
bool bIsEnabled = false;
Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution");
Any aVal = xHierarchyAccess->getByHierarchicalName(cReplacement);
OUString sPropPrefix(cFontPairs);
const Sequence<OUString> aNodeNames = GetNodeNames(sPropPrefix, ConfigNameFormat::LocalPath);
DBG_ASSERT(aVal.hasValue(), "no value available");
if(aVal.hasValue())
bIsEnabled = *o3tl::doAccess<bool>(aVal);
return bIsEnabled;
}
std::vector<SubstitutionStruct> GetFontSubstitutions()
{
Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution");
const Sequence<OUString> aNodeNames = utl::ConfigItem::GetNodeNames(xHierarchyAccess, cFontPairs, utl::ConfigNameFormat::LocalPath);
Sequence<OUString> 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<Any> aNodeValues = GetProperties(aPropNames);
Sequence<Any> aNodeValues = utl::ConfigItem::GetProperties(xHierarchyAccess, aPropNames, /*bAllLocales*/false);
const Any* pNodeValues = aNodeValues.getConstArray();
nName = 0;
std::vector<SubstitutionStruct> 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<bool>(pNodeValues[nName++]);
aInsert.bReplaceOnScreenOnly = *o3tl::doAccess<bool>(pNodeValues[nName++]);
pImpl->aSubstArr.push_back(aInsert);
aSubstArr.push_back(aInsert);
}
return aSubstArr;
}
SvtFontSubstConfig::~SvtFontSubstConfig()
void SetFontSubstitutions(bool bIsEnabled, std::vector<SubstitutionStruct> const & aSubstArr)
{
}
void SvtFontSubstConfig::Notify( const css::uno::Sequence< OUString >& )
{
}
void SvtFontSubstConfig::ImplCommit()
{
PutProperties({cReplacement}, {css::uno::Any(bIsEnabled)});
Reference<css::container::XHierarchicalNameAccess> 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<PropertyValue> 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<PropertyValue> 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<sal_Int32>(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<SubstitutionStruct> 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: */

View file

@ -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<XHierarchicalNameAccess> 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<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const Sequence< OUString >& rNames,
bool bAllLocales)
{
Sequence< Any > aRet(rNames.getLength());
const OUString* pNames = rNames.getConstArray();
Any* pRet = aRet.getArray();
Reference<XHierarchicalNameAccess> 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<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const Sequence< OUString >& rNames,
const Sequence< Any>& rValues,
bool bAllLocales)
{
Reference<XNameReplace> 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<XNameAccess> xNodeAcc;
aNode >>= xNodeAcc;
Reference<XNameReplace> xNodeReplace(xNodeAcc, UNO_QUERY);
Reference<XNameContainer> 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<XChangesBatch> 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<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
if(xHierarchyAccess.is())
{
try
{
Reference<XNameAccess> 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<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const OUString& rNode,
ConfigNameFormat eFormat)
{
Sequence< OUString > aRet;
try
{
Reference<XNameAccess> 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<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
if(xHierarchyAccess.is())
bRet = ClearNodeSet(xHierarchyAccess, rNode);
return bRet;
}
bool ConfigItem::ClearNodeSet(
css::uno::Reference<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const OUString& rNode)
{
bool bRet = false;
try
{
try
Reference<XNameContainer> xCont;
if(!rNode.isEmpty())
{
Reference<XNameContainer> 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<XChangesBatch> 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<XChangesBatch> 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<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
if(xHierarchyAccess.is())
bRet = ReplaceSetProperties(xHierarchyAccess, rNode, rValues,
( m_nMode & ConfigItemMode::AllLocales ) == ConfigItemMode::AllLocales);
return bRet;
}
bool ConfigItem::ReplaceSetProperties(
css::uno::Reference<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
const OUString& rNode,
const Sequence< PropertyValue >& rValues,
bool bAllLocales)
{
bool bRet = true;
Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
try
{
Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
try
Reference<XNameContainer> xCont;
if(!rNode.isEmpty())
{
Reference<XNameContainer> 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<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
const bool isSimpleValueSet = !xFac.is();
//remove unknown members first
{
const Sequence<OUString> 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<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
const bool isSimpleValueSet = !xFac.is();
//remove unknown members first
{
const Sequence<OUString> 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 <void/>
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<XInterface> 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 <void/>
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<XInterface> 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;
}

View file

@ -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() {