LibreOffice Module comphelper (master) 1
propshlp.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <osl/diagnose.h>
25#include <com/sun/star/beans/PropertyAttribute.hpp>
26#include <com/sun/star/lang/DisposedException.hpp>
27#include <com/sun/star/lang/IllegalArgumentException.hpp>
28#include <memory>
29#include <sal/log.hxx>
30
31using namespace osl;
32using namespace com::sun::star::uno;
33using namespace com::sun::star::beans;
34using namespace com::sun::star::lang;
35using namespace cppu;
36
37namespace comphelper
38{
39extern "C" {
40
41static int compare_OUString_Property_Impl(const void* arg1, const void* arg2) SAL_THROW_EXTERN_C()
42{
43 return static_cast<OUString const*>(arg1)->compareTo(static_cast<Property const*>(arg2)->Name);
44}
45}
46
51namespace
52{
53class OPropertySetHelperInfo_Impl : public WeakImplHelper<css::beans::XPropertySetInfo>
54{
56
57public:
58 explicit OPropertySetHelperInfo_Impl(IPropertyArrayHelper& rHelper_);
59
60 // XPropertySetInfo-methods
61 virtual Sequence<Property> SAL_CALL getProperties() override;
62 virtual Property SAL_CALL getPropertyByName(const OUString& PropertyName) override;
63 virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& PropertyName) override;
64};
65}
66
70OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(IPropertyArrayHelper& rHelper_)
71 : aInfos(rHelper_.getProperties())
72{
73}
74
78Sequence<Property> OPropertySetHelperInfo_Impl::getProperties() { return aInfos; }
79
83Property OPropertySetHelperInfo_Impl::getPropertyByName(const OUString& PropertyName)
84{
85 Property* pR
86 = static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(),
87 sizeof(Property), compare_OUString_Property_Impl));
88 if (!pR)
89 throw UnknownPropertyException(PropertyName);
90
91 return *pR;
92}
93
97sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName(const OUString& PropertyName)
98{
99 Property* pR
100 = static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(),
101 sizeof(Property), compare_OUString_Property_Impl));
102 return pR != nullptr;
103}
104
105OPropertySetHelper::OPropertySetHelper() {}
106
107OPropertySetHelper::OPropertySetHelper(bool bIgnoreRuntimeExceptionsWhileFiring)
108 : m_bIgnoreRuntimeExceptionsWhileFiring(bIgnoreRuntimeExceptionsWhileFiring)
109{
110}
111
116
117// XInterface
118Any OPropertySetHelper::queryInterface(const css::uno::Type& rType)
119{
120 return ::cppu::queryInterface(rType, static_cast<XPropertySet*>(this),
121 static_cast<XMultiPropertySet*>(this),
122 static_cast<XFastPropertySet*>(this));
123}
124
128css::uno::Sequence<css::uno::Type> OPropertySetHelper::getTypes()
129{
133}
134
135// ComponentHelper
136void OPropertySetHelper::disposing(std::unique_lock<std::mutex>& rGuard)
137{
138 // Create an event with this as sender
139 Reference<XPropertySet> rSource = this;
140 EventObject aEvt;
141 aEvt.Source = rSource;
142
143 // inform all listeners to release this object
144 // The listener containers are automatically cleared
145 aBoundLC.disposeAndClear(rGuard, aEvt);
146 aVetoableLC.disposeAndClear(rGuard, aEvt);
147}
148
151{
152 return new OPropertySetHelperInfo_Impl(rProperties);
153}
154
155// XPropertySet
156void OPropertySetHelper::setPropertyValue(const OUString& rPropertyName, const Any& rValue)
157{
158 // get the map table
160 // map the name to the handle
161 sal_Int32 nHandle = rPH.getHandleByName(rPropertyName);
162 std::unique_lock aGuard(m_aMutex);
163 setFastPropertyValueImpl(aGuard, nHandle, rValue);
164}
165
166// XPropertySet
167Any OPropertySetHelper::getPropertyValue(const OUString& rPropertyName)
168{
169 std::unique_lock aGuard(m_aMutex);
170 return getPropertyValueImpl(aGuard, rPropertyName);
171}
172
173Any OPropertySetHelper::getPropertyValueImpl(std::unique_lock<std::mutex>& rGuard,
174 const OUString& rPropertyName)
175{
176 // get the map table
178 // map the name to the handle
179 sal_Int32 nHandle = rPH.getHandleByName(rPropertyName);
180 // call the method of the XFastPropertySet interface
181 Any aAny;
182 getFastPropertyValue(rGuard, aAny, nHandle);
183 return aAny;
184}
185
186// XPropertySet
188 const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener)
189{
190 std::unique_lock aGuard(m_aMutex);
191 OSL_ENSURE(!m_bDisposed, "object is disposed");
192 if (m_bDisposed)
193 return;
194
195 // only add listeners if you are not disposed
196 // a listener with no name means all properties
197 if (!rPropertyName.isEmpty())
198 {
199 // get the map table
201 // map the name to the handle
202 sal_Int32 nHandle = rPH.getHandleByName(rPropertyName);
203 if (nHandle == -1)
204 {
205 // property not known throw exception
206 throw UnknownPropertyException(rPropertyName);
207 }
208
209 sal_Int16 nAttributes;
210 rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle);
211 if (!(nAttributes & css::beans::PropertyAttribute::BOUND))
212 {
213 OSL_FAIL("add listener to an unbound property");
214 // silent ignore this
215 return;
216 }
217 // add the change listener to the helper container
218 aBoundLC.addInterface(aGuard, nHandle, rxListener);
219 }
220 else
221 // add the change listener to the helper container
222 maPropertyChangeListeners.addInterface(aGuard, rxListener);
223}
224
225// XPropertySet
227 const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener)
228{
229 std::unique_lock aGuard(m_aMutex);
230 OSL_ENSURE(!m_bDisposed, "object is disposed");
231 // all listeners are automatically released in a dispose call
232 if (m_bDisposed)
233 return;
234
235 if (!rPropertyName.isEmpty())
236 {
237 // get the map table
239 // map the name to the handle
240 sal_Int32 nHandle = rPH.getHandleByName(rPropertyName);
241 if (nHandle == -1)
242 // property not known throw exception
243 throw UnknownPropertyException(rPropertyName);
244 aBoundLC.removeInterface(aGuard, nHandle, rxListener);
245 }
246 else
247 {
248 // remove the change listener to the helper container
249 maPropertyChangeListeners.removeInterface(aGuard, rxListener);
250 }
251}
252
253// XPropertySet
255 const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener)
256{
257 std::unique_lock aGuard(m_aMutex);
258 OSL_ENSURE(!m_bDisposed, "object is disposed");
259 if (m_bDisposed)
260 return;
261
262 // only add listeners if you are not disposed
263 // a listener with no name means all properties
264 if (!rPropertyName.isEmpty())
265 {
266 // get the map table
268 // map the name to the handle
269 sal_Int32 nHandle = rPH.getHandleByName(rPropertyName);
270 if (nHandle == -1)
271 {
272 // property not known throw exception
273 throw UnknownPropertyException(rPropertyName);
274 }
275
276 sal_Int16 nAttributes;
277 rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle);
278 if (!(nAttributes & PropertyAttribute::CONSTRAINED))
279 {
280 OSL_FAIL("addVetoableChangeListener, and property is not constrained");
281 // silent ignore this
282 return;
283 }
284 // add the vetoable listener to the helper container
285 aVetoableLC.addInterface(aGuard, nHandle, rxListener);
286 }
287 else
288 // add the vetoable listener to the helper container
289 maVetoableChangeListeners.addInterface(aGuard, rxListener);
290}
291
292// XPropertySet
294 const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener)
295{
296 std::unique_lock aGuard(m_aMutex);
297 OSL_ENSURE(!m_bDisposed, "object is disposed");
298 // all listeners are automatically released in a dispose call
299 if (m_bDisposed)
300 return;
301
302 if (!rPropertyName.isEmpty())
303 {
304 // get the map table
306 // map the name to the handle
307 sal_Int32 nHandle = rPH.getHandleByName(rPropertyName);
308 if (nHandle == -1)
309 {
310 // property not known throw exception
311 throw UnknownPropertyException(rPropertyName);
312 }
313 // remove the vetoable listener to the helper container
314 aVetoableLC.removeInterface(aGuard, nHandle, rxListener);
315 }
316 else
317 // add the vetoable listener to the helper container
318 maVetoableChangeListeners.removeInterface(aGuard, rxListener);
319}
320
321void OPropertySetHelper::setDependentFastPropertyValue(std::unique_lock<std::mutex>& rGuard,
322 sal_Int32 i_handle,
323 const css::uno::Any& i_value)
324{
325 sal_Int16 nAttributes(0);
327 if (!rInfo.fillPropertyMembersByHandle(nullptr, &nAttributes, i_handle))
328 // unknown property
329 throw UnknownPropertyException(OUString::number(i_handle));
330
331 // no need to check for READONLY-ness of the property. The method is intended to be called internally, which
332 // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed
333 // to change their value.
334
335 Any aConverted, aOld;
336 bool bChanged = convertFastPropertyValue(rGuard, aConverted, aOld, i_handle, i_value);
337 if (!bChanged)
338 return;
339
340 // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be
341 // a good idea. The caller is responsible for not invoking this for constrained properties.
342 OSL_ENSURE((nAttributes & PropertyAttribute::CONSTRAINED) == 0,
343 "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained "
344 "properties!");
345
346 // actually set the new value
347 try
348 {
349 setFastPropertyValue_NoBroadcast(rGuard, i_handle, aConverted);
350 }
351 catch (const UnknownPropertyException&)
352 {
353 throw; /* allowed to leave */
354 }
355 catch (const PropertyVetoException&)
356 {
357 throw; /* allowed to leave */
358 }
359 catch (const IllegalArgumentException&)
360 {
361 throw; /* allowed to leave */
362 }
363 catch (const WrappedTargetException&)
364 {
365 throw; /* allowed to leave */
366 }
367 catch (const RuntimeException&)
368 {
369 throw; /* allowed to leave */
370 }
371 catch (const Exception&)
372 {
373 // not allowed to leave this method
374 WrappedTargetException aWrapped;
375 aWrapped.TargetException = ::cppu::getCaughtException();
376 aWrapped.Context = static_cast<XPropertySet*>(this);
377 throw aWrapped;
378 }
379
380 // remember the handle/values, for the events to be fired later
381 m_handles.push_back(i_handle);
382 m_newValues.push_back(
383 aConverted); // TODO: setFastPropertyValue notifies the unconverted value here ...?
384 m_oldValues.push_back(aOld);
385}
386
387// XFastPropertySet
388void OPropertySetHelper::setFastPropertyValue(sal_Int32 nHandle, const Any& rValue)
389{
390 std::unique_lock aGuard(m_aMutex);
391 setFastPropertyValueImpl(aGuard, nHandle, rValue);
392}
393
394void OPropertySetHelper::setFastPropertyValueImpl(std::unique_lock<std::mutex>& rGuard,
395 sal_Int32 nHandle, const Any& rValue)
396{
397 OSL_ENSURE(!m_bDisposed, "object is disposed");
398
400 sal_Int16 nAttributes;
401 if (!rInfo.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle))
402 {
403 // unknown property
404 throw UnknownPropertyException(OUString::number(nHandle));
405 }
406 if (nAttributes & PropertyAttribute::READONLY)
407 throw PropertyVetoException();
408
409 Any aConvertedVal;
410 Any aOldVal;
411
412 // Will the property change?
413 bool bChanged = convertFastPropertyValue(rGuard, aConvertedVal, aOldVal, nHandle, rValue);
414 if (!bChanged)
415 return;
416
417 // Is it a constrained property?
418 if (nAttributes & PropertyAttribute::CONSTRAINED)
419 {
420 // In aValue is the converted rValue
421 // fire a constrained event
422 // second parameter NULL means constrained
423 fire(rGuard, &nHandle, &rValue, &aOldVal, 1, true);
424 }
425
426 try
427 {
428 // set the property to the new value
429 setFastPropertyValue_NoBroadcast(rGuard, nHandle, aConvertedVal);
430 }
431 catch (const css::beans::UnknownPropertyException&)
432 {
433 throw; /* allowed to leave */
434 }
435 catch (const css::beans::PropertyVetoException&)
436 {
437 throw; /* allowed to leave */
438 }
439 catch (const css::lang::IllegalArgumentException&)
440 {
441 throw; /* allowed to leave */
442 }
443 catch (const css::lang::WrappedTargetException&)
444 {
445 throw; /* allowed to leave */
446 }
447 catch (const css::uno::RuntimeException&)
448 {
449 throw; /* allowed to leave */
450 }
451 catch (const css::uno::Exception& e)
452 {
453 // not allowed to leave this method
454 css::lang::WrappedTargetException aWrap;
455 aWrap.Context = static_cast<css::beans::XPropertySet*>(this);
456 aWrap.TargetException <<= e;
457
458 throw aWrap;
459 }
460
461 // file a change event, if the value changed
462 impl_fireAll(rGuard, &nHandle, &rValue, &aOldVal, 1);
463}
464
465// XFastPropertySet
467{
469 if (!rInfo.fillPropertyMembersByHandle(nullptr, nullptr, nHandle))
470 // unknown property
471 throw UnknownPropertyException(OUString::number(nHandle));
472
473 Any aRet;
474 std::unique_lock aGuard(m_aMutex);
475 getFastPropertyValue(aGuard, aRet, nHandle);
476 return aRet;
477}
478
479void OPropertySetHelper::impl_fireAll(std::unique_lock<std::mutex>& rGuard, sal_Int32* i_handles,
480 const Any* i_newValues, const Any* i_oldValues,
481 sal_Int32 i_count)
482{
483 if (m_handles.empty())
484 {
485 fire(rGuard, i_handles, i_newValues, i_oldValues, i_count, false);
486 return;
487 }
488
489 const size_t additionalEvents = m_handles.size();
490 OSL_ENSURE(additionalEvents == m_newValues.size() && additionalEvents == m_oldValues.size(),
491 "OPropertySetHelper::impl_fireAll: inconsistency!");
492
493 std::vector<sal_Int32> allHandles(additionalEvents + i_count);
494 std::copy(m_handles.begin(), m_handles.end(), allHandles.begin());
495 std::copy(i_handles, i_handles + i_count, allHandles.begin() + additionalEvents);
496
497 std::vector<Any> allNewValues(additionalEvents + i_count);
498 std::copy(m_newValues.begin(), m_newValues.end(), allNewValues.begin());
499 std::copy(i_newValues, i_newValues + i_count, allNewValues.begin() + additionalEvents);
500
501 std::vector<Any> allOldValues(additionalEvents + i_count);
502 std::copy(m_oldValues.begin(), m_oldValues.end(), allOldValues.begin());
503 std::copy(i_oldValues, i_oldValues + i_count, allOldValues.begin() + additionalEvents);
504
505 m_handles.clear();
506 m_newValues.clear();
507 m_oldValues.clear();
508
509 fire(rGuard, allHandles.data(), allNewValues.data(), allOldValues.data(),
510 additionalEvents + i_count, false);
511}
512
513void OPropertySetHelper::fire(std::unique_lock<std::mutex>& rGuard, sal_Int32* pnHandles,
514 const Any* pNewValues, const Any* pOldValues,
515 sal_Int32 nHandles, // This is the Count of the array
516 bool bVetoable)
517{
518 // Only fire, if one or more properties changed
519 if (!nHandles)
520 return;
521
522 // create the event sequence of all changed properties
523 Sequence<PropertyChangeEvent> aEvts(nHandles);
524 PropertyChangeEvent* pEvts = aEvts.getArray();
525 Reference<XInterface> xSource(static_cast<XPropertySet*>(this), UNO_QUERY);
526 sal_Int32 i;
527 sal_Int32 nChangesLen = 0;
528 // Loop over all changed properties to fill the event struct
529 for (i = 0; i < nHandles; i++)
530 {
531 // Vetoable fire and constrained attribute set or
532 // Change fire and Changed and bound attribute set
534 sal_Int16 nAttributes;
535 OUString aPropName;
536 rInfo.fillPropertyMembersByHandle(&aPropName, &nAttributes, pnHandles[i]);
537
538 if ((bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED))
539 || (!bVetoable && (nAttributes & PropertyAttribute::BOUND)))
540 {
541 pEvts[nChangesLen].Source = xSource;
542 pEvts[nChangesLen].PropertyName = aPropName;
543 pEvts[nChangesLen].PropertyHandle = pnHandles[i];
544 pEvts[nChangesLen].OldValue = pOldValues[i];
545 pEvts[nChangesLen].NewValue = pNewValues[i];
546 nChangesLen++;
547 }
548 }
549
550 bool bIgnoreRuntimeExceptionsWhileFiring = m_bIgnoreRuntimeExceptionsWhileFiring;
551
552 // fire the events for all changed properties
553 for (i = 0; i < nChangesLen; i++)
554 {
555 if (bVetoable) // fire change Events?
557 rGuard, aVetoableLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]);
558 else
559 // get the listener container for the property name
561 rGuard, aBoundLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]);
562
563 // broadcast to all listeners with "" property name
564 if (bVetoable)
565 // fire change Events?
567 else
569 }
570
571 // reduce array to changed properties
572 aEvts.realloc(nChangesLen);
573
574 if (bVetoable)
575 return;
576
578 return;
579
580 // Here is a Bug, unbound properties are also fired
581 OInterfaceIteratorHelper4 aIt(rGuard, maPropertiesChangeListeners);
582 rGuard.unlock();
583 while (aIt.hasMoreElements())
584 {
585 XPropertiesChangeListener* pL = aIt.next().get();
586 try
587 {
588 try
589 {
590 // fire the whole event sequence to the
591 // XPropertiesChangeListener's
592 pL->propertiesChange(aEvts);
593 }
594 catch (DisposedException& exc)
595 {
596 OSL_ENSURE(exc.Context.is(), "DisposedException without Context!");
597 if (exc.Context == pL)
598 {
599 rGuard.lock();
600 aIt.remove(rGuard);
601 rGuard.unlock();
602 }
603 else
604 throw;
605 }
606 }
607 catch (RuntimeException& exc)
608 {
609 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc);
610 if (!bIgnoreRuntimeExceptionsWhileFiring)
611 throw;
612 }
613 }
614 rGuard.lock();
615}
616
618 std::unique_lock<std::mutex>& rGuard,
620 const css::beans::PropertyChangeEvent& rChangeEvent)
621{
622 if (!pListeners || !pListeners->getLength(rGuard))
623 return;
624 // Iterate over all listeners and send events
625 OInterfaceIteratorHelper4 aIt(rGuard, *pListeners);
626 rGuard.unlock();
627 while (aIt.hasMoreElements())
628 {
629 XVetoableChangeListener* pL = aIt.next().get();
630 try
631 {
632 try
633 {
634 pL->vetoableChange(rChangeEvent);
635 }
636 catch (DisposedException& exc)
637 {
638 OSL_ENSURE(exc.Context.is(), "DisposedException without Context!");
639 if (exc.Context == pL)
640 {
641 rGuard.lock();
642 aIt.remove(rGuard);
643 rGuard.unlock();
644 }
645 else
646 throw;
647 }
648 }
649 catch (RuntimeException& exc)
650 {
651 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc);
653 throw;
654 }
655 }
656 rGuard.lock();
657}
658
660 std::unique_lock<std::mutex>& rGuard,
662 const css::beans::PropertyChangeEvent& rChangeEvent)
663{
664 if (!pListeners || !pListeners->getLength(rGuard))
665 return;
666 // Iterate over all listeners and send events
667 OInterfaceIteratorHelper4 aIt(rGuard, *pListeners);
668 rGuard.unlock();
669 while (aIt.hasMoreElements())
670 {
671 XPropertyChangeListener* pL = aIt.next().get();
672 try
673 {
674 try
675 {
676 pL->propertyChange(rChangeEvent);
677 }
678 catch (DisposedException& exc)
679 {
680 OSL_ENSURE(exc.Context.is(), "DisposedException without Context!");
681 if (exc.Context == pL)
682 {
683 rGuard.lock();
684 aIt.remove(rGuard);
685 rGuard.unlock();
686 }
687 else
688 throw;
689 }
690 }
691 catch (RuntimeException& exc)
692 {
693 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc);
695 throw;
696 }
697 }
698 rGuard.lock();
699}
700
701// OPropertySetHelper
702void OPropertySetHelper::setFastPropertyValues(std::unique_lock<std::mutex>& rGuard,
703 sal_Int32 nSeqLen, sal_Int32* pHandles,
704 const Any* pValues, sal_Int32 nHitCount)
705{
706 OSL_ENSURE(!m_bDisposed, "object is disposed");
707
708 // get the map table
710
711 std::unique_ptr<Any[]> pConvertedValues(new Any[nHitCount]);
712 std::unique_ptr<Any[]> pOldValues(new Any[nHitCount]);
713 sal_Int32 n = 0;
714 sal_Int32 i;
715
716 for (i = 0; i < nSeqLen; i++)
717 {
718 if (pHandles[i] != -1)
719 {
720 sal_Int16 nAttributes;
721 rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, pHandles[i]);
722 if (nAttributes & PropertyAttribute::READONLY)
723 throw PropertyVetoException();
724 // Will the property change?
725 if (convertFastPropertyValue(rGuard, pConvertedValues[n], pOldValues[n], pHandles[i],
726 pValues[i]))
727 {
728 // only increment if the property really change
729 pHandles[n] = pHandles[i];
730 n++;
731 }
732 }
733 }
734
735 // fire vetoable events
736 fire(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n, true);
737
738 // Loop over all changed properties
739 for (i = 0; i < n; i++)
740 {
741 // Will the property change?
742 setFastPropertyValue_NoBroadcast(rGuard, pHandles[i], pConvertedValues[i]);
743 }
744
745 // fire change events
746 impl_fireAll(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n);
747}
748
749// XMultiPropertySet
755 const Sequence<Any>& rValues)
756{
757 sal_Int32 nSeqLen = rPropertyNames.getLength();
758 if (nSeqLen != rValues.getLength())
759 throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet*>(this),
760 -1);
761 std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nSeqLen]);
762 // get the map table
764 // fill the handle array
765 sal_Int32 nHitCount = rPH.fillHandles(pHandles.get(), rPropertyNames);
766 if (nHitCount == 0)
767 return;
768 std::unique_lock aGuard(m_aMutex);
769 setFastPropertyValues(aGuard, nSeqLen, pHandles.get(), rValues.getConstArray(), nHitCount);
770}
771
772// XMultiPropertySet
774{
775 sal_Int32 nSeqLen = rPropertyNames.getLength();
776 std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nSeqLen]);
777 Sequence<Any> aValues(nSeqLen);
778
779 // get the map table
781 // fill the handle array
782 rPH.fillHandles(pHandles.get(), rPropertyNames);
783
784 Any* pValues = aValues.getArray();
785
786 std::unique_lock aGuard(m_aMutex);
787 // fill the sequence with the values
788 for (sal_Int32 i = 0; i < nSeqLen; i++)
789 getFastPropertyValue(aGuard, pValues[i], pHandles[i]);
790
791 return aValues;
792}
793
794// XMultiPropertySet
797{
798 std::unique_lock g(m_aMutex);
800}
801
802// XMultiPropertySet
805{
806 std::unique_lock g(m_aMutex);
808}
809
810// XMultiPropertySet
812 const Sequence<OUString>& rPropertyNames, const Reference<XPropertiesChangeListener>& rListener)
813{
814 sal_Int32 nLen = rPropertyNames.getLength();
815 std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nLen]);
817 rPH.fillHandles(pHandles.get(), rPropertyNames);
818 const OUString* pNames = rPropertyNames.getConstArray();
819
820 // get the count of matching properties
821 sal_Int32 nFireLen = 0;
822 sal_Int32 i;
823 for (i = 0; i < nLen; i++)
824 if (pHandles[i] != -1)
825 nFireLen++;
826
827 Sequence<PropertyChangeEvent> aChanges(nFireLen);
828 PropertyChangeEvent* pChanges = aChanges.getArray();
829
830 {
831 // must lock the mutex outside the loop. So all values are consistent.
832 std::unique_lock aGuard(m_aMutex);
833 Reference<XInterface> xSource(static_cast<XPropertySet*>(this), UNO_QUERY);
834 sal_Int32 nFirePos = 0;
835 for (i = 0; i < nLen; i++)
836 {
837 if (pHandles[i] != -1)
838 {
839 pChanges[nFirePos].Source = xSource;
840 pChanges[nFirePos].PropertyName = pNames[i];
841 pChanges[nFirePos].PropertyHandle = pHandles[i];
842 getFastPropertyValue(aGuard, pChanges[nFirePos].OldValue, pHandles[i]);
843 pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue;
844 nFirePos++;
845 }
846 }
847 // release guard to fire events
848 }
849 if (nFireLen)
850 rListener->propertiesChange(aChanges);
851}
852
854
855} // end namespace comphelper
856
857/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
sal_Int32 addInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
Inserts an element into the container.
sal_Int32 getLength(std::unique_lock< std::mutex > &rGuard) const
Return the number of Elements in the container.
sal_Int32 removeInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
Removes an element from the container.
This is the iterator of an OInterfaceContainerHelper4.
bool hasMoreElements() const
Return true, if there are more elements in the iterator.
css::uno::Reference< ListenerT > const & next()
Return the next element of the iterator.
void remove(::std::unique_lock<::std::mutex > &rGuard)
Removes the current element (the last one returned by next()) from the underlying container.
sal_Int32 removeInterface(::std::unique_lock<::std::mutex > &rGuard, const key &rKey, const css::uno::Reference< listener > &rListener)
Removes an element from the container with the specified key.
sal_Int32 addInterface(::std::unique_lock<::std::mutex > &rGuard, const key &rKey, const css::uno::Reference< listener > &rListener)
Inserts an element into the container with the specified key.
void disposeAndClear(std::unique_lock< std::mutex > &rGuard, const css::lang::EventObject &rEvt)
Call disposing on all references in the container, that support XEventListener.
OInterfaceContainerHelper4< listener > * getContainer(std::unique_lock< std::mutex > &rGuard, const key &rKey) const
Return the container created under this key.
std::vector< sal_Int32 > m_handles
Definition: propshlp.hxx:301
virtual void SAL_CALL removePropertyChangeListener(const ::rtl::OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &aListener) override final
Ignored if the property is not bound.
comphelper::OInterfaceContainerHelper4< css::beans::XVetoableChangeListener > maVetoableChangeListeners
Container for the XVetoableChangeListener where the listeners want to listen to all properties.
Definition: propshlp.hxx:300
void firePropertyChangeListeners(std::unique_lock< std::mutex > &rGuard, comphelper::OInterfaceContainerHelper4< css::beans::XPropertyChangeListener > *pListeners, const css::beans::PropertyChangeEvent &rChangeEvent)
Definition: propshlp.cxx:659
virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyValues(const css::uno::Sequence<::rtl::OUString > &PropertyNames) override final
std::vector< css::uno::Any > m_oldValues
Definition: propshlp.hxx:303
virtual bool convertFastPropertyValue(std::unique_lock< std::mutex > &rGuard, css::uno::Any &rConvertedValue, css::uno::Any &rOldValue, sal_Int32 nHandle, const css::uno::Any &rValue)=0
Converted the value rValue and return the result in rConvertedValue and the old value in rOldValue.
virtual css::uno::Any SAL_CALL getPropertyValue(const ::rtl::OUString &aPropertyName) override final
Throw UnknownPropertyException if the property with the name rPropertyName does not exist.
virtual void SAL_CALL removeVetoableChangeListener(const ::rtl::OUString &aPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override final
Ignored if the property is not constrained.
void disposing(std::unique_lock< std::mutex > &rGuard)
Send a disposing notification to the listeners.
Definition: propshlp.cxx:136
virtual void SAL_CALL setPropertyValue(const ::rtl::OUString &rPropertyName, const css::uno::Any &aValue) override final
Throw UnknownPropertyException or PropertyVetoException if the property with the name rPropertyName d...
virtual void SAL_CALL addPropertyChangeListener(const ::rtl::OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &aListener) override final
Ignored if the property is not bound.
static css::uno::Reference< css::beans::XPropertySetInfo > createPropertySetInfo(cppu::IPropertyArrayHelper &rProperties)
The property sequence is created in the call.
Definition: propshlp.cxx:150
OMultiTypeInterfaceContainerHelperVar4< sal_Int32, css::beans::XVetoableChangeListener > aVetoableLC
Container for the XPropertyVetoableListener.
Definition: propshlp.hxx:288
virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override final
Definition: propshlp.cxx:466
void impl_fireAll(std::unique_lock< std::mutex > &rGuard, sal_Int32 *i_handles, const css::uno::Any *i_newValues, const css::uno::Any *i_oldValues, sal_Int32 i_count)
notifies the given changes in property's values, plus all property changes collected during recent |s...
std::vector< css::uno::Any > m_newValues
Definition: propshlp.hxx:302
void setFastPropertyValues(std::unique_lock< std::mutex > &rGuard, sal_Int32 nSeqLen, sal_Int32 *pHandles, const css::uno::Any *pValues, sal_Int32 nHitCount)
Set multiple properties with the handles.
virtual void SAL_CALL removePropertiesChangeListener(const css::uno::Reference< css::beans::XPropertiesChangeListener > &Listener) override final
comphelper::OInterfaceContainerHelper4< css::beans::XPropertyChangeListener > maPropertyChangeListeners
Container for the XPropertyChangedListener where the listeners want to listen to all properties.
Definition: propshlp.hxx:293
void fireVetoableChangeListeners(std::unique_lock< std::mutex > &rGuard, comphelper::OInterfaceContainerHelper4< css::beans::XVetoableChangeListener > *pListeners, const css::beans::PropertyChangeEvent &rChangeEvent)
Definition: propshlp.cxx:617
virtual void SAL_CALL addPropertiesChangeListener(const css::uno::Sequence<::rtl::OUString > &PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener > &Listener) override final
virtual void setFastPropertyValueImpl(std::unique_lock< std::mutex > &rGuard, sal_Int32 nHandle, const css::uno::Any &rValue)
Override this if you need to do something special during setFastPropertyValue.
Definition: propshlp.cxx:394
void setDependentFastPropertyValue(std::unique_lock< std::mutex > &rGuard, sal_Int32 i_handle, const css::uno::Any &i_value)
sets an dependent property's value
Definition: propshlp.cxx:321
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
Only returns a reference to XMultiPropertySet, XFastPropertySet, XPropertySet and XEventListener.
Definition: propshlp.cxx:118
virtual css::uno::Any getPropertyValueImpl(std::unique_lock< std::mutex > &rGuard, const ::rtl::OUString &aPropertyName)
Override this if you need to do something special during getPropertyValue.
Definition: propshlp.cxx:173
virtual void SAL_CALL firePropertiesChangeEvent(const css::uno::Sequence<::rtl::OUString > &PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener > &Listener) override final
virtual void setFastPropertyValue_NoBroadcast(std::unique_lock< std::mutex > &rGuard, sal_Int32 nHandle, const css::uno::Any &rValue)=0
The same as setFastPropertyValue; nHandle is always valid.
virtual void SAL_CALL setPropertyValues(const css::uno::Sequence<::rtl::OUString > &PropertyNames, const css::uno::Sequence< css::uno::Any > &Values) override
virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const css::uno::Any &rValue) override final
Throw UnknownPropertyException or PropertyVetoException if the property with the name rPropertyName d...
static css::uno::Sequence< css::uno::Type > getTypes()
eases implementing XTypeProvider::getTypes, returns the types of XMultiPropertySet,...
Definition: propshlp.cxx:128
comphelper::OInterfaceContainerHelper4< css::beans::XPropertiesChangeListener > maPropertiesChangeListeners
Definition: propshlp.hxx:295
virtual cppu::IPropertyArrayHelper & getInfoHelper()=0
This abstract method must return the name to index table.
void fire(std::unique_lock< std::mutex > &rGuard, sal_Int32 *pnHandles, const css::uno::Any *pNewValues, const css::uno::Any *pOldValues, sal_Int32 nCount, bool bVetoable)
This method fire events to all registered property listeners.
~OPropertySetHelper()
You must call disposing() before destruction.
Definition: propshlp.cxx:115
OMultiTypeInterfaceContainerHelperVar4< sal_Int32, css::beans::XPropertyChangeListener > aBoundLC
Container for the XPropertyChangedListener.
Definition: propshlp.hxx:283
virtual void SAL_CALL addVetoableChangeListener(const ::rtl::OUString &aPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override final
Ignored if the property is not constrained.
virtual sal_Bool SAL_CALL fillPropertyMembersByHandle(::rtl::OUString *pPropName, sal_Int16 *pAttributes, sal_Int32 nHandle)=0
virtual sal_Int32 SAL_CALL fillHandles(sal_Int32 *pHandles, const css::uno::Sequence< ::rtl::OUString > &rPropNames)=0
virtual sal_Int32 SAL_CALL getHandleByName(const ::rtl::OUString &rPropertyName)=0
OPropertySetHelper(OBroadcastHelper &rBHelper)
sal_Int64 n
#define SAL_INFO(area, stream)
@ Exception
class SAL_NO_VTABLE XPropertySet
static int compare_OUString_Property_Impl(const void *arg1, const void *arg2) SAL_THROW_EXTERN_C()
Definition: propshlp.cxx:41
int i
OUString aPropName
Sequence< Property > aInfos
Definition: propshlp.cxx:55
sal_Int32 nHandle
sal_Int16 nAttributes
unsigned char sal_Bool
#define SAL_THROW_EXTERN_C()