Line data Source code
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 <uielement/uicommanddescription.hxx>
21 :
22 : #include "properties.h"
23 :
24 : #include "helper/mischelper.hxx"
25 :
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>
33 :
34 : #include <rtl/ustrbuf.hxx>
35 : #include <cppuhelper/implbase2.hxx>
36 : #include <cppuhelper/supportsservice.hxx>
37 : #include <unotools/configmgr.hxx>
38 :
39 : #include <vcl/mnemonic.hxx>
40 : #include <comphelper/sequence.hxx>
41 :
42 : #include <unordered_map>
43 :
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;
51 :
52 : namespace {
53 :
54 : struct ModuleToCategory
55 : {
56 : const char* pModuleId;
57 : const char* pCommands;
58 : };
59 :
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";
64 :
65 : class ConfigurationAccess_UICategory : public ::cppu::WeakImplHelper2<XNameAccess,XContainerListener>
66 : {
67 : osl::Mutex aMutex;
68 : public:
69 : ConfigurationAccess_UICategory( const OUString& aModuleName, const Reference< XNameAccess >& xGenericUICommands, const Reference< XComponentContext >& rxContext );
70 : virtual ~ConfigurationAccess_UICategory();
71 :
72 : // XNameAccess
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;
75 :
76 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getElementNames()
77 : throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
78 :
79 : virtual sal_Bool SAL_CALL hasByName( const OUString& aName )
80 : throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
81 :
82 : // XElementAccess
83 : virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
84 : throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
85 :
86 : virtual sal_Bool SAL_CALL hasElements()
87 : throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
88 :
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;
93 :
94 : // lang.XEventListener
95 : virtual void SAL_CALL disposing( const EventObject& aEvent ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
96 :
97 : protected:
98 : Any getUINameFromID( const OUString& rId );
99 : Any getUINameFromCache( const OUString& rId );
100 : Sequence< OUString > getAllIds();
101 : bool fillCache();
102 :
103 : private:
104 : typedef std::unordered_map< OUString,
105 : OUString,
106 : OUStringHash,
107 : std::equal_to< OUString > > IdToInfoCache;
108 :
109 : bool initializeConfigAccess();
110 :
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;
118 : bool m_bCacheFilled;
119 : IdToInfoCache m_aIdCache;
120 : };
121 :
122 : // XInterface, XTypeProvider
123 :
124 2 : 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 2 : m_bCacheFilled( false )
130 : {
131 : // Create configuration hierarchical access name
132 2 : m_aConfigCategoryAccess += aModuleName;
133 2 : m_aConfigCategoryAccess += CONFIGURATION_CATEGORY_ELEMENT_ACCESS;
134 :
135 2 : m_xConfigProvider = theDefaultProvider::get( rxContext );
136 2 : }
137 :
138 6 : ConfigurationAccess_UICategory::~ConfigurationAccess_UICategory()
139 : {
140 : // SAFE
141 2 : osl::MutexGuard g(aMutex);
142 4 : Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
143 2 : if ( xContainer.is() )
144 2 : xContainer->removeContainerListener(m_xConfigListener);
145 4 : }
146 :
147 : // XNameAccess
148 0 : Any SAL_CALL ConfigurationAccess_UICategory::getByName( const OUString& rId )
149 : throw ( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
150 : {
151 0 : osl::MutexGuard g(aMutex);
152 0 : if ( !m_bConfigAccessInitialized )
153 : {
154 0 : initializeConfigAccess();
155 0 : m_bConfigAccessInitialized = true;
156 0 : fillCache();
157 : }
158 :
159 : // SAFE
160 0 : Any a = getUINameFromID( rId );
161 :
162 0 : if ( !a.hasValue() )
163 0 : throw NoSuchElementException();
164 :
165 0 : return a;
166 : }
167 :
168 0 : Sequence< OUString > SAL_CALL ConfigurationAccess_UICategory::getElementNames()
169 : throw ( RuntimeException, std::exception )
170 : {
171 0 : return getAllIds();
172 : }
173 :
174 0 : sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasByName( const OUString& rId )
175 : throw (::com::sun::star::uno::RuntimeException, std::exception)
176 : {
177 0 : return getByName( rId ).hasValue();
178 : }
179 :
180 : // XElementAccess
181 0 : Type SAL_CALL ConfigurationAccess_UICategory::getElementType()
182 : throw ( RuntimeException, std::exception )
183 : {
184 0 : return( cppu::UnoType<OUString>::get());
185 : }
186 :
187 0 : sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasElements()
188 : throw ( RuntimeException, std::exception )
189 : {
190 : // There must be global categories!
191 0 : return sal_True;
192 : }
193 :
194 0 : bool ConfigurationAccess_UICategory::fillCache()
195 : {
196 : SAL_INFO( "fwk", "framework (cd100003) ::ConfigurationAccess_UICategory::fillCache" );
197 :
198 0 : if ( m_bCacheFilled )
199 0 : return true;
200 :
201 0 : sal_Int32 i( 0 );
202 0 : OUString aUIName;
203 0 : Sequence< OUString > aNameSeq = m_xConfigAccess->getElementNames();
204 :
205 0 : for ( i = 0; i < aNameSeq.getLength(); i++ )
206 : {
207 : try
208 : {
209 0 : Reference< XNameAccess > xNameAccess(m_xConfigAccess->getByName( aNameSeq[i] ),UNO_QUERY);
210 0 : if ( xNameAccess.is() )
211 : {
212 0 : xNameAccess->getByName( m_aPropUIName ) >>= aUIName;
213 :
214 0 : m_aIdCache.insert( IdToInfoCache::value_type( aNameSeq[i], aUIName ));
215 0 : }
216 : }
217 0 : catch ( const com::sun::star::lang::WrappedTargetException& )
218 : {
219 : }
220 0 : catch ( const com::sun::star::container::NoSuchElementException& )
221 : {
222 : }
223 : }
224 :
225 0 : m_bCacheFilled = true;
226 :
227 0 : return true;
228 : }
229 :
230 0 : Any ConfigurationAccess_UICategory::getUINameFromID( const OUString& rId )
231 : {
232 0 : Any a;
233 :
234 : try
235 : {
236 0 : a = getUINameFromCache( rId );
237 0 : if ( !a.hasValue() )
238 : {
239 : // Try to ask our global commands configuration access
240 0 : if ( m_xGenericUICategories.is() )
241 : {
242 : try
243 : {
244 0 : return m_xGenericUICategories->getByName( rId );
245 : }
246 0 : catch ( const com::sun::star::lang::WrappedTargetException& )
247 : {
248 : }
249 0 : catch ( const com::sun::star::container::NoSuchElementException& )
250 : {
251 : }
252 : }
253 : }
254 : }
255 0 : catch( const com::sun::star::container::NoSuchElementException& )
256 : {
257 : }
258 0 : catch ( const com::sun::star::lang::WrappedTargetException& )
259 : {
260 : }
261 :
262 0 : return a;
263 : }
264 :
265 0 : Any ConfigurationAccess_UICategory::getUINameFromCache( const OUString& rId )
266 : {
267 0 : Any a;
268 :
269 0 : IdToInfoCache::const_iterator pIter = m_aIdCache.find( rId );
270 0 : if ( pIter != m_aIdCache.end() )
271 0 : a <<= pIter->second;
272 :
273 0 : return a;
274 : }
275 :
276 0 : Sequence< OUString > ConfigurationAccess_UICategory::getAllIds()
277 : {
278 : // SAFE
279 0 : osl::MutexGuard g(aMutex);
280 :
281 0 : if ( !m_bConfigAccessInitialized )
282 : {
283 0 : initializeConfigAccess();
284 0 : m_bConfigAccessInitialized = true;
285 0 : fillCache();
286 : }
287 :
288 0 : if ( m_xConfigAccess.is() )
289 : {
290 0 : Reference< XNameAccess > xNameAccess;
291 :
292 : try
293 : {
294 0 : Sequence< OUString > aNameSeq = m_xConfigAccess->getElementNames();
295 :
296 0 : if ( m_xGenericUICategories.is() )
297 : {
298 : // Create concat list of supported user interface commands of the module
299 0 : Sequence< OUString > aGenericNameSeq = m_xGenericUICategories->getElementNames();
300 0 : sal_uInt32 nCount1 = aNameSeq.getLength();
301 0 : sal_uInt32 nCount2 = aGenericNameSeq.getLength();
302 :
303 0 : aNameSeq.realloc( nCount1 + nCount2 );
304 0 : OUString* pNameSeq = aNameSeq.getArray();
305 0 : const OUString* pGenericSeq = aGenericNameSeq.getConstArray();
306 0 : for ( sal_uInt32 i = 0; i < nCount2; i++ )
307 0 : pNameSeq[nCount1+i] = pGenericSeq[i];
308 : }
309 :
310 0 : return aNameSeq;
311 : }
312 0 : catch( const com::sun::star::container::NoSuchElementException& )
313 : {
314 : }
315 0 : catch ( const com::sun::star::lang::WrappedTargetException& )
316 : {
317 0 : }
318 : }
319 :
320 0 : return Sequence< OUString >();
321 : }
322 :
323 0 : bool ConfigurationAccess_UICategory::initializeConfigAccess()
324 : {
325 0 : Sequence< Any > aArgs( 1 );
326 0 : PropertyValue aPropValue;
327 :
328 : try
329 : {
330 0 : aPropValue.Name = "nodepath";
331 0 : aPropValue.Value <<= m_aConfigCategoryAccess;
332 0 : aArgs[0] <<= aPropValue;
333 :
334 0 : m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(
335 0 : "com.sun.star.configuration.ConfigurationAccess", aArgs ),UNO_QUERY );
336 0 : if ( m_xConfigAccess.is() )
337 : {
338 : // Add as container listener
339 0 : Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
340 0 : if ( xContainer.is() )
341 : {
342 0 : m_xConfigListener = new WeakContainerListener(this);
343 0 : xContainer->addContainerListener(m_xConfigListener);
344 0 : }
345 : }
346 :
347 0 : return true;
348 : }
349 0 : catch ( const WrappedTargetException& )
350 : {
351 : }
352 0 : catch ( const Exception& )
353 : {
354 : }
355 :
356 0 : return false;
357 : }
358 :
359 : // container.XContainerListener
360 0 : void SAL_CALL ConfigurationAccess_UICategory::elementInserted( const ContainerEvent& ) throw(RuntimeException, std::exception)
361 : {
362 0 : }
363 :
364 0 : void SAL_CALL ConfigurationAccess_UICategory::elementRemoved ( const ContainerEvent& ) throw(RuntimeException, std::exception)
365 : {
366 0 : }
367 :
368 0 : void SAL_CALL ConfigurationAccess_UICategory::elementReplaced( const ContainerEvent& ) throw(RuntimeException, std::exception)
369 : {
370 0 : }
371 :
372 : // lang.XEventListener
373 0 : void SAL_CALL ConfigurationAccess_UICategory::disposing( const EventObject& aEvent ) throw(RuntimeException, std::exception)
374 : {
375 : // SAFE
376 : // remove our reference to the config access
377 0 : osl::MutexGuard g(aMutex);
378 :
379 0 : Reference< XInterface > xIfac1( aEvent.Source, UNO_QUERY );
380 0 : Reference< XInterface > xIfac2( m_xConfigAccess, UNO_QUERY );
381 0 : if ( xIfac1 == xIfac2 )
382 0 : m_xConfigAccess.clear();
383 0 : }
384 :
385 : class UICategoryDescription : public UICommandDescription
386 : {
387 : public:
388 : UICategoryDescription( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
389 : virtual ~UICategoryDescription();
390 :
391 2 : virtual OUString SAL_CALL getImplementationName()
392 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
393 : {
394 2 : return OUString("com.sun.star.comp.framework.UICategoryDescription");
395 : }
396 :
397 0 : virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
398 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
399 : {
400 0 : return cppu::supportsService(this, ServiceName);
401 : }
402 :
403 1 : virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
404 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
405 : {
406 1 : css::uno::Sequence< OUString > aSeq(1);
407 1 : aSeq[0] = "com.sun.star.ui.UICategoryDescription";
408 1 : return aSeq;
409 : }
410 :
411 : private:
412 : virtual css::uno::Reference< css::container::XNameAccess > impl_createConfigAccess(const OUString& _sName) SAL_OVERRIDE;
413 : };
414 :
415 2 : UICategoryDescription::UICategoryDescription( const Reference< XComponentContext >& rxContext ) :
416 2 : UICommandDescription(rxContext,true)
417 : {
418 2 : Reference< XNameAccess > xEmpty;
419 4 : OUString aGenericCategories( "GenericCategories" );
420 2 : m_xGenericUICommands = new ConfigurationAccess_UICategory( aGenericCategories, xEmpty, rxContext );
421 :
422 : // insert generic categories mappings
423 : m_aModuleToCommandFileMap.insert( ModuleToCommandFileMap::value_type(
424 2 : OUString(GENERIC_MODULE_NAME ), aGenericCategories ));
425 :
426 2 : UICommandsHashMap::iterator pCatIter = m_aUICommandsHashMap.find( aGenericCategories );
427 2 : if ( pCatIter != m_aUICommandsHashMap.end() )
428 0 : pCatIter->second = m_xGenericUICommands;
429 :
430 4 : impl_fillElements("ooSetupFactoryCmdCategoryConfigRef");
431 2 : }
432 :
433 4 : UICategoryDescription::~UICategoryDescription()
434 : {
435 4 : }
436 0 : Reference< XNameAccess > UICategoryDescription::impl_createConfigAccess(const OUString& _sName)
437 : {
438 0 : return new ConfigurationAccess_UICategory( _sName, m_xGenericUICommands, m_xContext );
439 : }
440 :
441 2 : struct Instance {
442 2 : explicit Instance(
443 : css::uno::Reference<css::uno::XComponentContext> const & context):
444 : instance(static_cast<cppu::OWeakObject *>(
445 2 : new UICategoryDescription(context)))
446 : {
447 2 : }
448 :
449 : css::uno::Reference<css::uno::XInterface> instance;
450 : };
451 :
452 : struct Singleton:
453 : public rtl::StaticWithArg<
454 : Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
455 : {};
456 :
457 : }
458 :
459 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
460 2 : com_sun_star_comp_framework_UICategoryDescription_get_implementation(
461 : css::uno::XComponentContext *context,
462 : css::uno::Sequence<css::uno::Any> const &)
463 : {
464 : return cppu::acquire(static_cast<cppu::OWeakObject *>(
465 2 : Singleton::get(context).instance.get()));
466 : }
467 :
468 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|