1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_framework.hxx" 30 31 //_________________________________________________________________________________________________________________ 32 // my own includes 33 //_________________________________________________________________________________________________________________ 34 35 #ifndef __FRAMEWORK_UICONFIGURATION_UICATEGORYDESCRPTION_HXX_ 36 #include "uiconfiguration/uicategorydescription.hxx" 37 #endif 38 #include <threadhelp/resetableguard.hxx> 39 #include "services.h" 40 41 #include "properties.h" 42 43 //_________________________________________________________________________________________________________________ 44 // interface includes 45 //_________________________________________________________________________________________________________________ 46 #include <com/sun/star/beans/PropertyValue.hpp> 47 #include <com/sun/star/beans/XPropertySet.hpp> 48 #include <com/sun/star/container/XNameAccess.hpp> 49 #include <com/sun/star/container/XNameContainer.hpp> 50 #include <com/sun/star/container/XContainer.hpp> 51 52 //_________________________________________________________________________________________________________________ 53 // includes of other projects 54 //_________________________________________________________________________________________________________________ 55 #include <rtl/ustrbuf.hxx> 56 #include <cppuhelper/implbase2.hxx> 57 #include <unotools/configmgr.hxx> 58 #include <tools/string.hxx> 59 60 #ifndef _VCL_MNEMONIC_HXX_ 61 #include <vcl/mnemonic.hxx> 62 #endif 63 #include <comphelper/sequence.hxx> 64 #include <rtl/logfile.hxx> 65 66 //_________________________________________________________________________________________________________________ 67 // Defines 68 //_________________________________________________________________________________________________________________ 69 // 70 71 using namespace com::sun::star::uno; 72 using namespace com::sun::star::lang; 73 using namespace com::sun::star::beans; 74 using namespace com::sun::star::container; 75 using namespace ::com::sun::star::frame; 76 77 //_________________________________________________________________________________________________________________ 78 // Namespace 79 //_________________________________________________________________________________________________________________ 80 // 81 82 struct ModuleToCategory 83 { 84 const char* pModuleId; 85 const char* pCommands; 86 }; 87 88 static const char CATEGORY[] = "Category"; 89 static const char GENERIC_MODULE_NAME[] = "generic"; 90 static const char CONFIGURATION_ROOT_ACCESS[] = "/org.openoffice.Office.UI."; 91 static const char CONFIGURATION_CATEGORY_ELEMENT_ACCESS[] = "/Commands/Categories"; 92 static const char CONFIGURATION_PROPERTY_NAME[] = "Name"; 93 94 namespace framework 95 { 96 97 //***************************************************************************************************************** 98 // Configuration access class for PopupMenuControllerFactory implementation 99 //***************************************************************************************************************** 100 101 class ConfigurationAccess_UICategory : // Order is neccessary for right initialization! 102 private ThreadHelpBase , 103 public ::cppu::WeakImplHelper2<XNameAccess,XContainerListener> 104 { 105 public: 106 ConfigurationAccess_UICategory( const ::rtl::OUString& aModuleName, const Reference< XNameAccess >& xGenericUICommands, const Reference< XMultiServiceFactory >& rServiceManager ); 107 virtual ~ConfigurationAccess_UICategory(); 108 109 // XNameAccess 110 virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) 111 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); 112 113 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() 114 throw (::com::sun::star::uno::RuntimeException); 115 116 virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) 117 throw (::com::sun::star::uno::RuntimeException); 118 119 // XElementAccess 120 virtual ::com::sun::star::uno::Type SAL_CALL getElementType() 121 throw (::com::sun::star::uno::RuntimeException); 122 123 virtual sal_Bool SAL_CALL hasElements() 124 throw (::com::sun::star::uno::RuntimeException); 125 126 // container.XContainerListener 127 virtual void SAL_CALL elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException); 128 virtual void SAL_CALL elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException); 129 virtual void SAL_CALL elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException); 130 131 // lang.XEventListener 132 virtual void SAL_CALL disposing( const EventObject& aEvent ) throw(RuntimeException); 133 134 protected: 135 Any getUINameFromID( const rtl::OUString& rId ); 136 Any getUINameFromCache( const rtl::OUString& rId ); 137 Sequence< rtl::OUString > getAllIds(); 138 sal_Bool fillCache(); 139 140 private: 141 typedef ::std::hash_map< ::rtl::OUString, 142 ::rtl::OUString, 143 OUStringHashCode, 144 ::std::equal_to< ::rtl::OUString > > IdToInfoCache; 145 146 sal_Bool initializeConfigAccess(); 147 148 rtl::OUString m_aConfigCategoryAccess; 149 rtl::OUString m_aPropUIName; 150 Reference< XNameAccess > m_xGenericUICategories; 151 Reference< XMultiServiceFactory > m_xServiceManager; 152 Reference< XMultiServiceFactory > m_xConfigProvider; 153 Reference< XNameAccess > m_xConfigAccess; 154 sal_Bool m_bConfigAccessInitialized; 155 sal_Bool m_bCacheFilled; 156 IdToInfoCache m_aIdCache; 157 }; 158 159 //***************************************************************************************************************** 160 // XInterface, XTypeProvider 161 //***************************************************************************************************************** 162 163 ConfigurationAccess_UICategory::ConfigurationAccess_UICategory( const rtl::OUString& aModuleName, const Reference< XNameAccess >& rGenericUICategories, const Reference< XMultiServiceFactory >& rServiceManager ) : 164 ThreadHelpBase(), 165 m_aConfigCategoryAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )), 166 m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_PROPERTY_NAME )), 167 m_xGenericUICategories( rGenericUICategories ), 168 m_xServiceManager( rServiceManager ), 169 m_bConfigAccessInitialized( sal_False ), 170 m_bCacheFilled( sal_False ) 171 { 172 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::ConfigurationAccess_UICategory" ); 173 // Create configuration hierachical access name 174 m_aConfigCategoryAccess += aModuleName; 175 m_aConfigCategoryAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_CATEGORY_ELEMENT_ACCESS )); 176 177 m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY ); 178 } 179 180 ConfigurationAccess_UICategory::~ConfigurationAccess_UICategory() 181 { 182 // SAFE 183 ResetableGuard aLock( m_aLock ); 184 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); 185 if ( xContainer.is() ) 186 xContainer->removeContainerListener( this ); 187 } 188 189 // XNameAccess 190 Any SAL_CALL ConfigurationAccess_UICategory::getByName( const ::rtl::OUString& rId ) 191 throw ( NoSuchElementException, WrappedTargetException, RuntimeException) 192 { 193 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getByName" ); 194 ResetableGuard aLock( m_aLock ); 195 if ( !m_bConfigAccessInitialized ) 196 { 197 initializeConfigAccess(); 198 m_bConfigAccessInitialized = sal_True; 199 fillCache(); 200 } 201 202 // SAFE 203 Any a = getUINameFromID( rId ); 204 205 if ( !a.hasValue() ) 206 throw NoSuchElementException(); 207 208 return a; 209 } 210 211 Sequence< ::rtl::OUString > SAL_CALL ConfigurationAccess_UICategory::getElementNames() 212 throw ( RuntimeException ) 213 { 214 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getElementNames" ); 215 return getAllIds(); 216 } 217 218 sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasByName( const ::rtl::OUString& rId ) 219 throw (::com::sun::star::uno::RuntimeException) 220 { 221 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::hasByName" ); 222 return getByName( rId ).hasValue(); 223 } 224 225 // XElementAccess 226 Type SAL_CALL ConfigurationAccess_UICategory::getElementType() 227 throw ( RuntimeException ) 228 { 229 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getElementType" ); 230 return( ::getCppuType( (const rtl::OUString*)NULL ) ); 231 } 232 233 sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasElements() 234 throw ( RuntimeException ) 235 { 236 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::hasElements" ); 237 // There must be global categories! 238 return sal_True; 239 } 240 241 sal_Bool ConfigurationAccess_UICategory::fillCache() 242 { 243 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::fillCache" ); 244 RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ConfigurationAccess_UICategory::fillCache" ); 245 246 if ( m_bCacheFilled ) 247 return sal_True; 248 249 sal_Int32 i( 0 ); 250 rtl::OUString aUIName; 251 Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames(); 252 253 for ( i = 0; i < aNameSeq.getLength(); i++ ) 254 { 255 try 256 { 257 Reference< XNameAccess > xNameAccess(m_xConfigAccess->getByName( aNameSeq[i] ),UNO_QUERY); 258 if ( xNameAccess.is() ) 259 { 260 xNameAccess->getByName( m_aPropUIName ) >>= aUIName; 261 262 m_aIdCache.insert( IdToInfoCache::value_type( aNameSeq[i], aUIName )); 263 } 264 } 265 catch ( com::sun::star::lang::WrappedTargetException& ) 266 { 267 } 268 catch ( com::sun::star::container::NoSuchElementException& ) 269 { 270 } 271 } 272 273 m_bCacheFilled = sal_True; 274 275 return sal_True; 276 } 277 278 Any ConfigurationAccess_UICategory::getUINameFromID( const rtl::OUString& rId ) 279 { 280 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getUINameFromID" ); 281 Any a; 282 283 try 284 { 285 a = getUINameFromCache( rId ); 286 if ( !a.hasValue() ) 287 { 288 // Try to ask our global commands configuration access 289 if ( m_xGenericUICategories.is() ) 290 { 291 try 292 { 293 return m_xGenericUICategories->getByName( rId ); 294 } 295 catch ( com::sun::star::lang::WrappedTargetException& ) 296 { 297 } 298 catch ( com::sun::star::container::NoSuchElementException& ) 299 { 300 } 301 } 302 } 303 } 304 catch( com::sun::star::container::NoSuchElementException& ) 305 { 306 } 307 catch ( com::sun::star::lang::WrappedTargetException& ) 308 { 309 } 310 311 return a; 312 } 313 314 Any ConfigurationAccess_UICategory::getUINameFromCache( const rtl::OUString& rId ) 315 { 316 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getUINameFromCache" ); 317 Any a; 318 319 IdToInfoCache::const_iterator pIter = m_aIdCache.find( rId ); 320 if ( pIter != m_aIdCache.end() ) 321 a <<= pIter->second; 322 323 return a; 324 } 325 326 Sequence< rtl::OUString > ConfigurationAccess_UICategory::getAllIds() 327 { 328 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getAllIds" ); 329 // SAFE 330 ResetableGuard aLock( m_aLock ); 331 332 if ( !m_bConfigAccessInitialized ) 333 { 334 initializeConfigAccess(); 335 m_bConfigAccessInitialized = sal_True; 336 fillCache(); 337 } 338 339 if ( m_xConfigAccess.is() ) 340 { 341 Any a; 342 Reference< XNameAccess > xNameAccess; 343 344 try 345 { 346 Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames(); 347 348 if ( m_xGenericUICategories.is() ) 349 { 350 // Create concat list of supported user interface commands of the module 351 Sequence< ::rtl::OUString > aGenericNameSeq = m_xGenericUICategories->getElementNames(); 352 sal_uInt32 nCount1 = aNameSeq.getLength(); 353 sal_uInt32 nCount2 = aGenericNameSeq.getLength(); 354 355 aNameSeq.realloc( nCount1 + nCount2 ); 356 ::rtl::OUString* pNameSeq = aNameSeq.getArray(); 357 const ::rtl::OUString* pGenericSeq = aGenericNameSeq.getConstArray(); 358 for ( sal_uInt32 i = 0; i < nCount2; i++ ) 359 pNameSeq[nCount1+i] = pGenericSeq[i]; 360 } 361 362 return aNameSeq; 363 } 364 catch( com::sun::star::container::NoSuchElementException& ) 365 { 366 } 367 catch ( com::sun::star::lang::WrappedTargetException& ) 368 { 369 } 370 } 371 372 return Sequence< rtl::OUString >(); 373 } 374 375 sal_Bool ConfigurationAccess_UICategory::initializeConfigAccess() 376 { 377 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::initializeConfigAccess" ); 378 Sequence< Any > aArgs( 1 ); 379 PropertyValue aPropValue; 380 381 try 382 { 383 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )); 384 aPropValue.Value <<= m_aConfigCategoryAccess; 385 aArgs[0] <<= aPropValue; 386 387 m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ),UNO_QUERY ); 388 if ( m_xConfigAccess.is() ) 389 { 390 // Add as container listener 391 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); 392 if ( xContainer.is() ) 393 xContainer->addContainerListener( this ); 394 } 395 396 return sal_True; 397 } 398 catch ( WrappedTargetException& ) 399 { 400 } 401 catch ( Exception& ) 402 { 403 } 404 405 return sal_False; 406 } 407 408 // container.XContainerListener 409 void SAL_CALL ConfigurationAccess_UICategory::elementInserted( const ContainerEvent& ) throw(RuntimeException) 410 { 411 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementInserted" ); 412 } 413 414 void SAL_CALL ConfigurationAccess_UICategory::elementRemoved ( const ContainerEvent& ) throw(RuntimeException) 415 { 416 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementRemoved " ); 417 } 418 419 void SAL_CALL ConfigurationAccess_UICategory::elementReplaced( const ContainerEvent& ) throw(RuntimeException) 420 { 421 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementReplaced" ); 422 } 423 424 // lang.XEventListener 425 void SAL_CALL ConfigurationAccess_UICategory::disposing( const EventObject& aEvent ) throw(RuntimeException) 426 { 427 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::disposing" ); 428 // SAFE 429 // remove our reference to the config access 430 ResetableGuard aLock( m_aLock ); 431 432 Reference< XInterface > xIfac1( aEvent.Source, UNO_QUERY ); 433 Reference< XInterface > xIfac2( m_xConfigAccess, UNO_QUERY ); 434 if ( xIfac1 == xIfac2 ) 435 m_xConfigAccess.clear(); 436 } 437 438 //***************************************************************************************************************** 439 // XInterface, XTypeProvider, XServiceInfo 440 //***************************************************************************************************************** 441 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( UICategoryDescription , 442 ::cppu::OWeakObject , 443 SERVICENAME_UICATEGORYDESCRIPTION , 444 IMPLEMENTATIONNAME_UICATEGORYDESCRIPTION 445 ) 446 447 DEFINE_INIT_SERVICE ( UICategoryDescription, {} ) 448 449 UICategoryDescription::UICategoryDescription( const Reference< XMultiServiceFactory >& xServiceManager ) : 450 UICommandDescription(xServiceManager,true) 451 { 452 Reference< XNameAccess > xEmpty; 453 rtl::OUString aGenericCategories( RTL_CONSTASCII_USTRINGPARAM( "GenericCategories" )); 454 m_xGenericUICommands = new ConfigurationAccess_UICategory( aGenericCategories, xEmpty, xServiceManager ); 455 456 // insert generic categories mappings 457 m_aModuleToCommandFileMap.insert( ModuleToCommandFileMap::value_type( 458 rtl::OUString::createFromAscii( GENERIC_MODULE_NAME ), aGenericCategories )); 459 460 UICommandsHashMap::iterator pCatIter = m_aUICommandsHashMap.find( aGenericCategories ); 461 if ( pCatIter != m_aUICommandsHashMap.end() ) 462 pCatIter->second = m_xGenericUICommands; 463 464 impl_fillElements("ooSetupFactoryCmdCategoryConfigRef"); 465 } 466 467 UICategoryDescription::~UICategoryDescription() 468 { 469 } 470 Reference< XNameAccess > UICategoryDescription::impl_createConfigAccess(const ::rtl::OUString& _sName) 471 { 472 return new ConfigurationAccess_UICategory( _sName,m_xGenericUICommands,m_xServiceManager ); 473 } 474 475 } // namespace framework 476 477