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