summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2015-10-05 18:08:02 +0100
committerMichael Meeks <michael.meeks@collabora.com>2015-10-09 08:42:49 +0000
commitccf8bdcf929e842ef42ae968e4f0532282357277 (patch)
treef267454624fc8ceb12d1fd90fc826da4cf8e8c59
parent18b934af9979522c8cff1ff76504ce19c3e6916d (diff)
Create a wrapper to make listening for configmgr changes easy.
Change-Id: Ib58d04f9e046e604b24e0e338796a7a60aa1d6fd Reviewed-on: https://gerrit.libreoffice.org/19253 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
-rw-r--r--comphelper/source/misc/configuration.cxx51
-rw-r--r--configmgr/CppunitTest_configmgr_unit.mk4
-rw-r--r--configmgr/qa/unit/test.cxx47
-rw-r--r--include/comphelper/configurationlistener.hxx118
4 files changed, 220 insertions, 0 deletions
diff --git a/comphelper/source/misc/configuration.cxx b/comphelper/source/misc/configuration.cxx
index 6280fdc84ac2..e5bf8b84d2d2 100644
--- a/comphelper/source/misc/configuration.cxx
+++ b/comphelper/source/misc/configuration.cxx
@@ -27,6 +27,7 @@
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <comphelper/configuration.hxx>
+#include <comphelper/configurationlistener.hxx>
#include <rtl/instance.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
@@ -209,4 +210,54 @@ comphelper::detail::ConfigurationWrapper::createChanges() const {
new ConfigurationChanges(context_));
}
+void comphelper::ConfigurationListener::addListener(ConfigurationListenerPropertyBase *pListener)
+{
+ maListeners.push_back( pListener );
+ mxConfig->addPropertyChangeListener( pListener->maName, this );
+ pListener->setProperty( mxConfig->getPropertyValue( pListener->maName ) );
+}
+
+void comphelper::ConfigurationListener::removeListener(ConfigurationListenerPropertyBase *pListener)
+{
+ auto it = maListeners.begin();
+ it = std::find( maListeners.begin(), maListeners.end(), pListener );
+ if ( it != maListeners.end() )
+ {
+ maListeners.erase( it );
+ mxConfig->removePropertyChangeListener( pListener->maName, this );
+ }
+}
+
+void comphelper::ConfigurationListener::dispose()
+{
+ for (auto it = maListeners.begin(); it != maListeners.end(); ++it)
+ {
+ mxConfig->removePropertyChangeListener( (*it)->maName, this );
+ (*it)->dispose();
+ }
+ maListeners.clear();
+}
+
+void SAL_CALL comphelper::ConfigurationListener::disposing(css::lang::EventObject const &)
+ throw (css::uno::RuntimeException, std::exception)
+{
+ dispose();
+}
+
+void SAL_CALL comphelper::ConfigurationListener::propertyChange(
+ css::beans::PropertyChangeEvent const &rEvt )
+ throw (css::uno::RuntimeException, std::exception)
+{
+ assert( rEvt.Source == mxConfig );
+ for ( auto it = maListeners.begin(); it != maListeners.end(); ++it )
+ {
+ if ( (*it)->maName == rEvt.PropertyName )
+ {
+ // ignore rEvt.NewValue - in theory it could be stale => not set.
+ css::uno::Any aValue = mxConfig->getPropertyValue( (*it)->maName );
+ (*it)->setProperty( aValue );
+ }
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/configmgr/CppunitTest_configmgr_unit.mk b/configmgr/CppunitTest_configmgr_unit.mk
index e8bddc24bee8..ca9653fd126e 100644
--- a/configmgr/CppunitTest_configmgr_unit.mk
+++ b/configmgr/CppunitTest_configmgr_unit.mk
@@ -21,6 +21,10 @@ $(eval $(call gb_CppunitTest_use_library_objects,configmgr_unit,configmgr))
$(eval $(call gb_CppunitTest_use_sdk_api,configmgr_unit,))
+$(eval $(call gb_CppunitTest_use_custom_headers,configmgr_unit,\
+ officecfg/registry \
+))
+
$(eval $(call gb_CppunitTest_use_libraries,configmgr_unit, \
comphelper \
cppu \
diff --git a/configmgr/qa/unit/test.cxx b/configmgr/qa/unit/test.cxx
index a9f609bc3677..6985cab57fde 100644
--- a/configmgr/qa/unit/test.cxx
+++ b/configmgr/qa/unit/test.cxx
@@ -55,7 +55,11 @@
#include <rtl/ustring.hxx>
#include <sal/types.h>
#include <comphelper/processfactory.hxx>
+#include <comphelper/configuration.hxx>
+#include <comphelper/configurationlistener.hxx>
+#include <comphelper/configurationlistener.hxx>
#include <unotest/bootstrapfixturebase.hxx>
+#include <officecfg/Office/Math.hxx>
namespace {
@@ -70,6 +74,7 @@ public:
void testSetSetMemberName();
void testInsertSetMember();
void testReadCommands();
+ void testListener();
#if 0
void testThreads();
#endif
@@ -98,6 +103,7 @@ public:
CPPUNIT_TEST(testSetSetMemberName);
CPPUNIT_TEST(testInsertSetMember);
CPPUNIT_TEST(testReadCommands);
+ CPPUNIT_TEST(testListener);
#if 0
CPPUNIT_TEST(testThreads);
#endif
@@ -356,6 +362,47 @@ void Test::testReadCommands()
access, css::uno::UNO_QUERY_THROW)->dispose();
}
+void Test::testListener()
+{
+ OUString aRandomPath = "/org.openoffice.Office.Math/View";
+
+ // test with no props.
+ {
+ rtl::Reference<comphelper::ConfigurationListener> xListener(
+ new comphelper::ConfigurationListener(aRandomPath));
+ xListener->dispose();
+ }
+
+ // test some changes
+ {
+ rtl::Reference<comphelper::ConfigurationListener> xListener(
+ new comphelper::ConfigurationListener(aRandomPath));
+
+ comphelper::ConfigurationListenerProperty<bool> aSetting(xListener, "AutoRedraw");
+ CPPUNIT_ASSERT_MESSAGE("check AutoRedraw defaults to true", aSetting.get());
+
+ // set to false
+ {
+ std::shared_ptr< comphelper::ConfigurationChanges > xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Math::View::AutoRedraw::set(false, xChanges);
+ xChanges->commit();
+ }
+ CPPUNIT_ASSERT_MESSAGE("listener failed to trigger", !aSetting.get());
+
+ // set to true
+ {
+ std::shared_ptr< comphelper::ConfigurationChanges > xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Math::View::AutoRedraw::set(true, xChanges);
+ xChanges->commit();
+ }
+ CPPUNIT_ASSERT_MESSAGE("listener failed to trigger", aSetting.get());
+
+ xListener->dispose();
+ }
+}
+
void Test::testRecursive()
{
bool destroyed = false;
diff --git a/include/comphelper/configurationlistener.hxx b/include/comphelper/configurationlistener.hxx
new file mode 100644
index 000000000000..658b84b8e80d
--- /dev/null
+++ b/include/comphelper/configurationlistener.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_COMPHELPER_CONFIGURATIONLISTENER_HXX
+#define INCLUDED_COMPHELPER_CONFIGURATIONLISTENER_HXX
+
+#include <algorithm>
+#include <vector>
+#include <iterator>
+#include <comphelper/comphelperdllapi.h>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyChangeEvent.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <rtl/ref.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/configurationhelper.hxx>
+
+namespace comphelper {
+
+class ConfigurationListener;
+
+class COMPHELPER_DLLPUBLIC ConfigurationListenerPropertyBase {
+public:
+ OUString maName;
+ rtl::Reference<ConfigurationListener> mxListener;
+
+ virtual ~ConfigurationListenerPropertyBase() {}
+ virtual void setProperty(const css::uno::Any &aProperty) = 0;
+ void dispose() { mxListener.clear(); }
+};
+
+template< typename uno_type > class ConfigurationListenerProperty : public ConfigurationListenerPropertyBase
+{
+ uno_type maValue;
+protected:
+ virtual void setProperty(const css::uno::Any &aProperty) SAL_OVERRIDE
+ {
+ aProperty >>= maValue;
+ }
+public:
+ /**
+ * Provide a mirror of the configmgr's version of this property
+ * for the lifecycle of this property. The property value tracks
+ * the same value in the configuration.
+ */
+ inline ConfigurationListenerProperty(const rtl::Reference< ConfigurationListener > &xListener,
+ const OUString &rProp );
+
+ inline ~ConfigurationListenerProperty();
+
+ uno_type get() { return maValue; }
+};
+
+class COMPHELPER_DLLPUBLIC ConfigurationListener :
+ public cppu::WeakImplHelper< css::beans::XPropertyChangeListener >
+{
+ css::uno::Reference< css::beans::XPropertySet > mxConfig;
+ std::vector< ConfigurationListenerPropertyBase * > maListeners;
+public:
+ /// Public health warning, you -must- dispose this if you use it.
+ ConfigurationListener(const OUString &rPath,
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ const & xContext = comphelper::getProcessComponentContext())
+ : mxConfig( ConfigurationHelper::openConfig( xContext, rPath,
+ ConfigurationHelper::EConfigurationModes::E_READONLY ),
+ css::uno::UNO_QUERY_THROW )
+ { }
+
+ virtual ~ConfigurationListener()
+ {
+ dispose();
+ }
+
+ /// Listen for the specific property denoted by the listener
+ void addListener(ConfigurationListenerPropertyBase *pListener);
+
+ /// Stop listening.
+ void removeListener(ConfigurationListenerPropertyBase *pListener);
+
+ /// Release various circular references
+ void dispose();
+
+ // XPropertyChangeListener implementation
+ virtual void SAL_CALL disposing(css::lang::EventObject const &)
+ throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
+
+ /// Notify of the property change
+ virtual void SAL_CALL propertyChange(
+ css::beans::PropertyChangeEvent const &rEvt )
+ throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
+};
+
+template< typename uno_type > ConfigurationListenerProperty< uno_type >::ConfigurationListenerProperty(const rtl::Reference< ConfigurationListener > &xListener, const OUString &rProp )
+{
+ maName = rProp;
+ mxListener = xListener;
+ mxListener->addListener(this);
+}
+
+template< typename uno_type > ConfigurationListenerProperty< uno_type >::~ConfigurationListenerProperty()
+{
+ if (mxListener.is())
+ mxListener->removeListener(this);
+}
+
+} // namespace comphelper
+
+#endif // INCLUDED_COMPHELPER_CONFIGURATIONLISTENER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */