26#include <com/sun/star/beans/XPropertySet.hpp>
27#include <com/sun/star/util/XChangesListener.hpp>
28#include <com/sun/star/util/XChangesNotifier.hpp>
29#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
30#include <com/sun/star/configuration/XTemplateContainer.hpp>
31#include <com/sun/star/container/XNameContainer.hpp>
32#include <com/sun/star/lang/XSingleServiceFactory.hpp>
33#include <com/sun/star/lang/XServiceInfo.hpp>
34#include <com/sun/star/beans/PropertyValue.hpp>
35#include <com/sun/star/beans/PropertyAttribute.hpp>
36#include <com/sun/star/util/XChangesBatch.hpp>
38#include <osl/diagnose.h>
64 css::util::XChangesListener
73 virtual void SAL_CALL
changesOccurred(
const ChangesEvent& Event )
override;
76 virtual void SAL_CALL
disposing(
const EventObject& Source )
override;
82class ValueCounter_Impl
86 explicit ValueCounter_Impl(sal_Int16& rCounter)
93 OSL_ENSURE(rCnt>0,
"RefCount < 0 ??");
100ConfigChangeListener_Impl::ConfigChangeListener_Impl(
103 aPropertyNames(rNames)
110 OUString* pNames = aChangedNames.getArray();
112 sal_Int32 nNotify = 0;
113 for(
const auto& rElementChange : rEvent.Changes)
116 rElementChange.Accessor >>= sTemp;
120 [&sTemp](
const OUString& rCheckPropertyName) { return isPrefixOfConfigurationPath(sTemp, rCheckPropertyName); });
122 pNames[nNotify++] = sTemp;
129 osl::Guard<comphelper::SolarMutex> aMutexGuard( pMutex );
130 aChangedNames.realloc(nNotify);
142 sSubTree(
std::move(aSubTree)),
144 m_bIsModified(false),
145 m_bEnableInternalNotification(false),
178 sal_Int32 nSourceCounter;
179 sal_Int32 nSourceSize;
180 sal_Int32 nDestinationCounter;
181 sal_Int32 nPropertyCounter;
182 sal_Int32 nPropertiesSize;
194 nSourceSize = lInNames.getLength();
195 lOutValues.realloc( nSourceSize );
196 auto plOutValues = lOutValues.getArray();
204 nDestinationCounter = 0;
205 for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter )
208 if( lInValues[nSourceCounter].getValueTypeName() ==
"com.sun.star.uno.XInterface" )
210 lInValues[nSourceCounter] >>= xLocalizedNode;
212 if( xSetAccess.is() )
214 lPropertyNames = xSetAccess->getElementNames();
215 nPropertiesSize = lPropertyNames.getLength();
216 lProperties.realloc( nPropertiesSize );
217 auto plProperties = lProperties.getArray();
219 for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter )
221 plProperties[nPropertyCounter].Name = lPropertyNames[nPropertyCounter];
222 OUString sLocaleValue;
223 xSetAccess->getByName( lPropertyNames[nPropertyCounter] ) >>= sLocaleValue;
224 plProperties[nPropertyCounter].Value <<= sLocaleValue;
227 plOutValues[nDestinationCounter] <<= lProperties;
233 plOutValues[nDestinationCounter] = lInValues[nSourceCounter];
235 ++nDestinationCounter;
246 sal_Int32 nSourceSize;
247 sal_Int32 nDestinationCounter;
248 sal_Int32 nPropertiesSize;
260 nSourceSize = lInNames.getLength();
262 lOutNames.realloc ( nSourceSize );
263 auto plOutNames = lOutNames.getArray();
264 lOutValues.realloc ( nSourceSize );
265 auto plOutValues = lOutValues.getArray();
272 nDestinationCounter = 0;
273 for( sal_Int32 nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter )
278 lInValues[nSourceCounter] >>= lProperties;
279 nPropertiesSize = lProperties.getLength();
281 sNodeName = lInNames[nSourceCounter] +
"/";
283 if( (nDestinationCounter+nPropertiesSize) > lOutNames.getLength() )
285 lOutNames.realloc ( nDestinationCounter+nPropertiesSize );
286 plOutNames = lOutNames.getArray();
287 lOutValues.realloc ( nDestinationCounter+nPropertiesSize );
288 plOutValues = lOutValues.getArray();
291 for(
const auto& rProperty : std::as_const(lProperties) )
293 plOutNames [nDestinationCounter] = sNodeName + rProperty.Name;
294 plOutValues[nDestinationCounter] = rProperty.Value;
295 ++nDestinationCounter;
301 if( (nDestinationCounter+1) > lOutNames.getLength() )
303 lOutNames.realloc ( nDestinationCounter+1 );
304 plOutNames = lOutNames.getArray();
305 lOutValues.realloc ( nDestinationCounter+1 );
306 plOutValues = lOutValues.getArray();
309 plOutNames [nDestinationCounter] = lInNames [nSourceCounter];
310 plOutValues[nDestinationCounter] = lInValues[nSourceCounter];
311 ++nDestinationCounter;
322 sal_Int32
nCount = rNames.getLength();
324 sal_Bool* plStates = lStates.getArray();
328 std::fill_n(plStates, lStates.getLength(),
false);
332 if (!xHierarchyAccess.is())
339 OUString
sName = rNames[
i];
344 if (sPath.isEmpty() && sProperty.isEmpty())
346 OSL_FAIL(
"ConfigItem::IsReadonly() split failed");
353 if (!sPath.isEmpty())
355 Any aNode = xHierarchyAccess->getByHierarchicalName(sPath);
356 if (!(aNode >>= xNode) || !xNode.is())
358 OSL_FAIL(
"ConfigItem::IsReadonly() no set available");
364 xNode = xHierarchyAccess;
367 xSet.set(xNode, UNO_QUERY);
370 xInfo = xSet->getPropertySetInfo();
371 OSL_ENSURE(xInfo.is(),
"ConfigItem::IsReadonly() getPropertySetInfo failed ...");
375 xInfo.set(xNode, UNO_QUERY);
376 OSL_ENSURE(xInfo.is(),
"ConfigItem::IsReadonly() UNO_QUERY failed ...");
381 OSL_FAIL(
"ConfigItem::IsReadonly() no prop info available");
385 Property aProp = xInfo->getPropertyByName(sProperty);
386 plStates[
i] = (aProp.Attributes & PropertyAttribute::READONLY) == PropertyAttribute::READONLY;
399 if(xHierarchyAccess.is())
406 css::uno::Reference<css::container::XHierarchicalNameAccess>
const & xHierarchyAccess,
411 const OUString* pNames = rNames.getConstArray();
412 Any* pRet = aRet.getArray();
413 for(
int i = 0;
i < rNames.getLength();
i++)
417 pRet[
i] = xHierarchyAccess->getByHierarchicalName(pNames[i]);
419 catch (
const Exception&)
423 "ignoring XHierarchicalNameAccess " << pNames[i]);
443 bool bRet = xHierarchyAccess.is() && xTopNodeReplace.is();
448 const OUString* pNames =
nullptr;
450 sal_Int32 nNameCount;
458 pNames = lNames.getConstArray ();
459 pValues = lValues.getConstArray ();
460 nNameCount = lNames.getLength ();
466 pNames = rNames.getConstArray ();
467 pValues = rValues.getConstArray ();
468 nNameCount = rNames.getLength ();
470 for(
int i = 0;
i < nNameCount;
i++)
474 OUString sNode, sProperty;
477 Any aNode = xHierarchyAccess->getByHierarchicalName(sNode);
484 bool bExist = (xNodeAcc.is() && xNodeAcc->hasByName(sProperty));
485 if (bExist && xNodeReplace.is())
486 xNodeReplace->replaceByName(sProperty, pValues[i]);
488 if (!bExist && xNodeCont.is())
489 xNodeCont->insertByName(sProperty, pValues[i]);
495 xTopNodeReplace->replaceByName(sProperty, pValues[i]);
498 catch (css::uno::Exception &)
506 xBatch->commitChanges();
508 catch (css::uno::Exception &)
518 css::uno::Reference<css::container::XHierarchicalNameAccess>
const & xHierarchyAccess,
524 bool bRet = xTopNodeReplace.is();
529 const OUString* pNames =
nullptr;
531 sal_Int32 nNameCount;
539 pNames = lNames.getConstArray ();
540 pValues = lValues.getConstArray ();
541 nNameCount = lNames.getLength ();
547 pNames = rNames.getConstArray ();
548 pValues = rValues.getConstArray ();
549 nNameCount = rNames.getLength ();
551 for(
int i = 0;
i < nNameCount;
i++)
555 OUString sNode, sProperty;
558 Any aNode = xHierarchyAccess->getByHierarchicalName(sNode);
565 bool bExist = (xNodeAcc.is() && xNodeAcc->hasByName(sProperty));
566 if (bExist && xNodeReplace.is())
567 xNodeReplace->replaceByName(sProperty, pValues[i]);
569 if (!bExist && xNodeCont.is())
570 xNodeCont->insertByName(sProperty, pValues[i]);
576 xTopNodeReplace->replaceByName(sProperty, pValues[i]);
579 catch (css::uno::Exception &)
587 xBatch->commitChanges();
589 catch (css::uno::Exception &)
600 OSL_ENSURE(
xChangeLstnr.is(),
"ConfigItem::DisableNotification: notifications not enabled currently!" );
605 bool bEnableInternalNotification )
614 OSL_ENSURE(!
xChangeLstnr.is(),
"EnableNotification already called");
634 if(!xHierarchyAccess.is())
662 if (xTypeContainer.is())
664 OUString sTypeName = xTypeContainer->getElementTemplateName();
665 sTypeName = sTypeName.copy(sTypeName.lastIndexOf(
'/')+1);
667 std::transform(std::cbegin(_rNames), std::cend(_rNames), _rNames.getArray(),
668 [&sTypeName](
const OUString& rName) -> OUString { return wrapConfigurationElementName(rName,sTypeName); });
673 if (xSVI.is() && xSVI->supportsService(
"com.sun.star.configuration.SetAccess"))
675 std::transform(std::cbegin(_rNames), std::cend(_rNames), _rNames.getArray(),
676 [](
const OUString& rName) -> OUString { return wrapConfigurationElementName(rName); });
695 if(xHierarchyAccess.is())
701 css::uno::Reference<css::container::XHierarchicalNameAccess>
const & xHierarchyAccess,
702 const OUString& rNode,
711 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
715 xCont.set(xHierarchyAccess, UNO_QUERY);
718 aRet = xCont->getElementNames();
723 catch (css::uno::Exception &)
735 if(xHierarchyAccess.is())
741 css::uno::Reference<css::container::XHierarchicalNameAccess>
const & xHierarchyAccess,
742 const OUString& rNode)
750 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
754 xCont.set(xHierarchyAccess, UNO_QUERY);
759 for(
const OUString& rName : aNames)
763 xCont->removeByName(rName);
765 catch (css::uno::Exception &)
770 xBatch->commitChanges();
773 catch (css::uno::Exception &)
785 if(xHierarchyAccess.is())
792 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
796 xCont.set(xHierarchyAccess, UNO_QUERY);
801 for(
const OUString& rElement : rElements)
803 xCont->removeByName(rElement);
806 xBatch->commitChanges();
808 catch (css::uno::Exception &)
814 catch (css::uno::Exception &)
832 OUString* pSubNodeNames = aSubNodeNames.getArray();
834 OUString sLastSubNode;
835 sal_Int32 nSubIndex = 0;
837 for(
const PropertyValue& rProperty : rValues)
842 if(sLastSubNode != sSubNode)
844 pSubNodeNames[nSubIndex++] = sSubNode;
847 sLastSubNode = sSubNode;
849 aSubNodeNames.realloc(nSubIndex);
851 return aSubNodeNames;
860 if(!xHierarchyAccess.is())
867 css::uno::Reference<css::container::XHierarchicalNameAccess>
const & xHierarchyAccess,
877 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
881 xCont.set(xHierarchyAccess, UNO_QUERY);
891 for(
const auto& rSubNodeName : aSubNodeNames)
893 if(!xCont->hasByName(rSubNodeName))
896 Any aVal; aVal <<= xInst;
897 xCont->insertByName(rSubNodeName, aVal);
903 xBatch->commitChanges();
905 catch (css::uno::Exception &)
910 const PropertyValue* pProperties = rValues.getConstArray();
913 OUString* pSetNames = aSetNames.getArray();
916 Any* pSetValues = aSetValues.getArray();
918 bool bEmptyNode = rNode.isEmpty();
919 for(sal_Int32 k = 0; k < rValues.getLength(); k++)
921 pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0);
922 pSetValues[k] = pProperties[k].Value;
924 bRet =
PutProperties(xHierarchyAccess, aSetNames, aSetValues,
false);
929 for(
const PropertyValue& rValue : rValues)
935 if(xCont->hasByName(sSubNode))
936 xCont->replaceByName(sSubNode, rValue.Value);
938 xCont->insertByName(sSubNode, rValue.Value);
940 OSL_ENSURE( xHierarchyAccess->hasByHierarchicalName(rValue.Name),
941 "Invalid config path" );
943 catch (css::uno::Exception &)
948 xBatch->commitChanges();
951 catch (
const Exception&)
965 if(xHierarchyAccess.is())
972 css::uno::Reference<css::container::XHierarchicalNameAccess>
const & xHierarchyAccess,
973 const OUString& rNode,
984 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
988 xCont.set(xHierarchyAccess, UNO_QUERY);
996 const bool isSimpleValueSet = !xFac.is();
1002 for(
const OUString& rContainerSubNode : aContainerSubNodes)
1008 xCont->removeByName(rContainerSubNode);
1010 catch (
const Exception&)
1012 if (isSimpleValueSet)
1017 xCont->replaceByName(rContainerSubNode,
Any());
1027 try { xBatch->commitChanges(); }
1028 catch (css::uno::Exception &)
1036 for(
const OUString& rSubNodeName : aSubNodeNames)
1038 if(!xCont->hasByName(rSubNodeName))
1042 Any aVal; aVal <<= xInst;
1043 xCont->insertByName(rSubNodeName, aVal);
1046 try { xBatch->commitChanges(); }
1047 catch (css::uno::Exception &)
1052 const PropertyValue* pProperties = rValues.getConstArray();
1055 OUString* pSetNames = aSetNames.getArray();
1058 Any* pSetValues = aSetValues.getArray();
1060 bool bEmptyNode = rNode.isEmpty();
1061 for(sal_Int32 k = 0; k < rValues.getLength(); k++)
1063 pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0);
1064 pSetValues[k] = pProperties[k].Value;
1066 bRet =
PutProperties(xHierarchyAccess, aSetNames, aSetValues, bAllLocales);
1071 for(
const PropertyValue& rValue : rValues)
1077 if(xCont->hasByName(sSubNode))
1078 xCont->replaceByName(sSubNode, rValue.Value);
1080 xCont->insertByName(sSubNode, rValue.Value);
1082 catch (css::uno::Exception &)
1087 xBatch->commitChanges();
1090 catch (
const Exception& )
1103 if(xHierarchyAccess.is())
1109 if(!rNode.isEmpty())
1111 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
1115 xCont.set(xHierarchyAccess, UNO_QUERY);
1123 if(!xCont->hasByName(rNewNode))
1126 Any aVal; aVal <<= xInst;
1127 xCont->insertByName(rNewNode, aVal);
1131 xBatch->commitChanges();
1133 catch (css::uno::Exception &)
1143 if(!xCont->hasByName(rNewNode))
1144 xCont->insertByName(rNewNode,
Any());
1146 catch (css::uno::Exception &)
1151 xBatch->commitChanges();
const PropertyValue * pValues
static SolarMutex * get()
ConfigChangeListener_Impl(ConfigItem &rItem, const Sequence< OUString > &rNames)
virtual void SAL_CALL changesOccurred(const ChangesEvent &Event) override
const Sequence< OUString > aPropertyNames
virtual void SAL_CALL disposing(const EventObject &Source) override
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
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)
css::uno::Reference< css::container::XHierarchicalNameAccess > GetTree()
bool SetSetProperties(const OUString &rNode, const css::uno::Sequence< css::beans::PropertyValue > &rValues)
css::uno::Sequence< OUString > GetNodeNames(const OUString &rNode)
virtual ~ConfigItem() override
sal_Int16 m_nInValueChange
void CallNotify(const css::uno::Sequence< OUString > &aPropertyNames)
bool EnableNotification(const css::uno::Sequence< OUString > &rNames, bool bEnableInternalNotification=false)
enables notifications about changes on selected sub nodes/values
virtual void Notify(const css::uno::Sequence< OUString > &aPropertyNames)=0
is called from the ConfigManager before application ends of from the PropertyChangeListener if the su...
void DisableNotification()
disables notifications about changes on sub nodes/values, which previously had been enabled with Enab...
void RemoveChangesListener()
virtual void ImplCommit()=0
writes the changed values into the sub tree.
css::uno::Reference< css::util::XChangesListener > xChangeLstnr
css::uno::Reference< css::container::XHierarchicalNameAccess > m_xHierarchyAccess
bool m_bEnableInternalNotification
friend class ConfigChangeListener_Impl
bool PutProperties(const css::uno::Sequence< OUString > &rNames, const css::uno::Sequence< css::uno::Any > &rValues)
ConfigItem(OUString aSubTree, ConfigItemMode nMode=ConfigItemMode::NONE)
bool ReplaceSetProperties(const OUString &rNode, const css::uno::Sequence< css::beans::PropertyValue > &rValues)
css::uno::Sequence< sal_Bool > GetReadOnlyStates(const css::uno::Sequence< OUString > &rNames)
bool ClearNodeElements(const OUString &rNode, css::uno::Sequence< OUString > const &rElements)
bool ClearNodeSet(const OUString &rNode)
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)
bool AddNode(const OUString &rNode, const OUString &rNewNode)
SAL_DLLPRIVATE css::uno::Reference< css::container::XHierarchicalNameAccess > addConfigItem(utl::ConfigItem &item)
SAL_DLLPRIVATE void removeConfigItem(utl::ConfigItem &item)
static SAL_DLLPRIVATE css::uno::Reference< css::container::XHierarchicalNameAccess > acquireTree(utl::ConfigItem const &item)
static SAL_DLLPRIVATE ConfigManager & getConfigManager()
static OUString lcl_extractSetPropertyName(const OUString &rInPath, std::u16string_view rPrefix)
static Sequence< OUString > lcl_extractSetPropertyNames(const Sequence< PropertyValue > &rValues, std::u16string_view rPrefix)
static void lcl_normalizeLocalNames(Sequence< OUString > &_rNames, ConfigNameFormat _eFormat, Reference< XInterface > const &_xParentNode)
#define suppress_fun_call_w_exception(expr)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
OUString get(TranslateId sContextAndId, const std::locale &loc)
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
OUString extractFirstFromConfigurationPath(OUString const &_sInPath, OUString *_sOutPath)
extract the first nodename from a configuration path.
OUString dropPrefixFromConfigurationPath(OUString const &_sNestedPath, std::u16string_view _sPrefixPath)
get the relative path to a nested node with respect to a parent path.
bool splitLastFromConfigurationPath(std::u16string_view _sInPath, OUString &_rsOutPath, OUString &_rsLocalName)
extract the local nodename and the parent nodepath from a configuration path.