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 <helper/mischelper.hxx>
24 #include <com/sun/star/configuration/theDefaultProvider.hpp>
25 #include <com/sun/star/container/XNameAccess.hpp>
26 #include <com/sun/star/container/XContainer.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
29 #include <sal/log.hxx>
30 #include <rtl/ref.hxx>
31 #include <cppuhelper/implbase.hxx>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <unotools/syslocale.hxx>
35 #include <comphelper/propertysequence.hxx>
37 #include <string_view>
38 #include <unordered_map>
40 using namespace com::sun::star::uno
;
41 using namespace com::sun::star::lang
;
42 using namespace com::sun::star::configuration
;
43 using namespace com::sun::star::container
;
44 using namespace framework
;
48 class ConfigurationAccess_UICategory
: public ::cppu::WeakImplHelper
<XNameAccess
,XContainerListener
>
52 ConfigurationAccess_UICategory( std::u16string_view aModuleName
, const Reference
< XNameAccess
>& xGenericUICommands
, const Reference
< XComponentContext
>& rxContext
);
53 virtual ~ConfigurationAccess_UICategory() override
;
56 virtual css::uno::Any SAL_CALL
getByName( const OUString
& aName
) override
;
58 virtual css::uno::Sequence
< OUString
> SAL_CALL
getElementNames() override
;
60 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
63 virtual css::uno::Type SAL_CALL
getElementType() override
;
65 virtual sal_Bool SAL_CALL
hasElements() override
;
67 // container.XContainerListener
68 virtual void SAL_CALL
elementInserted( const ContainerEvent
& aEvent
) override
;
69 virtual void SAL_CALL
elementRemoved ( const ContainerEvent
& aEvent
) override
;
70 virtual void SAL_CALL
elementReplaced( const ContainerEvent
& aEvent
) override
;
72 // lang.XEventListener
73 virtual void SAL_CALL
disposing( const EventObject
& aEvent
) override
;
76 Any
getUINameFromID( const OUString
& rId
);
77 Any
getUINameFromCache( const OUString
& rId
);
78 Sequence
< OUString
> getAllIds();
82 typedef std::unordered_map
< OUString
,
83 OUString
> IdToInfoCache
;
85 void initializeConfigAccess();
87 OUString m_aConfigCategoryAccess
;
88 OUString m_aPropUIName
;
89 Reference
< XNameAccess
> m_xGenericUICategories
;
90 Reference
< XMultiServiceFactory
> m_xConfigProvider
;
91 Reference
< XNameAccess
> m_xConfigAccess
;
92 rtl::Reference
< WeakContainerListener
> m_xConfigListener
;
93 bool m_bConfigAccessInitialized
;
95 IdToInfoCache m_aIdCache
;
98 // XInterface, XTypeProvider
100 ConfigurationAccess_UICategory::ConfigurationAccess_UICategory( std::u16string_view aModuleName
, const Reference
< XNameAccess
>& rGenericUICategories
, const Reference
< XComponentContext
>& rxContext
) :
101 // Create configuration hierarchical access name
102 m_aConfigCategoryAccess(
103 OUString::Concat("/org.openoffice.Office.UI.") + aModuleName
+ "/Commands/Categories"),
104 m_aPropUIName( u
"Name"_ustr
),
105 m_xGenericUICategories( rGenericUICategories
),
106 m_xConfigProvider(theDefaultProvider::get( rxContext
)),
107 m_bConfigAccessInitialized( false ),
108 m_bCacheFilled( false )
112 ConfigurationAccess_UICategory::~ConfigurationAccess_UICategory()
115 std::unique_lock
g(aMutex
);
116 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
117 if ( xContainer
.is() )
118 xContainer
->removeContainerListener(m_xConfigListener
);
122 Any SAL_CALL
ConfigurationAccess_UICategory::getByName( const OUString
& rId
)
124 std::unique_lock
g(aMutex
);
125 if ( !m_bConfigAccessInitialized
)
127 initializeConfigAccess();
128 m_bConfigAccessInitialized
= true;
133 Any a
= getUINameFromID( rId
);
136 throw NoSuchElementException();
141 Sequence
< OUString
> SAL_CALL
ConfigurationAccess_UICategory::getElementNames()
146 sal_Bool SAL_CALL
ConfigurationAccess_UICategory::hasByName( const OUString
& rId
)
148 return getByName( rId
).hasValue();
152 Type SAL_CALL
ConfigurationAccess_UICategory::getElementType()
154 return cppu::UnoType
<OUString
>::get();
157 sal_Bool SAL_CALL
ConfigurationAccess_UICategory::hasElements()
159 // There must be global categories!
163 void ConfigurationAccess_UICategory::fillCache()
165 SAL_INFO( "fwk", "framework (cd100003) ::ConfigurationAccess_UICategory::fillCache" );
167 if ( m_bCacheFilled
)
171 const Sequence
< OUString
> aNameSeq
= m_xConfigAccess
->getElementNames();
173 for ( OUString
const & rName
: aNameSeq
)
177 Reference
< XNameAccess
> xNameAccess(m_xConfigAccess
->getByName( rName
),UNO_QUERY
);
178 if ( xNameAccess
.is() )
180 xNameAccess
->getByName( m_aPropUIName
) >>= aUIName
;
182 m_aIdCache
.emplace( rName
, aUIName
);
185 catch ( const css::lang::WrappedTargetException
& )
188 catch ( const css::container::NoSuchElementException
& )
193 m_bCacheFilled
= true;
196 Any
ConfigurationAccess_UICategory::getUINameFromID( const OUString
& rId
)
202 a
= getUINameFromCache( rId
);
205 // Try to ask our global commands configuration access
206 if ( m_xGenericUICategories
.is() )
210 return m_xGenericUICategories
->getByName( rId
);
212 catch ( const css::lang::WrappedTargetException
& )
215 catch ( const css::container::NoSuchElementException
& )
221 catch( const css::container::NoSuchElementException
& )
224 catch ( const css::lang::WrappedTargetException
& )
231 Any
ConfigurationAccess_UICategory::getUINameFromCache( const OUString
& rId
)
235 IdToInfoCache::const_iterator pIter
= m_aIdCache
.find( rId
);
236 if ( pIter
!= m_aIdCache
.end() )
242 Sequence
< OUString
> ConfigurationAccess_UICategory::getAllIds()
245 std::unique_lock
g(aMutex
);
247 if ( !m_bConfigAccessInitialized
)
249 initializeConfigAccess();
250 m_bConfigAccessInitialized
= true;
254 if ( m_xConfigAccess
.is() )
258 Sequence
< OUString
> aNameSeq
= m_xConfigAccess
->getElementNames();
260 if ( m_xGenericUICategories
.is() )
262 // Create concat list of supported user interface commands of the module
263 Sequence
< OUString
> aGenericNameSeq
= m_xGenericUICategories
->getElementNames();
264 sal_uInt32 nCount1
= aNameSeq
.getLength();
265 sal_uInt32 nCount2
= aGenericNameSeq
.getLength();
267 aNameSeq
.realloc( nCount1
+ nCount2
);
268 OUString
* pNameSeq
= aNameSeq
.getArray();
269 const OUString
* pGenericSeq
= aGenericNameSeq
.getConstArray();
270 for ( sal_uInt32 i
= 0; i
< nCount2
; i
++ )
271 pNameSeq
[nCount1
+i
] = pGenericSeq
[i
];
276 catch( const css::container::NoSuchElementException
& )
279 catch ( const css::lang::WrappedTargetException
& )
284 return Sequence
< OUString
>();
287 void ConfigurationAccess_UICategory::initializeConfigAccess()
291 Sequence
<Any
> aArgs(comphelper::InitAnyPropertySequence(
293 {"nodepath", Any(m_aConfigCategoryAccess
)}
296 m_xConfigAccess
.set( m_xConfigProvider
->createInstanceWithArguments(
297 u
"com.sun.star.configuration.ConfigurationAccess"_ustr
, aArgs
),UNO_QUERY
);
298 if ( m_xConfigAccess
.is() )
300 // Add as container listener
301 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
302 if ( xContainer
.is() )
304 m_xConfigListener
= new WeakContainerListener(this);
305 xContainer
->addContainerListener(m_xConfigListener
);
309 catch ( const WrappedTargetException
& )
312 catch ( const Exception
& )
317 // container.XContainerListener
318 void SAL_CALL
ConfigurationAccess_UICategory::elementInserted( const ContainerEvent
& )
322 void SAL_CALL
ConfigurationAccess_UICategory::elementRemoved ( const ContainerEvent
& )
326 void SAL_CALL
ConfigurationAccess_UICategory::elementReplaced( const ContainerEvent
& )
330 // lang.XEventListener
331 void SAL_CALL
ConfigurationAccess_UICategory::disposing( const EventObject
& aEvent
)
334 // remove our reference to the config access
335 std::unique_lock
g(aMutex
);
337 Reference
< XInterface
> xIfac1( aEvent
.Source
, UNO_QUERY
);
338 Reference
< XInterface
> xIfac2( m_xConfigAccess
, UNO_QUERY
);
339 if ( xIfac1
== xIfac2
)
340 m_xConfigAccess
.clear();
343 class UICategoryDescription
: public UICommandDescription
346 explicit UICategoryDescription( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
348 virtual OUString SAL_CALL
getImplementationName() override
350 return u
"com.sun.star.comp.framework.UICategoryDescription"_ustr
;
353 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
355 return cppu::supportsService(this, ServiceName
);
358 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
360 return {u
"com.sun.star.ui.UICategoryDescription"_ustr
};
365 UICategoryDescription::UICategoryDescription( const Reference
< XComponentContext
>& rxContext
) :
366 UICommandDescription(rxContext
,true)
368 SvtSysLocale aSysLocale
;
369 const LanguageTag
& rCurrentLanguage
= aSysLocale
.GetUILanguageTag();
370 Reference
< XNameAccess
> xEmpty
;
371 OUString
aGenericCategories( u
"GenericCategories"_ustr
);
372 m_xGenericUICommands
[rCurrentLanguage
] = new ConfigurationAccess_UICategory( aGenericCategories
, xEmpty
, rxContext
);
374 // insert generic categories mappings
375 m_aModuleToCommandFileMap
.emplace( u
"generic"_ustr
, aGenericCategories
);
377 auto& rMap
= m_aUICommandsHashMap
[rCurrentLanguage
];
378 UICommandsHashMap::iterator pCatIter
= rMap
.find( aGenericCategories
);
379 if ( pCatIter
!= rMap
.end() )
380 pCatIter
->second
= m_xGenericUICommands
[rCurrentLanguage
];
382 impl_fillElements("ooSetupFactoryCmdCategoryConfigRef");
387 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
388 com_sun_star_comp_framework_UICategoryDescription_get_implementation(
389 css::uno::XComponentContext
*context
,
390 css::uno::Sequence
<css::uno::Any
> const &)
392 return cppu::acquire(new UICategoryDescription(context
));
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */