comphelper/inc/comphelper/configuration.hxx | 2 comphelper/source/misc/configuration.cxx | 109 +++--- configmgr/source/access.cxx | 75 ++++ configmgr/source/childaccess.cxx | 76 ---- configmgr/source/configmgr.component | 2 configmgr/source/readonlyaccess.cxx | 64 ++- configmgr/source/readwriteaccess.cxx | 74 +++- cui/source/inc/treeopt.hxx | 9 cui/source/options/treeopt.cxx | 318 ++++++++---------- offapi/com/sun/star/configuration/ReadOnlyAccess.idl | 15 offapi/com/sun/star/configuration/ReadWriteAccess.idl | 15 11 files changed, 421 insertions(+), 338 deletions(-)
New commits: commit cef66a3eed301ab77e02be6d6ba148142051e13d Author: Stephan Bergmann <sberg...@redhat.com> Date: Wed Jul 25 19:06:42 2012 +0200 Revert "fdo#52232 ConfigurationSet wrapper unusable for localized properties" This reverts commit aebf5bf22304c73e121b16dc0b51f909c5f34c28, now that e397a9cfabc2928cd5571309f5b634a7e78098ec "Make comphelper/configuration.hxx work for localized properties" fixes the original problem. Change-Id: If4e187b911510d5932d52cec08d43cb73f6e339c diff --git a/cui/source/inc/treeopt.hxx b/cui/source/inc/treeopt.hxx index 64d2b9b..38700e6 100644 --- a/cui/source/inc/treeopt.hxx +++ b/cui/source/inc/treeopt.hxx @@ -138,7 +138,6 @@ struct LastPageSaver // class OfaTreeOptionsDialog -------------------------------------------- namespace com { namespace sun { namespace star { namespace frame { class XFrame; } } } } -namespace com { namespace sun { namespace star { namespace container { class XNameAccess; } } } } namespace com { namespace sun { namespace star { namespace lang { class XMultiServiceFactory; } } } } namespace com { namespace sun { namespace star { namespace awt { class XContainerWindowProvider; } } } } @@ -192,12 +191,8 @@ private: com::sun::star::lang::XMultiServiceFactory >& xMFac, const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& xFrame ); - Module* LoadModule( const rtl::OUString& rModuleIdentifier, - const com::sun::star::uno::Reference< - com::sun::star::container::XNameAccess >& xRoot ); - void LoadNodes( const com::sun::star::uno::Reference< - com::sun::star::container::XNameAccess >& xRoot, - Module* pModule, + Module* LoadModule( const rtl::OUString& rModuleIdentifier ); + void LoadNodes( Module* pModule, const rtl::OUString& rExtensionId, VectorOfNodes& rOutNodeList ); void InsertNodes( const VectorOfNodes& rNodeList ); diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx index ce34083..9db1841 100644 --- a/cui/source/options/treeopt.cxx +++ b/cui/source/options/treeopt.cxx @@ -67,11 +67,11 @@ #include <com/sun/star/frame/XModuleManager.hpp> #include <com/sun/star/loader/CannotActivateFactoryException.hpp> #include <com/sun/star/util/XMacroExpander.hpp> -#include <comphelper/configurationhelper.hxx> #include <comphelper/processfactory.hxx> #include <editeng/optitems.hxx> #include <editeng/unolingu.hxx> #include <linguistic/misc.hxx> +#include <officecfg/Office/OptionsDialog.hxx> #include <osl/module.hxx> #include <osl/process.h> #include <rtl/bootstrap.hxx> @@ -1927,18 +1927,12 @@ void OfaTreeOptionsDialog::LoadExtensionOptions( const rtl::OUString& rExtension { Module* pModule = NULL; Reference< XMultiServiceFactory > xMSFac = comphelper::getProcessServiceFactory(); - // open optionsdialog.xcu - Reference< XNameAccess > xRoot( - ::comphelper::ConfigurationHelper::openConfig( - xMSFac, C2U("org.openoffice.Office.OptionsDialog"), - ::comphelper::ConfigurationHelper::E_READONLY ), UNO_QUERY ); - DBG_ASSERT( xRoot.is(), "OfaTreeOptionsDialog::LoadExtensionOptions(): no config" ); // when called by Tools - Options then load nodes of active module if ( rExtensionId.isEmpty() ) - pModule = LoadModule( GetModuleIdentifier( xMSFac, Reference< XFrame >() ), xRoot ); + pModule = LoadModule( GetModuleIdentifier( xMSFac, Reference< XFrame >() ) ); VectorOfNodes aNodeList; - LoadNodes( xRoot, pModule, rExtensionId, aNodeList ); + LoadNodes( pModule, rExtensionId, aNodeList ); InsertNodes( aNodeList ); } @@ -1977,64 +1971,58 @@ rtl::OUString OfaTreeOptionsDialog::GetModuleIdentifier( } Module* OfaTreeOptionsDialog::LoadModule( - const rtl::OUString& rModuleIdentifier, const Reference< XNameAccess >& xRoot ) + const rtl::OUString& rModuleIdentifier ) { Module* pModule = NULL; - Reference< XNameAccess > xSet; + Reference< XNameAccess > xSet( + officecfg::Office::OptionsDialog::Modules::get()); - if ( xRoot->hasByName( C2U("Modules") ) ) + Sequence< rtl::OUString > seqNames = xSet->getElementNames(); + for ( int i = 0; i < seqNames.getLength(); ++i ) { - xRoot->getByName( C2U("Modules") ) >>= xSet; - if ( xSet.is() ) + rtl::OUString sModule( seqNames[i] ); + if ( rModuleIdentifier == sModule ) { - Sequence< rtl::OUString > seqNames = xSet->getElementNames(); - for ( int i = 0; i < seqNames.getLength(); ++i ) + // current active module found + pModule = new Module( sModule ); + pModule->m_bActive = true; + + Reference< XNameAccess > xModAccess; + xSet->getByName( seqNames[i] ) >>= xModAccess; + if ( xModAccess.is() ) { - rtl::OUString sModule( seqNames[i] ); - if ( rModuleIdentifier == sModule ) + // load the nodes of this module + Reference< XNameAccess > xNodeAccess; + xModAccess->getByName( C2U("Nodes") ) >>= xNodeAccess; + if ( xNodeAccess.is() ) { - // current active module found - pModule = new Module( sModule ); - pModule->m_bActive = true; - - Reference< XNameAccess > xModAccess; - xSet->getByName( seqNames[i] ) >>= xModAccess; - if ( xModAccess.is() ) + Sequence< rtl::OUString > xTemp = xNodeAccess->getElementNames(); + Reference< XNameAccess > xAccess; + sal_Int32 nIndex = -1; + for ( int x = 0; x < xTemp.getLength(); ++x ) { - // load the nodes of this module - Reference< XNameAccess > xNodeAccess; - xModAccess->getByName( C2U("Nodes") ) >>= xNodeAccess; - if ( xNodeAccess.is() ) + xNodeAccess->getByName( xTemp[x] ) >>= xAccess; + if ( xAccess.is() ) { - Sequence< rtl::OUString > xTemp = xNodeAccess->getElementNames(); - Reference< XNameAccess > xAccess; - sal_Int32 nIndex = -1; - for ( int x = 0; x < xTemp.getLength(); ++x ) + xAccess->getByName( C2U("Index") ) >>= nIndex; + if ( nIndex < 0 ) + // append nodes with index < 0 + pModule->m_aNodeList.push_back( + new OrderedEntry( nIndex, xTemp[x] ) ); + else { - xNodeAccess->getByName( xTemp[x] ) >>= xAccess; - if ( xAccess.is() ) + // search position of the node + sal_uInt32 y = 0; + for ( ; y < pModule->m_aNodeList.size(); ++y ) { - xAccess->getByName( C2U("Index") ) >>= nIndex; - if ( nIndex < 0 ) - // append nodes with index < 0 - pModule->m_aNodeList.push_back( - new OrderedEntry( nIndex, xTemp[x] ) ); - else - { - // search position of the node - sal_uInt32 y = 0; - for ( ; y < pModule->m_aNodeList.size(); ++y ) - { - sal_Int32 nNodeIdx = pModule->m_aNodeList[y]->m_nIndex; - if ( nNodeIdx < 0 || nNodeIdx > nIndex ) - break; - } - // and insert the node on this position - pModule->m_aNodeList.insert( - pModule->m_aNodeList.begin() + y, - new OrderedEntry( nIndex, xTemp[x] ) ); - } + sal_Int32 nNodeIdx = pModule->m_aNodeList[y]->m_nIndex; + if ( nNodeIdx < 0 || nNodeIdx > nIndex ) + break; } + // and insert the node on this position + pModule->m_aNodeList.insert( + pModule->m_aNodeList.begin() + y, + new OrderedEntry( nIndex, xTemp[x] ) ); } } } @@ -2046,151 +2034,145 @@ Module* OfaTreeOptionsDialog::LoadModule( } void OfaTreeOptionsDialog::LoadNodes( - const Reference< XNameAccess >& xRoot, Module* pModule, - const rtl::OUString& rExtensionId, VectorOfNodes& rOutNodeList ) + Module* pModule, const rtl::OUString& rExtensionId, + VectorOfNodes& rOutNodeList ) { - Reference< XNameAccess > xSet; - if ( xRoot->hasByName( C2U("Nodes") ) ) + Reference< XNameAccess > xSet( + officecfg::Office::OptionsDialog::Nodes::get()); + VectorOfNodes aNodeList; + Sequence< rtl::OUString > seqNames = xSet->getElementNames(); + + for ( int i = 0; i < seqNames.getLength(); ++i ) { - xRoot->getByName( C2U("Nodes") ) >>= xSet; - if ( xSet.is() ) + String sGroupName( seqNames[i] ); + Reference< XNameAccess > xNodeAccess; + xSet->getByName( seqNames[i] ) >>= xNodeAccess; + + if ( xNodeAccess.is() ) { - VectorOfNodes aNodeList; - Sequence< rtl::OUString > seqNames = xSet->getElementNames(); + rtl::OUString sNodeId, sLabel, sPageURL, sGroupId; + bool bAllModules = false; + sal_Int32 nGroupIndex = 0; + + sNodeId = seqNames[i]; + xNodeAccess->getByName( C2U("Label") ) >>= sLabel; + xNodeAccess->getByName( C2U("OptionsPage") ) >>= sPageURL; + xNodeAccess->getByName( C2U("AllModules") ) >>= bAllModules; + xNodeAccess->getByName( C2U("GroupId") ) >>= sGroupId; + xNodeAccess->getByName( C2U("GroupIndex") ) >>= nGroupIndex; - for ( int i = 0; i < seqNames.getLength(); ++i ) + if ( sLabel.isEmpty() ) + sLabel = sGroupName; + String sTemp = getGroupName( sLabel, !rExtensionId.isEmpty() ); + if ( sTemp.Len() > 0 ) + sLabel = sTemp; + OptionsNode* pNode = + new OptionsNode( sNodeId, sLabel, sPageURL, bAllModules, sGroupId, nGroupIndex ); + + if ( rExtensionId.isEmpty() && !isNodeActive( pNode, pModule ) ) { - String sGroupName( seqNames[i] ); - Reference< XNameAccess > xNodeAccess; - xSet->getByName( seqNames[i] ) >>= xNodeAccess; + delete pNode; + continue; + } - if ( xNodeAccess.is() ) + Reference< XNameAccess > xLeavesSet; + xNodeAccess->getByName( C2U( "Leaves" ) ) >>= xLeavesSet; + if ( xLeavesSet.is() ) + { + Sequence< rtl::OUString > seqLeaves = xLeavesSet->getElementNames(); + for ( int j = 0; j < seqLeaves.getLength(); ++j ) { - rtl::OUString sNodeId, sLabel, sPageURL, sGroupId; - bool bAllModules = false; - sal_Int32 nGroupIndex = 0; - - sNodeId = seqNames[i]; - xNodeAccess->getByName( C2U("Label") ) >>= sLabel; - xNodeAccess->getByName( C2U("OptionsPage") ) >>= sPageURL; - xNodeAccess->getByName( C2U("AllModules") ) >>= bAllModules; - xNodeAccess->getByName( C2U("GroupId") ) >>= sGroupId; - xNodeAccess->getByName( C2U("GroupIndex") ) >>= nGroupIndex; - - if ( sLabel.isEmpty() ) - sLabel = sGroupName; - String sTemp = getGroupName( sLabel, !rExtensionId.isEmpty() ); - if ( sTemp.Len() > 0 ) - sLabel = sTemp; - OptionsNode* pNode = - new OptionsNode( sNodeId, sLabel, sPageURL, bAllModules, sGroupId, nGroupIndex ); - - if ( rExtensionId.isEmpty() && !isNodeActive( pNode, pModule ) ) - { - delete pNode; - continue; - } + Reference< XNameAccess > xLeaveAccess; + xLeavesSet->getByName( seqLeaves[j] ) >>= xLeaveAccess; - Reference< XNameAccess > xLeavesSet; - xNodeAccess->getByName( C2U( "Leaves" ) ) >>= xLeavesSet; - if ( xLeavesSet.is() ) + if ( xLeaveAccess.is() ) { - Sequence< rtl::OUString > seqLeaves = xLeavesSet->getElementNames(); - for ( int j = 0; j < seqLeaves.getLength(); ++j ) - { - Reference< XNameAccess > xLeaveAccess; - xLeavesSet->getByName( seqLeaves[j] ) >>= xLeaveAccess; + rtl::OUString sId, sLeafLabel, sEventHdl, sLeafURL, sLeafGrpId; + sal_Int32 nLeafGrpIdx = 0; - if ( xLeaveAccess.is() ) - { - rtl::OUString sId, sLeafLabel, sEventHdl, sLeafURL, sLeafGrpId; - sal_Int32 nLeafGrpIdx = 0; + xLeaveAccess->getByName( C2U("Id") ) >>= sId; + xLeaveAccess->getByName( C2U("Label") ) >>= sLeafLabel; + xLeaveAccess->getByName( C2U("OptionsPage") ) >>= sLeafURL; + xLeaveAccess->getByName( C2U("EventHandlerService") ) >>= sEventHdl; + xLeaveAccess->getByName( C2U("GroupId") ) >>= sLeafGrpId; + xLeaveAccess->getByName( C2U("GroupIndex") ) >>= nLeafGrpIdx; - xLeaveAccess->getByName( C2U("Id") ) >>= sId; - xLeaveAccess->getByName( C2U("Label") ) >>= sLeafLabel; - xLeaveAccess->getByName( C2U("OptionsPage") ) >>= sLeafURL; - xLeaveAccess->getByName( C2U("EventHandlerService") ) >>= sEventHdl; - xLeaveAccess->getByName( C2U("GroupId") ) >>= sLeafGrpId; - xLeaveAccess->getByName( C2U("GroupIndex") ) >>= nLeafGrpIdx; + if ( rExtensionId.isEmpty() || sId == rExtensionId ) + { + OptionsLeaf* pLeaf = new OptionsLeaf( + sId, sLeafLabel, sLeafURL, sEventHdl, sLeafGrpId, nLeafGrpIdx ); - if ( rExtensionId.isEmpty() || sId == rExtensionId ) + if ( !sLeafGrpId.isEmpty() ) + { + bool bAlreadyOpened = false; + if ( pNode->m_aGroupedLeaves.size() > 0 ) { - OptionsLeaf* pLeaf = new OptionsLeaf( - sId, sLeafLabel, sLeafURL, sEventHdl, sLeafGrpId, nLeafGrpIdx ); - - if ( !sLeafGrpId.isEmpty() ) + for ( sal_uInt32 k = 0; + k < pNode->m_aGroupedLeaves.size(); ++k ) { - bool bAlreadyOpened = false; - if ( pNode->m_aGroupedLeaves.size() > 0 ) + if ( pNode->m_aGroupedLeaves[k].size() > 0 && + pNode->m_aGroupedLeaves[k][0]->m_sGroupId + == sLeafGrpId ) { - for ( sal_uInt32 k = 0; - k < pNode->m_aGroupedLeaves.size(); ++k ) + sal_uInt32 l = 0; + for ( ; l < pNode->m_aGroupedLeaves[k].size(); ++l ) { - if ( pNode->m_aGroupedLeaves[k].size() > 0 && - pNode->m_aGroupedLeaves[k][0]->m_sGroupId - == sLeafGrpId ) - { - sal_uInt32 l = 0; - for ( ; l < pNode->m_aGroupedLeaves[k].size(); ++l ) - { - if ( pNode->m_aGroupedLeaves[k][l]-> - m_nGroupIndex >= nLeafGrpIdx ) - break; - } - pNode->m_aGroupedLeaves[k].insert( - pNode->m_aGroupedLeaves[k].begin() + l, pLeaf ); - bAlreadyOpened = true; + if ( pNode->m_aGroupedLeaves[k][l]-> + m_nGroupIndex >= nLeafGrpIdx ) break; - } } - } - if ( !bAlreadyOpened ) - { - VectorOfLeaves aGroupedLeaves; - aGroupedLeaves.push_back( pLeaf ); - pNode->m_aGroupedLeaves.push_back( aGroupedLeaves ); + pNode->m_aGroupedLeaves[k].insert( + pNode->m_aGroupedLeaves[k].begin() + l, pLeaf ); + bAlreadyOpened = true; + break; } } - else - pNode->m_aLeaves.push_back( - new OptionsLeaf( - sId, sLeafLabel, sLeafURL, - sEventHdl, sLeafGrpId, nLeafGrpIdx ) ); + } + if ( !bAlreadyOpened ) + { + VectorOfLeaves aGroupedLeaves; + aGroupedLeaves.push_back( pLeaf ); + pNode->m_aGroupedLeaves.push_back( aGroupedLeaves ); } } + else + pNode->m_aLeaves.push_back( + new OptionsLeaf( + sId, sLeafLabel, sLeafURL, + sEventHdl, sLeafGrpId, nLeafGrpIdx ) ); } } - - // do not insert nodes without leaves - if ( pNode->m_aLeaves.size() > 0 || pNode->m_aGroupedLeaves.size() > 0 ) - { - pModule ? aNodeList.push_back( pNode ) : rOutNodeList.push_back( pNode ); - } } } - if ( pModule && aNodeList.size() > 0 ) + // do not insert nodes without leaves + if ( pNode->m_aLeaves.size() > 0 || pNode->m_aGroupedLeaves.size() > 0 ) { - sal_uInt32 i = 0, j = 0; - for ( ; i < pModule->m_aNodeList.size(); ++i ) + pModule ? aNodeList.push_back( pNode ) : rOutNodeList.push_back( pNode ); + } + } + } + + if ( pModule && aNodeList.size() > 0 ) + { + sal_uInt32 i = 0, j = 0; + for ( ; i < pModule->m_aNodeList.size(); ++i ) + { + rtl::OUString sNodeId = pModule->m_aNodeList[i]->m_sId; + for ( j = 0; j < aNodeList.size(); ++j ) + { + OptionsNode* pNode = aNodeList[j]; + if ( pNode->m_sId == sNodeId ) { - rtl::OUString sNodeId = pModule->m_aNodeList[i]->m_sId; - for ( j = 0; j < aNodeList.size(); ++j ) - { - OptionsNode* pNode = aNodeList[j]; - if ( pNode->m_sId == sNodeId ) - { - rOutNodeList.push_back( pNode ); - aNodeList.erase( aNodeList.begin() + j ); - break; - } - } + rOutNodeList.push_back( pNode ); + aNodeList.erase( aNodeList.begin() + j ); + break; } - - for ( i = 0; i < aNodeList.size(); ++i ) - rOutNodeList.push_back( aNodeList[i] ); } } + + for ( i = 0; i < aNodeList.size(); ++i ) + rOutNodeList.push_back( aNodeList[i] ); } } commit cf7c9599e776eba8e14614cecb528d3da5778190 Author: Stephan Bergmann <sberg...@redhat.com> Date: Wed Jul 25 18:54:38 2012 +0200 Make comphelper/configuration.hxx work for localized properties See aebf5bf22304c73e121b16dc0b51f909c5f34c28 "fdo#52232 ConfigurationSet wrapper unusable for localized properties" for a discussion of the problems with the original design. 1 Redesigned configmgr's localized property access to understand ['*<locale>'] paths that select the best existing value match for the requested <locale>. Adapted ConfigurationWrapper::getLocalizedPropertyValue accordingly. 2 Redesigned ConfigurationChanges to fix the locale at instantiation time. That takes care of ConfigurationWrapper::setLocalizedPropertyValue, ConfigurationWrapper::getGroupReadWrite, and ConfigurationWrapper::getSetReadWrite. (This required an additional constructor parameter for the ReadWriteAccess service, to specify a locale at instantiation time.) 3 Redesigned ReadOnlyAccess to be a service that fixes the locale at instantiation time. That allows to take care of ConfigurationWrapper::getGroupReadOnly and ConfigurationWrapper::getSetReadOnly. Change-Id: I2ae7342b278b6f4222a0189a1deb2a53e204059f diff --git a/comphelper/inc/comphelper/configuration.hxx b/comphelper/inc/comphelper/configuration.hxx index 1cf4a26..d70b390 100644 --- a/comphelper/inc/comphelper/configuration.hxx +++ b/comphelper/inc/comphelper/configuration.hxx @@ -148,8 +148,6 @@ public: boost::shared_ptr< ConfigurationChanges > createChanges() const; private: - rtl::OUString extendLocalizedPath(rtl::OUString const & path) const; - com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > context_; diff --git a/comphelper/source/misc/configuration.cxx b/comphelper/source/misc/configuration.cxx index 383e35f..01ec08f 100644 --- a/comphelper/source/misc/configuration.cxx +++ b/comphelper/source/misc/configuration.cxx @@ -64,6 +64,51 @@ struct TheConfigurationWrapper: TheConfigurationWrapper > {}; +OUString getDefaultLocale( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + css::lang::Locale locale( + css::uno::Reference< css::lang::XLocalizable >( + css::configuration::theDefaultProvider::get(context), + css::uno::UNO_QUERY_THROW)-> + getLocale()); + OUStringBuffer buf; + SAL_WARN_IF( + locale.Language.indexOf('-') != -1, "comphelper", + "Locale language \"" << locale.Language << "\" contains \"-\""); + buf.append(locale.Language); + SAL_WARN_IF( + locale.Country.isEmpty() && !locale.Variant.isEmpty(), "comphelper", + "Locale has empty country but non-empty variant \"" << locale.Variant + << '"'); + if (!locale.Country.isEmpty()) { + buf.append('-'); + SAL_WARN_IF( + locale.Country.indexOf('-') != -1, "comphelper", + "Locale language \"" << locale.Country << "\" contains \"-\""); + buf.append(locale.Country); + if (!locale.Variant.isEmpty()) { + buf.append('-'); + buf.append(locale.Variant); + } + } + return buf.makeStringAndClear(); +} + +OUString extendLocalizedPath(OUString const & path, OUString const & locale) { + rtl::OUStringBuffer buf(path); + buf.append("/['*"); + SAL_WARN_IF( + locale.match("*"), "comphelper", + "Locale \"" << locale << "\" starts with \"-\""); + assert(locale.indexOf('&') == -1); + assert(locale.indexOf('"') == -1); + assert(locale.indexOf('\'') == -1); + buf.append(locale); + buf.append("']"); + return buf.makeStringAndClear(); +} + } boost::shared_ptr< comphelper::ConfigurationChanges > @@ -82,7 +127,9 @@ void comphelper::ConfigurationChanges::commit() const { comphelper::ConfigurationChanges::ConfigurationChanges( css::uno::Reference< css::uno::XComponentContext > const & context): - access_(css::configuration::ReadWriteAccess::create(context)) + access_( + css::configuration::ReadWriteAccess::create( + context, getDefaultLocale(context))) {} void comphelper::ConfigurationChanges::setPropertyValue( @@ -114,7 +161,8 @@ comphelper::detail::ConfigurationWrapper::get( comphelper::detail::ConfigurationWrapper::ConfigurationWrapper( css::uno::Reference< css::uno::XComponentContext > const & context): - context_(context), access_(css::configuration::ReadOnlyAccess::get(context)) + context_(context), + access_(css::configuration::ReadOnlyAccess::create(context, "*")) {} comphelper::detail::ConfigurationWrapper::~ConfigurationWrapper() {} @@ -137,7 +185,8 @@ css::uno::Any comphelper::detail::ConfigurationWrapper::getLocalizedPropertyValue( rtl::OUString const & path) const { - return access_->getByHierarchicalName(extendLocalizedPath(path)); + return access_->getByHierarchicalName( + extendLocalizedPath(path, getDefaultLocale(context_))); } void comphelper::detail::ConfigurationWrapper::setLocalizedPropertyValue( @@ -145,7 +194,7 @@ void comphelper::detail::ConfigurationWrapper::setLocalizedPropertyValue( rtl::OUString const & path, com::sun::star::uno::Any const & value) const { assert(batch.get() != 0); - batch->setPropertyValue(extendLocalizedPath(path), value); + batch->setPropertyValue(path, value); } css::uno::Reference< css::container::XHierarchicalNameAccess > @@ -153,7 +202,10 @@ comphelper::detail::ConfigurationWrapper::getGroupReadOnly( rtl::OUString const & path) const { return css::uno::Reference< css::container::XHierarchicalNameAccess >( - access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW); + (css::configuration::ReadOnlyAccess::create( + context_, getDefaultLocale(context_))-> + getByHierarchicalName(path)), + css::uno::UNO_QUERY_THROW); } css::uno::Reference< css::container::XHierarchicalNameReplace > @@ -170,7 +222,10 @@ comphelper::detail::ConfigurationWrapper::getSetReadOnly( rtl::OUString const & path) const { return css::uno::Reference< css::container::XNameAccess >( - access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW); + (css::configuration::ReadOnlyAccess::create( + context_, getDefaultLocale(context_))-> + getByHierarchicalName(path)), + css::uno::UNO_QUERY_THROW); } css::uno::Reference< css::container::XNameContainer > @@ -188,46 +243,4 @@ comphelper::detail::ConfigurationWrapper::createChanges() const { new ConfigurationChanges(context_)); } -rtl::OUString comphelper::detail::ConfigurationWrapper::extendLocalizedPath( - rtl::OUString const & path) const -{ - rtl::OUStringBuffer buf(path); - buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/['")); - css::lang::Locale locale( - css::uno::Reference< css::lang::XLocalizable >( - css::configuration::theDefaultProvider::get(context_), - css::uno::UNO_QUERY_THROW)-> - getLocale()); - SAL_WARN_IF( - locale.Language.indexOf('-') != -1, "comphelper", - "Locale language \"" << locale.Language << "\" contains \"-\""); - assert(locale.Language.indexOf('&') == -1); - assert(locale.Language.indexOf('"') == -1); - assert(locale.Language.indexOf('\'') == -1); - buf.append(locale.Language); - SAL_WARN_IF( - locale.Country.isEmpty() && !locale.Variant.isEmpty(), "comphelper", - "Locale has empty country but non-empty variant \"" << locale.Variant - << '"'); - if (!locale.Country.isEmpty()) { - buf.append('-'); - SAL_WARN_IF( - locale.Country.indexOf('-') != -1, "comphelper", - "Locale language \"" << locale.Country << "\" contains \"-\""); - assert(locale.Country.indexOf('&') == -1); - assert(locale.Country.indexOf('"') == -1); - assert(locale.Country.indexOf('\'') == -1); - buf.append(locale.Country); - if (!locale.Variant.isEmpty()) { - buf.append('-'); - assert(locale.Variant.indexOf('&') == -1); - assert(locale.Variant.indexOf('"') == -1); - assert(locale.Variant.indexOf('\'') == -1); - buf.append(locale.Variant); - } - } - buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("']")); - return buf.makeStringAndClear(); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/access.cxx b/configmgr/source/access.cxx index 30d0542..8d6d9cf 100644 --- a/configmgr/source/access.cxx +++ b/configmgr/source/access.cxx @@ -1484,6 +1484,81 @@ rtl::Reference< Node > Access::getParentNode() { } rtl::Reference< ChildAccess > Access::getChild(rtl::OUString const & name) { + if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && name.match("*")) { + OUString locale(name.copy(1)); + if (locale.match("*")) { + SAL_WARN( + "configmgr", + ("access best-matching localized property value via" + " \"*<locale>\" with <locale> \"") + << locale << "\" recursively starting with \"*\""); + return getChild(locale); + } + SAL_WARN_IF( + locale.isEmpty(), "configmgr", + ("access best-matching localized property value via \"*<locale>\"" + " with empty <locale>; falling back to defaults")); + if (!locale.isEmpty()) { + // Find best match using an adaption of RFC 4647 lookup matching + // rules, removing "-" or "_" delimited segments from the end: + for (;;) { + rtl::Reference< ChildAccess > child(getChild(locale)); + if (child.is()) { + return child; + } + sal_Int32 i = locale.getLength() - 1; + while (i > 0 && locale[i] != '-' && locale[i] != '_') { + --i; + } + if (i <= 0) { + break; + } + locale = locale.copy(0, i); + } + // As a workaround for broken xcu data that does not use shortest + // xml:lang attributes, look for the first entry with the same first + // segment as the requested language tag before falling back to + // defaults (see fdo#33638): + assert( + !locale.isEmpty() && locale.indexOf('-') == -1 && + locale.indexOf('_') == -1); + std::vector< rtl::Reference< ChildAccess > > children( + getAllChildren()); + for (std::vector< rtl::Reference< ChildAccess > >::iterator i( + children.begin()); + i != children.end(); ++i) + { + OUString name2((*i)->getNameInternal()); + if (name2.match(locale) && + (name2.getLength() == locale.getLength() || + name2[locale.getLength()] == '-' || + name2[locale.getLength()] == '_')) + { + return *i; + } + } + } + // Defaults are the "en-US" locale, the "en" locale, the empty string + // locale, the first child (if any), or a null ChildAccess, in that + // order: + rtl::Reference< ChildAccess > child(getChild("en-US")); + if (child.is()) { + return child; + } + child = getChild("en"); + if (child.is()) { + return child; + } + child = getChild(OUString()); + if (child.is()) { + return child; + } + std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); + if (!children.empty()) { + return children.front(); + } + return rtl::Reference< ChildAccess >(); + } ModifiedChildren::iterator i(modifiedChildren_.find(name)); return i == modifiedChildren_.end() ? getUnmodifiedChild(name) : getModifiedChild(i); diff --git a/configmgr/source/childaccess.cxx b/configmgr/source/childaccess.cxx index 3b5a8e2..99c4d2d 100644 --- a/configmgr/source/childaccess.cxx +++ b/configmgr/source/childaccess.cxx @@ -259,17 +259,6 @@ void ChildAccess::setProperty( localModifications->add(getRelativePath()); } -namespace -{ - rtl::OUString lcl_StripSegment(const rtl::OUString &rLocale) - { - sal_Int32 i = !rLocale.isEmpty() ? rLocale.getLength() - 1 : 0; - while (i > 0 && rLocale[i] != '-' && rLocale[i] != '_') - --i; - return rLocale.copy(0, i); - } -} - css::uno::Any ChildAccess::asValue() { if (changedValue_.get() != 0) { return *changedValue_; @@ -280,66 +269,11 @@ css::uno::Any ChildAccess::asValue() { getComponents()); case Node::KIND_LOCALIZED_PROPERTY: { - rtl::OUString sLocale(getRootAccess()->getLocale()); - if (!Components::allLocales(sLocale)) - { - rtl::Reference< ChildAccess > child; - // Find best match using an adaption of RFC 4647 lookup matching - // rules, removing "-" or "_" delimited segments from the end - while (1) - { - child = getChild(sLocale); - if (child.is()) - break; - rtl::OUString sTmpLocale = lcl_StripSegment(sLocale); - if (sTmpLocale.isEmpty()) - break; - sLocale = sTmpLocale; - } - - //Resolves: fdo#33638 Look for the first entry with the same - //first segment as the requested language tag, before falling - //back to en-US, etc. - typedef std::vector< rtl::Reference< ChildAccess > > ChildVector; - if (!child.is()) - { - const ChildVector &rAllChildren = getAllChildren(); - for (ChildVector::const_iterator aI = rAllChildren.begin(), - aEnd = rAllChildren.end(); aI != aEnd; ++aI) - { - rtl::OUString sLanguage = lcl_StripSegment((*aI)->getNameInternal()); - if (sLocale == sLanguage) - { - child = *aI; - break; - } - } - } - - // defaults are the "en-US" locale, the "en" locale, the empty - // string locale, the first child (if any), or a nil value (even - // though it may be illegal for the given property), in that - // order: - if (!child.is()) - { - child = getChild( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US"))); - if (!child.is()) - { - child = getChild( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en"))); - if (!child.is()) - { - child = getChild(rtl::OUString()); - if (!child.is()) - { - ChildVector all(getAllChildren()); - if (!all.empty()) - child = all.front(); - } - } - } - } + OUString locale(getRootAccess()->getLocale()); + if (!Components::allLocales(locale)) { + rtl::Reference< ChildAccess > child(getChild("*" + locale)); + // As a last resort, return a nil value even though it may be + // illegal for the given property: return child.is() ? child->asValue() : css::uno::Any(); } } diff --git a/configmgr/source/configmgr.component b/configmgr/source/configmgr.component index 34d0399..b409478 100644 --- a/configmgr/source/configmgr.component +++ b/configmgr/source/configmgr.component @@ -30,7 +30,7 @@ <singleton name="com.sun.star.configuration.theDefaultProvider"/> </implementation> <implementation name="com.sun.star.comp.configuration.ReadOnlyAccess"> - <singleton name="com.sun.star.configuration.ReadOnlyAccess"/> + <service name="com.sun.star.configuration.ReadOnlyAccess"/> </implementation> <implementation name="com.sun.star.comp.configuration.ReadWriteAccess"> <service name="com.sun.star.configuration.ReadWriteAccess"/> diff --git a/configmgr/source/readonlyaccess.cxx b/configmgr/source/readonlyaccess.cxx index d9ab2dc..264eae1 100644 --- a/configmgr/source/readonlyaccess.cxx +++ b/configmgr/source/readonlyaccess.cxx @@ -30,15 +30,21 @@ #include "sal/config.h" #include "boost/noncopyable.hpp" -#include "cppuhelper/implbase2.hxx" -#include "com/sun/star/lang/XServiceInfo.hpp" #include "com/sun/star/container/NoSuchElementException.hpp" #include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/NotInitializedException.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" #include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/uno/Sequence.hxx" #include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/weak.hxx" #include "osl/mutex.hxx" #include "rtl/ref.hxx" #include "rtl/ustring.h" @@ -57,12 +63,15 @@ namespace { namespace css = com::sun::star; class Service: - public cppu::WeakImplHelper2< - css::lang::XServiceInfo, css::container::XHierarchicalNameAccess >, + public cppu::WeakImplHelper3< + css::lang::XServiceInfo, css::lang::XInitialization, + css::container::XHierarchicalNameAccess >, private boost::noncopyable { public: - Service(css::uno::Reference< css::uno::XComponentContext > const & context); + explicit Service( + css::uno::Reference< css::uno::XComponentContext > const & context): + context_(context) {} private: virtual ~Service() {} @@ -79,30 +88,57 @@ private: getSupportedServiceNames() throw (css::uno::RuntimeException) { return read_only_access::getSupportedServiceNames(); } + virtual void SAL_CALL initialize( + css::uno::Sequence< css::uno::Any > const & aArguments) + throw (css::uno::Exception, css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL getByHierarchicalName( rtl::OUString const & aName) throw ( css::container::NoSuchElementException, css::uno::RuntimeException) - { return root_->getByHierarchicalName(aName); } + { return getRoot()->getByHierarchicalName(aName); } virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) throw (css::uno::RuntimeException) - { return root_->hasByHierarchicalName(aName); } + { return getRoot()->hasByHierarchicalName(aName); } + + rtl::Reference< RootAccess > getRoot(); + css::uno::Reference< css::uno::XComponentContext > context_; + + osl::Mutex mutex_; rtl::Reference< RootAccess > root_; }; -Service::Service( - css::uno::Reference< css::uno::XComponentContext > const & context) +void Service::initialize(css::uno::Sequence< css::uno::Any > const & aArguments) + throw (css::uno::Exception, css::uno::RuntimeException) { - osl::MutexGuard guard(*lock()); - Components & components = Components::getSingleton(context); - root_ = new RootAccess( - components, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")), - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), false); + OUString locale; + if (aArguments.getLength() != 1 || !(aArguments[0] >>= locale)) { + throw css::lang::IllegalArgumentException( + "not exactly one string argument", + static_cast< cppu::OWeakObject * >(this), -1); + } + osl::MutexGuard g1(mutex_); + if (root_.is()) { + throw css::uno::RuntimeException( + "already initialized", static_cast< cppu::OWeakObject * >(this)); + } + osl::MutexGuard g2(*lock()); + Components & components = Components::getSingleton(context_); + root_ = new RootAccess(components, "/", locale, false); components.addRootAccess(root_); } +rtl::Reference< RootAccess > Service::getRoot() { + osl::MutexGuard g(mutex_); + if (!root_.is()) { + throw css::lang::NotInitializedException( + "not initialized", static_cast< cppu::OWeakObject * >(this)); + } + return root_; +} + } css::uno::Reference< css::uno::XInterface > create( diff --git a/configmgr/source/readwriteaccess.cxx b/configmgr/source/readwriteaccess.cxx index 0e4415f..5d8d1de 100644 --- a/configmgr/source/readwriteaccess.cxx +++ b/configmgr/source/readwriteaccess.cxx @@ -30,18 +30,24 @@ #include "sal/config.h" #include "boost/noncopyable.hpp" -#include "cppuhelper/implbase2.hxx" +#include "com/sun/star/configuration/XReadWriteAccess.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" #include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/NotInitializedException.hpp" #include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XInitialization.hpp" #include "com/sun/star/lang/XServiceInfo.hpp" -#include "com/sun/star/container/NoSuchElementException.hpp" -#include "com/sun/star/configuration/XReadWriteAccess.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" #include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/uno/Sequence.hxx" #include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uno/XInterface.hpp" #include "com/sun/star/util/ChangesSet.hpp" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/mutex.hxx" #include "rtl/ref.hxx" #include "rtl/ustring.h" #include "rtl/ustring.hxx" @@ -59,12 +65,15 @@ namespace { namespace css = com::sun::star; class Service: - public cppu::WeakImplHelper2< - css::lang::XServiceInfo, css::configuration::XReadWriteAccess >, + public cppu::WeakImplHelper3< + css::lang::XServiceInfo, css::lang::XInitialization, + css::configuration::XReadWriteAccess >, private boost::noncopyable { public: - Service(css::uno::Reference< css::uno::XComponentContext > const & context); + explicit Service( + css::uno::Reference< css::uno::XComponentContext > const & context): + context_(context) {} private: virtual ~Service() {} @@ -81,15 +90,19 @@ private: getSupportedServiceNames() throw (css::uno::RuntimeException) { return read_write_access::getSupportedServiceNames(); } + virtual void SAL_CALL initialize( + css::uno::Sequence< css::uno::Any > const & aArguments) + throw (css::uno::Exception, css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL getByHierarchicalName( rtl::OUString const & aName) throw ( css::container::NoSuchElementException, css::uno::RuntimeException) - { return root_->getByHierarchicalName(aName); } + { return getRoot()->getByHierarchicalName(aName); } virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) throw (css::uno::RuntimeException) - { return root_->hasByHierarchicalName(aName); } + { return getRoot()->hasByHierarchicalName(aName); } virtual void SAL_CALL replaceByHierarchicalName( rtl::OUString const & aName, css::uno::Any const & aElement) @@ -97,34 +110,57 @@ private: css::lang::IllegalArgumentException, css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException) - { root_->replaceByHierarchicalName(aName, aElement); } + { getRoot()->replaceByHierarchicalName(aName, aElement); } virtual void SAL_CALL commitChanges() throw (css::lang::WrappedTargetException, css::uno::RuntimeException) - { root_->commitChanges(); } + { getRoot()->commitChanges(); } virtual sal_Bool SAL_CALL hasPendingChanges() throw (css::uno::RuntimeException) - { return root_->hasPendingChanges(); } + { return getRoot()->hasPendingChanges(); } virtual css::util::ChangesSet SAL_CALL getPendingChanges() throw (css::uno::RuntimeException) - { return root_->getPendingChanges(); } + { return getRoot()->getPendingChanges(); } + rtl::Reference< RootAccess > getRoot(); + + css::uno::Reference< css::uno::XComponentContext > context_; + + osl::Mutex mutex_; rtl::Reference< RootAccess > root_; }; -Service::Service( - css::uno::Reference< css::uno::XComponentContext > const & context) +void Service::initialize(css::uno::Sequence< css::uno::Any > const & aArguments) + throw (css::uno::Exception, css::uno::RuntimeException) { - osl::MutexGuard guard(*lock()); - Components & components = Components::getSingleton(context); - root_ = new RootAccess( - components, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")), - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), true); + OUString locale; + if (aArguments.getLength() != 1 || !(aArguments[0] >>= locale)) { + throw css::lang::IllegalArgumentException( + "not exactly one string argument", + static_cast< cppu::OWeakObject * >(this), -1); + } + osl::MutexGuard g1(mutex_); + if (root_.is()) { + throw css::uno::RuntimeException( + "already initialized", static_cast< cppu::OWeakObject * >(this)); + } + osl::MutexGuard g2(*lock()); + Components & components = Components::getSingleton(context_); + root_ = new RootAccess(components, "/", locale, true); components.addRootAccess(root_); } +rtl::Reference< RootAccess > Service::getRoot() { + osl::MutexGuard g(mutex_); + if (!root_.is()) { + throw css::lang::NotInitializedException( + "not initialized", static_cast< cppu::OWeakObject * >(this)); + } + return root_; +} + } css::uno::Reference< css::uno::XInterface > create( diff --git a/offapi/com/sun/star/configuration/ReadOnlyAccess.idl b/offapi/com/sun/star/configuration/ReadOnlyAccess.idl index aaeb6da..1da0593 100644 --- a/offapi/com/sun/star/configuration/ReadOnlyAccess.idl +++ b/offapi/com/sun/star/configuration/ReadOnlyAccess.idl @@ -34,13 +34,20 @@ module com { module sun { module star { module configuration { -/* Provides easy read-only access to the complete configuration. +/** Provides easy read-only access to the complete configuration. - <p>This singleton is still unpublished and unstable.</p> + <p>This service is still unpublished and unstable.</p> - @since LibreOffice 3.6 + @since LibreOffice 3.7 */ -singleton ReadOnlyAccess: com::sun::star::container::XHierarchicalNameAccess; +service ReadOnlyAccess: com::sun::star::container::XHierarchicalNameAccess { + /** Service constructor. + + @param locale a string representation of the locale to use for localized + properties; use <code>*</code> for all-locale access + */ + create([in] string locale); +}; }; }; }; }; diff --git a/offapi/com/sun/star/configuration/ReadWriteAccess.idl b/offapi/com/sun/star/configuration/ReadWriteAccess.idl index bae50bc..2522baa 100644 --- a/offapi/com/sun/star/configuration/ReadWriteAccess.idl +++ b/offapi/com/sun/star/configuration/ReadWriteAccess.idl @@ -34,13 +34,20 @@ module com { module sun { module star { module configuration { -/* Provides easy read/write access to the complete configuration. +/** Provides easy read/write access to the complete configuration. - <p>This service is still unpublished and unstable.</p> + <p>This service is still unpublished and unstable.</p> - @since LibreOffice 3.6 + @since LibreOffice 3.7 */ -service ReadWriteAccess: com::sun::star::configuration::XReadWriteAccess; +service ReadWriteAccess: com::sun::star::configuration::XReadWriteAccess { + /** Service constructor. + + @param locale a string representation of the locale to use for localized + properties; use <code>*</code> for all-locale access + */ + create([in] string locale); +}; }; }; }; }; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits