1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <uielement/uicommanddescription.hxx>
22 #include "properties.h"
24 #include "helper/mischelper.hxx"
26 #include <com/sun/star/beans/PropertyValue.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/configuration/theDefaultProvider.hpp>
29 #include <com/sun/star/container/XNameAccess.hpp>
30 #include <com/sun/star/container/XNameContainer.hpp>
31 #include <com/sun/star/container/XContainer.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <rtl/ustrbuf.hxx>
35 #include <cppuhelper/implbase2.hxx>
36 #include <cppuhelper/supportsservice.hxx>
37 #include <unotools/configmgr.hxx>
39 #include <vcl/mnemonic.hxx>
40 #include <comphelper/sequence.hxx>
42 #include <unordered_map>
44 using namespace com::sun::star::uno
;
45 using namespace com::sun::star::lang
;
46 using namespace com::sun::star::beans
;
47 using namespace com::sun::star::configuration
;
48 using namespace com::sun::star::container
;
49 using namespace ::com::sun::star::frame
;
50 using namespace framework
;
54 struct ModuleToCategory
56 const char* pModuleId
;
57 const char* pCommands
;
60 static const char GENERIC_MODULE_NAME
[] = "generic";
61 static const char CONFIGURATION_ROOT_ACCESS
[] = "/org.openoffice.Office.UI.";
62 static const char CONFIGURATION_CATEGORY_ELEMENT_ACCESS
[] = "/Commands/Categories";
63 static const char CONFIGURATION_PROPERTY_NAME
[] = "Name";
65 class ConfigurationAccess_UICategory
: public ::cppu::WeakImplHelper2
<XNameAccess
,XContainerListener
>
69 ConfigurationAccess_UICategory( const OUString
& aModuleName
, const Reference
< XNameAccess
>& xGenericUICommands
, const Reference
< XComponentContext
>& rxContext
);
70 virtual ~ConfigurationAccess_UICategory();
73 virtual ::com::sun::star::uno::Any SAL_CALL
getByName( const OUString
& aName
)
74 throw (::com::sun::star::container::NoSuchElementException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
76 virtual ::com::sun::star::uno::Sequence
< OUString
> SAL_CALL
getElementNames()
77 throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
79 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
)
80 throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
83 virtual ::com::sun::star::uno::Type SAL_CALL
getElementType()
84 throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
86 virtual sal_Bool SAL_CALL
hasElements()
87 throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
89 // container.XContainerListener
90 virtual void SAL_CALL
elementInserted( const ContainerEvent
& aEvent
) throw(RuntimeException
, std::exception
) SAL_OVERRIDE
;
91 virtual void SAL_CALL
elementRemoved ( const ContainerEvent
& aEvent
) throw(RuntimeException
, std::exception
) SAL_OVERRIDE
;
92 virtual void SAL_CALL
elementReplaced( const ContainerEvent
& aEvent
) throw(RuntimeException
, std::exception
) SAL_OVERRIDE
;
94 // lang.XEventListener
95 virtual void SAL_CALL
disposing( const EventObject
& aEvent
) throw(RuntimeException
, std::exception
) SAL_OVERRIDE
;
98 Any
getUINameFromID( const OUString
& rId
);
99 Any
getUINameFromCache( const OUString
& rId
);
100 Sequence
< OUString
> getAllIds();
104 typedef std::unordered_map
< OUString
,
107 std::equal_to
< OUString
> > IdToInfoCache
;
109 bool initializeConfigAccess();
111 OUString m_aConfigCategoryAccess
;
112 OUString m_aPropUIName
;
113 Reference
< XNameAccess
> m_xGenericUICategories
;
114 Reference
< XMultiServiceFactory
> m_xConfigProvider
;
115 Reference
< XNameAccess
> m_xConfigAccess
;
116 Reference
< XContainerListener
> m_xConfigListener
;
117 bool m_bConfigAccessInitialized
;
119 IdToInfoCache m_aIdCache
;
122 // XInterface, XTypeProvider
124 ConfigurationAccess_UICategory::ConfigurationAccess_UICategory( const OUString
& aModuleName
, const Reference
< XNameAccess
>& rGenericUICategories
, const Reference
< XComponentContext
>& rxContext
) :
125 m_aConfigCategoryAccess( CONFIGURATION_ROOT_ACCESS
),
126 m_aPropUIName( CONFIGURATION_PROPERTY_NAME
),
127 m_xGenericUICategories( rGenericUICategories
),
128 m_bConfigAccessInitialized( false ),
129 m_bCacheFilled( false )
131 // Create configuration hierarchical access name
132 m_aConfigCategoryAccess
+= aModuleName
;
133 m_aConfigCategoryAccess
+= CONFIGURATION_CATEGORY_ELEMENT_ACCESS
;
135 m_xConfigProvider
= theDefaultProvider::get( rxContext
);
138 ConfigurationAccess_UICategory::~ConfigurationAccess_UICategory()
141 osl::MutexGuard
g(aMutex
);
142 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
143 if ( xContainer
.is() )
144 xContainer
->removeContainerListener(m_xConfigListener
);
148 Any SAL_CALL
ConfigurationAccess_UICategory::getByName( const OUString
& rId
)
149 throw ( NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
)
151 osl::MutexGuard
g(aMutex
);
152 if ( !m_bConfigAccessInitialized
)
154 initializeConfigAccess();
155 m_bConfigAccessInitialized
= true;
160 Any a
= getUINameFromID( rId
);
163 throw NoSuchElementException();
168 Sequence
< OUString
> SAL_CALL
ConfigurationAccess_UICategory::getElementNames()
169 throw ( RuntimeException
, std::exception
)
174 sal_Bool SAL_CALL
ConfigurationAccess_UICategory::hasByName( const OUString
& rId
)
175 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
177 return getByName( rId
).hasValue();
181 Type SAL_CALL
ConfigurationAccess_UICategory::getElementType()
182 throw ( RuntimeException
, std::exception
)
184 return( cppu::UnoType
<OUString
>::get());
187 sal_Bool SAL_CALL
ConfigurationAccess_UICategory::hasElements()
188 throw ( RuntimeException
, std::exception
)
190 // There must be global categories!
194 bool ConfigurationAccess_UICategory::fillCache()
196 SAL_INFO( "fwk", "framework (cd100003) ::ConfigurationAccess_UICategory::fillCache" );
198 if ( m_bCacheFilled
)
203 Sequence
< OUString
> aNameSeq
= m_xConfigAccess
->getElementNames();
205 for ( i
= 0; i
< aNameSeq
.getLength(); i
++ )
209 Reference
< XNameAccess
> xNameAccess(m_xConfigAccess
->getByName( aNameSeq
[i
] ),UNO_QUERY
);
210 if ( xNameAccess
.is() )
212 xNameAccess
->getByName( m_aPropUIName
) >>= aUIName
;
214 m_aIdCache
.insert( IdToInfoCache::value_type( aNameSeq
[i
], aUIName
));
217 catch ( const com::sun::star::lang::WrappedTargetException
& )
220 catch ( const com::sun::star::container::NoSuchElementException
& )
225 m_bCacheFilled
= true;
230 Any
ConfigurationAccess_UICategory::getUINameFromID( const OUString
& rId
)
236 a
= getUINameFromCache( rId
);
239 // Try to ask our global commands configuration access
240 if ( m_xGenericUICategories
.is() )
244 return m_xGenericUICategories
->getByName( rId
);
246 catch ( const com::sun::star::lang::WrappedTargetException
& )
249 catch ( const com::sun::star::container::NoSuchElementException
& )
255 catch( const com::sun::star::container::NoSuchElementException
& )
258 catch ( const com::sun::star::lang::WrappedTargetException
& )
265 Any
ConfigurationAccess_UICategory::getUINameFromCache( const OUString
& rId
)
269 IdToInfoCache::const_iterator pIter
= m_aIdCache
.find( rId
);
270 if ( pIter
!= m_aIdCache
.end() )
276 Sequence
< OUString
> ConfigurationAccess_UICategory::getAllIds()
279 osl::MutexGuard
g(aMutex
);
281 if ( !m_bConfigAccessInitialized
)
283 initializeConfigAccess();
284 m_bConfigAccessInitialized
= true;
288 if ( m_xConfigAccess
.is() )
290 Reference
< XNameAccess
> xNameAccess
;
294 Sequence
< OUString
> aNameSeq
= m_xConfigAccess
->getElementNames();
296 if ( m_xGenericUICategories
.is() )
298 // Create concat list of supported user interface commands of the module
299 Sequence
< OUString
> aGenericNameSeq
= m_xGenericUICategories
->getElementNames();
300 sal_uInt32 nCount1
= aNameSeq
.getLength();
301 sal_uInt32 nCount2
= aGenericNameSeq
.getLength();
303 aNameSeq
.realloc( nCount1
+ nCount2
);
304 OUString
* pNameSeq
= aNameSeq
.getArray();
305 const OUString
* pGenericSeq
= aGenericNameSeq
.getConstArray();
306 for ( sal_uInt32 i
= 0; i
< nCount2
; i
++ )
307 pNameSeq
[nCount1
+i
] = pGenericSeq
[i
];
312 catch( const com::sun::star::container::NoSuchElementException
& )
315 catch ( const com::sun::star::lang::WrappedTargetException
& )
320 return Sequence
< OUString
>();
323 bool ConfigurationAccess_UICategory::initializeConfigAccess()
325 Sequence
< Any
> aArgs( 1 );
326 PropertyValue aPropValue
;
330 aPropValue
.Name
= "nodepath";
331 aPropValue
.Value
<<= m_aConfigCategoryAccess
;
332 aArgs
[0] <<= aPropValue
;
334 m_xConfigAccess
= Reference
< XNameAccess
>( m_xConfigProvider
->createInstanceWithArguments(
335 "com.sun.star.configuration.ConfigurationAccess", aArgs
),UNO_QUERY
);
336 if ( m_xConfigAccess
.is() )
338 // Add as container listener
339 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
340 if ( xContainer
.is() )
342 m_xConfigListener
= new WeakContainerListener(this);
343 xContainer
->addContainerListener(m_xConfigListener
);
349 catch ( const WrappedTargetException
& )
352 catch ( const Exception
& )
359 // container.XContainerListener
360 void SAL_CALL
ConfigurationAccess_UICategory::elementInserted( const ContainerEvent
& ) throw(RuntimeException
, std::exception
)
364 void SAL_CALL
ConfigurationAccess_UICategory::elementRemoved ( const ContainerEvent
& ) throw(RuntimeException
, std::exception
)
368 void SAL_CALL
ConfigurationAccess_UICategory::elementReplaced( const ContainerEvent
& ) throw(RuntimeException
, std::exception
)
372 // lang.XEventListener
373 void SAL_CALL
ConfigurationAccess_UICategory::disposing( const EventObject
& aEvent
) throw(RuntimeException
, std::exception
)
376 // remove our reference to the config access
377 osl::MutexGuard
g(aMutex
);
379 Reference
< XInterface
> xIfac1( aEvent
.Source
, UNO_QUERY
);
380 Reference
< XInterface
> xIfac2( m_xConfigAccess
, UNO_QUERY
);
381 if ( xIfac1
== xIfac2
)
382 m_xConfigAccess
.clear();
385 class UICategoryDescription
: public UICommandDescription
388 UICategoryDescription( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
389 virtual ~UICategoryDescription();
391 virtual OUString SAL_CALL
getImplementationName()
392 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
394 return OUString("com.sun.star.comp.framework.UICategoryDescription");
397 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
)
398 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
400 return cppu::supportsService(this, ServiceName
);
403 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames()
404 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
406 css::uno::Sequence
< OUString
> aSeq(1);
407 aSeq
[0] = "com.sun.star.ui.UICategoryDescription";
412 virtual css::uno::Reference
< css::container::XNameAccess
> impl_createConfigAccess(const OUString
& _sName
) SAL_OVERRIDE
;
415 UICategoryDescription::UICategoryDescription( const Reference
< XComponentContext
>& rxContext
) :
416 UICommandDescription(rxContext
,true)
418 Reference
< XNameAccess
> xEmpty
;
419 OUString
aGenericCategories( "GenericCategories" );
420 m_xGenericUICommands
= new ConfigurationAccess_UICategory( aGenericCategories
, xEmpty
, rxContext
);
422 // insert generic categories mappings
423 m_aModuleToCommandFileMap
.insert( ModuleToCommandFileMap::value_type(
424 OUString(GENERIC_MODULE_NAME
), aGenericCategories
));
426 UICommandsHashMap::iterator pCatIter
= m_aUICommandsHashMap
.find( aGenericCategories
);
427 if ( pCatIter
!= m_aUICommandsHashMap
.end() )
428 pCatIter
->second
= m_xGenericUICommands
;
430 impl_fillElements("ooSetupFactoryCmdCategoryConfigRef");
433 UICategoryDescription::~UICategoryDescription()
436 Reference
< XNameAccess
> UICategoryDescription::impl_createConfigAccess(const OUString
& _sName
)
438 return new ConfigurationAccess_UICategory( _sName
, m_xGenericUICommands
, m_xContext
);
443 css::uno::Reference
<css::uno::XComponentContext
> const & context
):
444 instance(static_cast<cppu::OWeakObject
*>(
445 new UICategoryDescription(context
)))
449 css::uno::Reference
<css::uno::XInterface
> instance
;
453 public rtl::StaticWithArg
<
454 Instance
, css::uno::Reference
<css::uno::XComponentContext
>, Singleton
>
459 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
460 com_sun_star_comp_framework_UICategoryDescription_get_implementation(
461 css::uno::XComponentContext
*context
,
462 css::uno::Sequence
<css::uno::Any
> const &)
464 return cppu::acquire(static_cast<cppu::OWeakObject
*>(
465 Singleton::get(context
).instance
.get()));
468 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */