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