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 #include <uiconfiguration/moduleuiconfigurationmanager.hxx> 31 #include <threadhelp/resetableguard.hxx> 32 #include <services.h> 33 #include <uielement/constitemcontainer.hxx> 34 #include <uielement/rootitemcontainer.hxx> 35 #include <uielement/uielementtypenames.hxx> 36 #include <framework/menuconfiguration.hxx> 37 #include <framework/toolboxconfiguration.hxx> 38 39 #ifndef __FRAMEWORK_XML_STATUSBARCONFIGURATION_HXX_ 40 #include <framework/statusbarconfiguration.hxx> 41 #endif 42 43 //_________________________________________________________________________________________________________________ 44 // interface includes 45 //_________________________________________________________________________________________________________________ 46 #include <com/sun/star/ui/UIElementType.hpp> 47 #include <com/sun/star/ui/ConfigurationEvent.hpp> 48 #include <com/sun/star/lang/DisposedException.hpp> 49 #include <com/sun/star/beans/XPropertySet.hpp> 50 #include <com/sun/star/embed/ElementModes.hpp> 51 #include <com/sun/star/container/XNameAccess.hpp> 52 #include <com/sun/star/io/XStream.hpp> 53 54 //_________________________________________________________________________________________________________________ 55 // other includes 56 //_________________________________________________________________________________________________________________ 57 58 #include <vcl/svapp.hxx> 59 #include <rtl/ustrbuf.hxx> 60 #include <comphelper/sequenceashashmap.hxx> 61 62 //_________________________________________________________________________________________________________________ 63 // namespaces 64 //_________________________________________________________________________________________________________________ 65 66 using rtl::OUString; 67 using namespace com::sun::star::uno; 68 using namespace com::sun::star::io; 69 using namespace com::sun::star::embed; 70 using namespace com::sun::star::lang; 71 using namespace com::sun::star::container; 72 using namespace com::sun::star::beans; 73 using namespace ::com::sun::star::ui; 74 75 namespace framework 76 { 77 78 //***************************************************************************************************************** 79 // XInterface, XTypeProvider, XServiceInfo 80 //***************************************************************************************************************** 81 DEFINE_XINTERFACE_8 ( ModuleUIConfigurationManager , 82 OWeakObject , 83 DIRECT_INTERFACE( css::lang::XTypeProvider ), 84 DIRECT_INTERFACE( css::lang::XServiceInfo ), 85 DIRECT_INTERFACE( css::lang::XComponent ), 86 DIRECT_INTERFACE( css::lang::XInitialization ), 87 DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfiguration ), 88 DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationManager ), 89 DIRECT_INTERFACE( ::com::sun::star::ui::XModuleUIConfigurationManager ), 90 DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationPersistence ) 91 ) 92 93 DEFINE_XTYPEPROVIDER_8 ( ModuleUIConfigurationManager , 94 css::lang::XTypeProvider , 95 css::lang::XServiceInfo , 96 css::lang::XComponent , 97 css::lang::XInitialization , 98 ::com::sun::star::ui::XUIConfiguration , 99 ::com::sun::star::ui::XUIConfigurationManager , 100 ::com::sun::star::ui::XModuleUIConfigurationManager , 101 ::com::sun::star::ui::XUIConfigurationPersistence 102 ) 103 104 DEFINE_XSERVICEINFO_MULTISERVICE ( ModuleUIConfigurationManager , 105 ::cppu::OWeakObject , 106 SERVICENAME_MODULEUICONFIGURATIONMANAGER , 107 IMPLEMENTATIONNAME_MODULEUICONFIGURATIONMANAGER 108 ) 109 110 DEFINE_INIT_SERVICE ( ModuleUIConfigurationManager, {} ) 111 112 113 // important: The order and position of the elements must match the constant 114 // definition of "::com::sun::star::ui::UIElementType" 115 static const char* UIELEMENTTYPENAMES[] = 116 { 117 "", // Dummy value for unknown! 118 UIELEMENTTYPE_MENUBAR_NAME, 119 UIELEMENTTYPE_POPUPMENU_NAME, 120 UIELEMENTTYPE_TOOLBAR_NAME, 121 UIELEMENTTYPE_STATUSBAR_NAME, 122 UIELEMENTTYPE_FLOATINGWINDOW_NAME, 123 UIELEMENTTYPE_PROGRESSBAR_NAME, 124 UIELEMENTTYPE_TOOLPANEL_NAME 125 }; 126 127 static const char RESOURCEURL_PREFIX[] = "private:resource/"; 128 static const sal_Int32 RESOURCEURL_PREFIX_SIZE = 17; 129 static const char RESOURCEURL_CUSTOM_ELEMENT[] = "custom_"; 130 131 static sal_Int16 RetrieveTypeFromResourceURL( const rtl::OUString& aResourceURL ) 132 { 133 134 if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && 135 ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) 136 { 137 OUString aTmpStr = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE ); 138 sal_Int32 nIndex = aTmpStr.indexOf( '/' ); 139 if (( nIndex > 0 ) && ( aTmpStr.getLength() > nIndex )) 140 { 141 OUString aTypeStr( aTmpStr.copy( 0, nIndex )); 142 for ( int i = 0; i < UIElementType::COUNT; i++ ) 143 { 144 if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] )) 145 return sal_Int16( i ); 146 } 147 } 148 } 149 150 return UIElementType::UNKNOWN; 151 } 152 153 static OUString RetrieveNameFromResourceURL( const rtl::OUString& aResourceURL ) 154 { 155 if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && 156 ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) 157 { 158 sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' ); 159 if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength())) 160 return aResourceURL.copy( nIndex+1 ); 161 } 162 163 return OUString(); 164 } 165 166 void ModuleUIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType ) 167 { 168 // preload list of element types on demand 169 impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType ); 170 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); 171 172 UIElementDataHashMap& rUserElements = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap; 173 UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin(); 174 175 OUString aCustomUrlPrefix( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_CUSTOM_ELEMENT )); 176 while ( pUserIter != rUserElements.end() ) 177 { 178 sal_Int32 nIndex = pUserIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE ); 179 if ( nIndex > RESOURCEURL_PREFIX_SIZE ) 180 { 181 // Performance: Retrieve user interface name only for custom user interface elements. 182 // It's only used by them! 183 UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType ); 184 if ( pDataSettings ) 185 { 186 // Retrieve user interface name from XPropertySet interface 187 rtl::OUString aUIName; 188 Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY ); 189 if ( xPropSet.is() ) 190 { 191 Any a = xPropSet->getPropertyValue( m_aPropUIName ); 192 a >>= aUIName; 193 } 194 195 UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName ); 196 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo )); 197 } 198 } 199 else 200 { 201 // The user interface name for standard user interface elements is stored in the WindowState.xcu file 202 UIElementInfo aInfo( pUserIter->second.aResourceURL, OUString() ); 203 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo )); 204 } 205 ++pUserIter; 206 } 207 208 UIElementDataHashMap& rDefaultElements = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; 209 UIElementDataHashMap::const_iterator pDefIter = rDefaultElements.begin(); 210 211 while ( pDefIter != rDefaultElements.end() ) 212 { 213 UIElementInfoHashMap::const_iterator pIterInfo = aUIElementInfoCollection.find( pDefIter->second.aResourceURL ); 214 if ( pIterInfo == aUIElementInfoCollection.end() ) 215 { 216 sal_Int32 nIndex = pDefIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE ); 217 if ( nIndex > RESOURCEURL_PREFIX_SIZE ) 218 { 219 // Performance: Retrieve user interface name only for custom user interface elements. 220 // It's only used by them! 221 UIElementData* pDataSettings = impl_findUIElementData( pDefIter->second.aResourceURL, nElementType ); 222 if ( pDataSettings ) 223 { 224 // Retrieve user interface name from XPropertySet interface 225 rtl::OUString aUIName; 226 Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY ); 227 if ( xPropSet.is() ) 228 { 229 Any a = xPropSet->getPropertyValue( m_aPropUIName ); 230 a >>= aUIName; 231 } 232 233 UIElementInfo aInfo( pDefIter->second.aResourceURL, aUIName ); 234 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo )); 235 } 236 } 237 else 238 { 239 // The user interface name for standard user interface elements is stored in the WindowState.xcu file 240 UIElementInfo aInfo( pDefIter->second.aResourceURL, OUString() ); 241 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo )); 242 } 243 } 244 245 ++pDefIter; 246 } 247 } 248 249 void ModuleUIConfigurationManager::impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType ) 250 { 251 UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType]; 252 253 if ( !rElementTypeData.bLoaded ) 254 { 255 Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; 256 if ( xElementTypeStorage.is() ) 257 { 258 rtl::OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE ); 259 aBuf.appendAscii( RESOURCEURL_PREFIX ); 260 aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] ); 261 aBuf.appendAscii( "/" ); 262 OUString aResURLPrefix( aBuf.makeStringAndClear() ); 263 264 UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap; 265 Reference< XNameAccess > xNameAccess( xElementTypeStorage, UNO_QUERY ); 266 Sequence< OUString > aUIElementNames = xNameAccess->getElementNames(); 267 for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ ) 268 { 269 UIElementData aUIElementData; 270 271 // Resource name must be without ".xml" 272 sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' ); 273 if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() )) 274 { 275 OUString aExtension( aUIElementNames[n].copy( nIndex+1 )); 276 OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex )); 277 278 if (( aUIElementName.getLength() > 0 ) && 279 ( aExtension.equalsIgnoreAsciiCaseAsciiL( "xml", 3 ))) 280 { 281 aUIElementData.aResourceURL = aResURLPrefix + aUIElementName; 282 aUIElementData.aName = aUIElementNames[n]; 283 284 if ( eLayer == LAYER_USERDEFINED ) 285 { 286 aUIElementData.bModified = false; 287 aUIElementData.bDefault = false; 288 aUIElementData.bDefaultNode = false; 289 } 290 291 // Create hash_map entries for all user interface elements inside the storage. We don't load the 292 // settings to speed up the process. 293 rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData )); 294 } 295 } 296 rElementTypeData.bLoaded = true; 297 } 298 } 299 } 300 301 //rElementTypeData.bLoaded = true; 302 } 303 304 void ModuleUIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData ) 305 { 306 UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType]; 307 308 Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; 309 if ( xElementTypeStorage.is() && aUIElementData.aName.getLength() ) 310 { 311 try 312 { 313 Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ ); 314 Reference< XInputStream > xInputStream = xStream->getInputStream(); 315 316 if ( xInputStream.is() ) 317 { 318 switch ( nElementType ) 319 { 320 case ::com::sun::star::ui::UIElementType::UNKNOWN: 321 break; 322 323 case ::com::sun::star::ui::UIElementType::MENUBAR: 324 { 325 try 326 { 327 MenuConfiguration aMenuCfg( m_xServiceManager ); 328 Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream )); 329 RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer ); 330 if ( pRootItemContainer ) 331 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); 332 else 333 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, sal_True ) ), UNO_QUERY ); 334 return; 335 } 336 catch ( ::com::sun::star::lang::WrappedTargetException& ) 337 { 338 } 339 } 340 break; 341 342 case ::com::sun::star::ui::UIElementType::POPUPMENU: 343 { 344 break; 345 } 346 347 case ::com::sun::star::ui::UIElementType::TOOLBAR: 348 { 349 try 350 { 351 Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); 352 ToolBoxConfiguration::LoadToolBox( m_xServiceManager, xInputStream, xIndexContainer ); 353 RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); 354 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); 355 return; 356 } 357 catch ( ::com::sun::star::lang::WrappedTargetException& ) 358 { 359 } 360 361 break; 362 } 363 364 case ::com::sun::star::ui::UIElementType::STATUSBAR: 365 { 366 try 367 { 368 Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); 369 StatusBarConfiguration::LoadStatusBar( m_xServiceManager, xInputStream, xIndexContainer ); 370 RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); 371 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); 372 return; 373 } 374 catch ( ::com::sun::star::lang::WrappedTargetException& ) 375 { 376 } 377 378 break; 379 } 380 381 case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW: 382 { 383 break; 384 } 385 } 386 } 387 } 388 catch ( ::com::sun::star::embed::InvalidStorageException& ) 389 { 390 } 391 catch ( ::com::sun::star::lang::IllegalArgumentException& ) 392 { 393 } 394 catch ( ::com::sun::star::io::IOException& ) 395 { 396 } 397 catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) 398 { 399 } 400 } 401 402 // At least we provide an empty settings container! 403 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer() ), UNO_QUERY ); 404 } 405 406 ModuleUIConfigurationManager::UIElementData* ModuleUIConfigurationManager::impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad ) 407 { 408 // preload list of element types on demand 409 impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType ); 410 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); 411 412 // first try to look into our user-defined vector/hash_map combination 413 UIElementDataHashMap& rUserHashMap = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap; 414 UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL ); 415 if ( pIter != rUserHashMap.end() ) 416 { 417 // Default data settings data must be retrieved from the default layer! 418 if ( !pIter->second.bDefault ) 419 { 420 if ( !pIter->second.xSettings.is() && bLoad ) 421 impl_requestUIElementData( nElementType, LAYER_USERDEFINED, pIter->second ); 422 return &(pIter->second); 423 } 424 } 425 426 // Not successfull, we have to look into our default vector/hash_map combination 427 UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; 428 pIter = rDefaultHashMap.find( aResourceURL ); 429 if ( pIter != rDefaultHashMap.end() ) 430 { 431 if ( !pIter->second.xSettings.is() && bLoad ) 432 impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second ); 433 return &(pIter->second); 434 } 435 436 // Nothing has been found! 437 return NULL; 438 } 439 440 void ModuleUIConfigurationManager::impl_storeElementTypeData( Reference< XStorage > xStorage, UIElementType& rElementType, bool bResetModifyState ) 441 { 442 UIElementDataHashMap& rHashMap = rElementType.aElementsHashMap; 443 UIElementDataHashMap::iterator pIter = rHashMap.begin(); 444 445 while ( pIter != rHashMap.end() ) 446 { 447 UIElementData& rElement = pIter->second; 448 if ( rElement.bModified ) 449 { 450 if ( rElement.bDefault ) 451 { 452 xStorage->removeElement( rElement.aName ); 453 rElement.bModified = sal_False; // mark as not modified 454 } 455 else 456 { 457 Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY ); 458 Reference< XOutputStream > xOutputStream( xStream->getOutputStream() ); 459 460 if ( xOutputStream.is() ) 461 { 462 switch( rElementType.nElementType ) 463 { 464 case ::com::sun::star::ui::UIElementType::MENUBAR: 465 { 466 try 467 { 468 MenuConfiguration aMenuCfg( m_xServiceManager ); 469 aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream ); 470 } 471 catch ( ::com::sun::star::lang::WrappedTargetException& ) 472 { 473 } 474 } 475 break; 476 477 case ::com::sun::star::ui::UIElementType::TOOLBAR: 478 { 479 try 480 { 481 ToolBoxConfiguration::StoreToolBox( m_xServiceManager, xOutputStream, rElement.xSettings ); 482 } 483 catch ( ::com::sun::star::lang::WrappedTargetException& ) 484 { 485 } 486 } 487 break; 488 489 case ::com::sun::star::ui::UIElementType::STATUSBAR: 490 { 491 try 492 { 493 StatusBarConfiguration::StoreStatusBar( m_xServiceManager, xOutputStream, rElement.xSettings ); 494 } 495 catch ( ::com::sun::star::lang::WrappedTargetException& ) 496 { 497 } 498 } 499 break; 500 501 default: 502 break; 503 } 504 } 505 506 // mark as not modified if we store to our own storage 507 if ( bResetModifyState ) 508 rElement.bModified = sal_False; 509 } 510 } 511 512 ++pIter; 513 } 514 515 // commit element type storage 516 Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY ); 517 if ( xTransactedObject.is() ) 518 xTransactedObject->commit(); 519 520 // mark UIElementType as not modified if we store to our own storage 521 if ( bResetModifyState ) 522 rElementType.bModified = sal_False; 523 } 524 525 // This is only allowed to be called on the LAYER_USER_DEFINED! 526 void ModuleUIConfigurationManager::impl_resetElementTypeData( 527 UIElementType& rUserElementType, 528 UIElementType& rDefaultElementType, 529 ConfigEventNotifyContainer& rRemoveNotifyContainer, 530 ConfigEventNotifyContainer& rReplaceNotifyContainer ) 531 { 532 UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap; 533 UIElementDataHashMap::iterator pIter = rHashMap.begin(); 534 535 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 536 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 537 Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY ); 538 sal_Int16 nType = rUserElementType.nElementType; 539 540 // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling 541 // our listeners! 542 while ( pIter != rHashMap.end() ) 543 { 544 UIElementData& rElement = pIter->second; 545 if ( !rElement.bDefault ) 546 { 547 if ( xDefaultNameAccess->hasByName( rElement.aName )) 548 { 549 // Replace settings with data from default layer 550 Reference< XIndexAccess > xOldSettings( rElement.xSettings ); 551 impl_requestUIElementData( nType, LAYER_DEFAULT, rElement ); 552 553 ConfigurationEvent aReplaceEvent; 554 aReplaceEvent.ResourceURL = rElement.aResourceURL; 555 aReplaceEvent.Accessor <<= xThis; 556 aReplaceEvent.Source = xIfac; 557 aReplaceEvent.ReplacedElement <<= xOldSettings; 558 aReplaceEvent.Element <<= rElement.xSettings; 559 560 rReplaceNotifyContainer.push_back( aReplaceEvent ); 561 562 // Mark element as default and not modified. That means "not active" 563 // in the user layer anymore. 564 rElement.bModified = false; 565 rElement.bDefault = true; 566 } 567 else 568 { 569 // Remove user-defined settings from user layer 570 ConfigurationEvent aEvent; 571 aEvent.ResourceURL = rElement.aResourceURL; 572 aEvent.Accessor <<= xThis; 573 aEvent.Source = xIfac; 574 aEvent.Element <<= rElement.xSettings; 575 576 rRemoveNotifyContainer.push_back( aEvent ); 577 578 // Mark element as default and not modified. That means "not active" 579 // in the user layer anymore. 580 rElement.bModified = false; 581 rElement.bDefault = true; 582 } 583 } 584 585 ++pIter; 586 } 587 588 // Remove all settings from our user interface elements 589 rHashMap.clear(); 590 } 591 592 void ModuleUIConfigurationManager::impl_reloadElementTypeData( 593 UIElementType& rUserElementType, 594 UIElementType& rDefaultElementType, 595 ConfigEventNotifyContainer& rRemoveNotifyContainer, 596 ConfigEventNotifyContainer& rReplaceNotifyContainer ) 597 { 598 UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap; 599 UIElementDataHashMap::iterator pIter = rHashMap.begin(); 600 Reference< XStorage > xUserStorage( rUserElementType.xStorage ); 601 Reference< XStorage > xDefaultStorage( rDefaultElementType.xStorage ); 602 Reference< XNameAccess > xUserNameAccess( rUserElementType.xStorage, UNO_QUERY ); 603 Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY ); 604 605 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 606 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 607 sal_Int16 nType = rUserElementType.nElementType; 608 609 while ( pIter != rHashMap.end() ) 610 { 611 UIElementData& rElement = pIter->second; 612 if ( rElement.bModified ) 613 { 614 if ( xUserNameAccess->hasByName( rElement.aName )) 615 { 616 // Replace settings with data from user layer 617 Reference< XIndexAccess > xOldSettings( rElement.xSettings ); 618 619 impl_requestUIElementData( nType, LAYER_USERDEFINED, rElement ); 620 621 ConfigurationEvent aReplaceEvent; 622 623 aReplaceEvent.ResourceURL = rElement.aResourceURL; 624 aReplaceEvent.Accessor <<= xThis; 625 aReplaceEvent.Source = xIfac; 626 aReplaceEvent.ReplacedElement <<= xOldSettings; 627 aReplaceEvent.Element <<= rElement.xSettings; 628 rReplaceNotifyContainer.push_back( aReplaceEvent ); 629 630 rElement.bModified = false; 631 } 632 else if ( xDefaultNameAccess->hasByName( rElement.aName )) 633 { 634 // Replace settings with data from default layer 635 Reference< XIndexAccess > xOldSettings( rElement.xSettings ); 636 637 impl_requestUIElementData( nType, LAYER_DEFAULT, rElement ); 638 639 ConfigurationEvent aReplaceEvent; 640 641 aReplaceEvent.ResourceURL = rElement.aResourceURL; 642 aReplaceEvent.Accessor <<= xThis; 643 aReplaceEvent.Source = xIfac; 644 aReplaceEvent.ReplacedElement <<= xOldSettings; 645 aReplaceEvent.Element <<= rElement.xSettings; 646 rReplaceNotifyContainer.push_back( aReplaceEvent ); 647 648 // Mark element as default and not modified. That means "not active" 649 // in the user layer anymore. 650 rElement.bModified = false; 651 rElement.bDefault = true; 652 } 653 else 654 { 655 // Element settings are not in any storage => remove 656 ConfigurationEvent aRemoveEvent; 657 658 aRemoveEvent.ResourceURL = rElement.aResourceURL; 659 aRemoveEvent.Accessor <<= xThis; 660 aRemoveEvent.Source = xIfac; 661 aRemoveEvent.Element <<= rElement.xSettings; 662 663 rRemoveNotifyContainer.push_back( aRemoveEvent ); 664 665 // Mark element as default and not modified. That means "not active" 666 // in the user layer anymore. 667 rElement.bModified = false; 668 rElement.bDefault = true; 669 } 670 } 671 ++pIter; 672 } 673 674 rUserElementType.bModified = sal_False; 675 } 676 677 void ModuleUIConfigurationManager::impl_Initialize() 678 { 679 // Initialize the top-level structures with the storage data 680 if ( m_xUserConfigStorage.is() ) 681 { 682 // Try to access our module sub folder 683 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; 684 i++ ) 685 { 686 Reference< XStorage > xElementTypeStorage; 687 try 688 { 689 if ( m_pStorageHandler[i] ) 690 xElementTypeStorage = m_pStorageHandler[i]->getWorkingStorageUser(); 691 } 692 catch ( com::sun::star::container::NoSuchElementException& ) 693 { 694 } 695 catch ( ::com::sun::star::embed::InvalidStorageException& ) 696 { 697 } 698 catch ( ::com::sun::star::lang::IllegalArgumentException& ) 699 { 700 } 701 catch ( ::com::sun::star::io::IOException& ) 702 { 703 } 704 catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) 705 { 706 } 707 708 m_aUIElements[LAYER_USERDEFINED][i].nElementType = i; 709 m_aUIElements[LAYER_USERDEFINED][i].bModified = false; 710 m_aUIElements[LAYER_USERDEFINED][i].xStorage = xElementTypeStorage; 711 m_aUIElements[LAYER_USERDEFINED][i].bDefaultLayer = false; 712 } 713 } 714 715 if ( m_xDefaultConfigStorage.is() ) 716 { 717 Reference< XNameAccess > xNameAccess( m_xDefaultConfigStorage, UNO_QUERY_THROW ); 718 719 // Try to access our module sub folder 720 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; 721 i++ ) 722 { 723 Reference< XStorage > xElementTypeStorage; 724 try 725 { 726 const OUString sName( OUString::createFromAscii( UIELEMENTTYPENAMES[i] ) ); 727 if( xNameAccess->hasByName( sName ) ) 728 xNameAccess->getByName( sName ) >>= xElementTypeStorage; 729 } 730 catch ( com::sun::star::container::NoSuchElementException& ) 731 { 732 } 733 734 m_aUIElements[LAYER_DEFAULT][i].nElementType = i; 735 m_aUIElements[LAYER_DEFAULT][i].bModified = false; 736 m_aUIElements[LAYER_DEFAULT][i].xStorage = xElementTypeStorage; 737 m_aUIElements[LAYER_DEFAULT][i].bDefaultLayer = true; 738 } 739 } 740 } 741 742 ModuleUIConfigurationManager::ModuleUIConfigurationManager( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xServiceManager ) : 743 ThreadHelpBase( &Application::GetSolarMutex() ) 744 , m_xDefaultConfigStorage( 0 ) 745 , m_xUserConfigStorage( 0 ) 746 , m_bReadOnly( true ) 747 , m_bInitialized( false ) 748 , m_bModified( false ) 749 , m_bConfigRead( false ) 750 , m_bDisposed( false ) 751 , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" )) 752 , m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" )) 753 , m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )) 754 , m_xServiceManager( xServiceManager ) 755 , m_aListenerContainer( m_aLock.getShareableOslMutex() ) 756 { 757 for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 758 m_pStorageHandler[i] = 0; 759 760 // Make sure we have a default initialized entry for every layer and user interface element type! 761 // The following code depends on this! 762 m_aUIElements[LAYER_DEFAULT].resize( ::com::sun::star::ui::UIElementType::COUNT ); 763 m_aUIElements[LAYER_USERDEFINED].resize( ::com::sun::star::ui::UIElementType::COUNT ); 764 } 765 766 ModuleUIConfigurationManager::~ModuleUIConfigurationManager() 767 { 768 for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 769 delete m_pStorageHandler[i]; 770 } 771 772 // XComponent 773 void SAL_CALL ModuleUIConfigurationManager::dispose() throw (::com::sun::star::uno::RuntimeException) 774 { 775 Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); 776 777 css::lang::EventObject aEvent( xThis ); 778 m_aListenerContainer.disposeAndClear( aEvent ); 779 780 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 781 ResetableGuard aGuard( m_aLock ); 782 Reference< XComponent > xModuleImageManager( m_xModuleImageManager ); 783 m_xModuleImageManager.clear(); 784 m_xModuleAcceleratorManager.clear(); 785 m_aUIElements[LAYER_USERDEFINED].clear(); 786 m_aUIElements[LAYER_DEFAULT].clear(); 787 m_xDefaultConfigStorage.clear(); 788 m_xUserConfigStorage.clear(); 789 m_xUserRootCommit.clear(); 790 m_bConfigRead = false; 791 m_bModified = false; 792 m_bDisposed = true; 793 aGuard.unlock(); 794 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 795 796 try 797 { 798 if ( xModuleImageManager.is() ) 799 xModuleImageManager->dispose(); 800 } 801 catch ( Exception& ) 802 { 803 } 804 } 805 806 void SAL_CALL ModuleUIConfigurationManager::addEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) 807 { 808 { 809 ResetableGuard aGuard( m_aLock ); 810 811 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 812 if ( m_bDisposed ) 813 throw DisposedException(); 814 } 815 816 m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); 817 } 818 819 void SAL_CALL ModuleUIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) 820 { 821 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 822 m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); 823 } 824 825 // XInitialization 826 void SAL_CALL ModuleUIConfigurationManager::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) 827 { 828 ResetableGuard aLock( m_aLock ); 829 830 if ( !m_bInitialized ) 831 { 832 ::comphelper::SequenceAsHashMap lArgs(aArguments); 833 m_aModuleIdentifier = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleIdentifier"), ::rtl::OUString()); 834 m_aModuleShortName = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleShortName"), ::rtl::OUString()); 835 836 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 837 { 838 rtl::OUString aResourceType; 839 if ( i == ::com::sun::star::ui::UIElementType::MENUBAR ) 840 aResourceType = PresetHandler::RESOURCETYPE_MENUBAR(); 841 else if ( i == ::com::sun::star::ui::UIElementType::TOOLBAR ) 842 aResourceType = PresetHandler::RESOURCETYPE_TOOLBAR(); 843 else if ( i == ::com::sun::star::ui::UIElementType::STATUSBAR ) 844 aResourceType = PresetHandler::RESOURCETYPE_STATUSBAR(); 845 846 if ( aResourceType.getLength() > 0 ) 847 { 848 m_pStorageHandler[i] = new PresetHandler( m_xServiceManager ); 849 m_pStorageHandler[i]->connectToResource( PresetHandler::E_MODULES, 850 aResourceType, // this path wont be used later ... seee next lines! 851 m_aModuleShortName, 852 css::uno::Reference< css::embed::XStorage >()); // no document root used here! 853 } 854 } 855 856 // initialize root storages for all resource types 857 m_xUserRootCommit = css::uno::Reference< css::embed::XTransactedObject >( 858 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY); // can be empty 859 m_xDefaultConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageShare( 860 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageShare()); 861 m_xUserConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageUser( 862 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageUser()); 863 864 if ( m_xUserConfigStorage.is() ) 865 { 866 Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY ); 867 if ( xPropSet.is() ) 868 { 869 long nOpenMode = 0; 870 Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ))); 871 if ( a >>= nOpenMode ) 872 m_bReadOnly = !( nOpenMode & ElementModes::WRITE ); 873 } 874 } 875 876 impl_Initialize(); 877 878 m_bInitialized = true; 879 } 880 } 881 882 // XUIConfiguration 883 void SAL_CALL ModuleUIConfigurationManager::addConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) 884 { 885 { 886 ResetableGuard aGuard( m_aLock ); 887 888 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 889 if ( m_bDisposed ) 890 throw DisposedException(); 891 } 892 893 m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener ); 894 } 895 896 void SAL_CALL ModuleUIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) 897 { 898 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 899 m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener ); 900 } 901 902 903 // XUIConfigurationManager 904 void SAL_CALL ModuleUIConfigurationManager::reset() throw (::com::sun::star::uno::RuntimeException) 905 { 906 ResetableGuard aGuard( m_aLock ); 907 908 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 909 if ( m_bDisposed ) 910 throw DisposedException(); 911 912 bool bResetStorage( false ); 913 914 if ( !isReadOnly() ) 915 { 916 // Remove all elements from our user-defined storage! 917 try 918 { 919 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 920 { 921 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; 922 Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY ); 923 924 if ( xSubStorage.is() ) 925 { 926 bool bCommitSubStorage( false ); 927 Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY ); 928 Sequence< OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames(); 929 for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ ) 930 { 931 xSubStorage->removeElement( aUIElementStreamNames[j] ); 932 bCommitSubStorage = true; 933 } 934 935 if ( bCommitSubStorage ) 936 { 937 Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY ); 938 if ( xTransactedObject.is() ) 939 xTransactedObject->commit(); 940 m_pStorageHandler[i]->commitUserChanges(); 941 } 942 } 943 } 944 945 bResetStorage = true; 946 947 // remove settings from user defined layer and notify listener about removed settings data! 948 ConfigEventNotifyContainer aRemoveEventNotifyContainer; 949 ConfigEventNotifyContainer aReplaceEventNotifyContainer; 950 for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ ) 951 { 952 try 953 { 954 UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][j]; 955 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][j]; 956 957 impl_resetElementTypeData( rUserElementType, rDefaultElementType, aRemoveEventNotifyContainer, aReplaceEventNotifyContainer ); 958 rUserElementType.bModified = sal_False; 959 } 960 catch ( Exception& ) 961 { 962 throw IOException(); 963 } 964 } 965 966 m_bModified = sal_False; 967 968 // Unlock mutex before notify our listeners 969 aGuard.unlock(); 970 971 // Notify our listeners 972 sal_uInt32 k = 0; 973 for ( k = 0; k < aRemoveEventNotifyContainer.size(); k++ ) 974 implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove ); 975 for ( k = 0; k < aReplaceEventNotifyContainer.size(); k++ ) 976 implts_notifyContainerListener( aReplaceEventNotifyContainer[k], NotifyOp_Replace ); 977 } 978 catch ( ::com::sun::star::lang::IllegalArgumentException& ) 979 { 980 } 981 catch ( ::com::sun::star::container::NoSuchElementException& ) 982 { 983 } 984 catch ( ::com::sun::star::embed::InvalidStorageException& ) 985 { 986 } 987 catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) 988 { 989 } 990 } 991 } 992 993 Sequence< Sequence< PropertyValue > > SAL_CALL ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType ) 994 throw ( IllegalArgumentException, RuntimeException ) 995 { 996 if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 997 throw IllegalArgumentException(); 998 999 ResetableGuard aGuard( m_aLock ); 1000 if ( m_bDisposed ) 1001 throw DisposedException(); 1002 1003 Sequence< Sequence< PropertyValue > > aElementInfoSeq; 1004 UIElementInfoHashMap aUIElementInfoCollection; 1005 1006 if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) 1007 { 1008 for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1009 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) ); 1010 } 1011 else 1012 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType ); 1013 1014 Sequence< PropertyValue > aUIElementInfo( 2 ); 1015 aUIElementInfo[0].Name = m_aPropResourceURL; 1016 aUIElementInfo[1].Name = m_aPropUIName; 1017 1018 aElementInfoSeq.realloc( aUIElementInfoCollection.size() ); 1019 UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin(); 1020 1021 sal_Int32 n = 0; 1022 while ( pIter != aUIElementInfoCollection.end() ) 1023 { 1024 aUIElementInfo[0].Value <<= pIter->second.aResourceURL; 1025 aUIElementInfo[1].Value <<= pIter->second.aUIName; 1026 aElementInfoSeq[n++] = aUIElementInfo; 1027 ++pIter; 1028 } 1029 1030 return aElementInfoSeq; 1031 } 1032 1033 Reference< XIndexContainer > SAL_CALL ModuleUIConfigurationManager::createSettings() throw (::com::sun::star::uno::RuntimeException) 1034 { 1035 ResetableGuard aGuard( m_aLock ); 1036 1037 if ( m_bDisposed ) 1038 throw DisposedException(); 1039 1040 // Creates an empty item container which can be filled from outside 1041 return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); 1042 } 1043 1044 sal_Bool SAL_CALL ModuleUIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL ) 1045 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 1046 { 1047 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1048 1049 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1050 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1051 throw IllegalArgumentException(); 1052 else 1053 { 1054 ResetableGuard aGuard( m_aLock ); 1055 1056 if ( m_bDisposed ) 1057 throw DisposedException(); 1058 1059 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); 1060 if ( pDataSettings ) 1061 return sal_True; 1062 } 1063 1064 return sal_False; 1065 } 1066 1067 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable ) 1068 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 1069 { 1070 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1071 1072 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1073 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1074 throw IllegalArgumentException(); 1075 else 1076 { 1077 ResetableGuard aGuard( m_aLock ); 1078 1079 if ( m_bDisposed ) 1080 throw DisposedException(); 1081 1082 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); 1083 if ( pDataSettings ) 1084 { 1085 // Create a copy of our data if someone wants to change the data. 1086 if ( bWriteable ) 1087 return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY ); 1088 else 1089 return pDataSettings->xSettings; 1090 } 1091 } 1092 1093 throw NoSuchElementException(); 1094 } 1095 1096 void SAL_CALL ModuleUIConfigurationManager::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData ) 1097 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) 1098 { 1099 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1100 1101 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1102 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1103 throw IllegalArgumentException(); 1104 else if ( m_bReadOnly ) 1105 throw IllegalAccessException(); 1106 else 1107 { 1108 ResetableGuard aGuard( m_aLock ); 1109 1110 if ( m_bDisposed ) 1111 throw DisposedException(); 1112 1113 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); 1114 if ( pDataSettings ) 1115 { 1116 if ( !pDataSettings->bDefaultNode ) 1117 { 1118 // we have a settings entry in our user-defined layer - replace 1119 Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings; 1120 1121 // Create a copy of the data if the container is not const 1122 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); 1123 if ( xReplace.is() ) 1124 pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); 1125 else 1126 pDataSettings->xSettings = aNewData; 1127 pDataSettings->bDefault = false; 1128 pDataSettings->bModified = true; 1129 m_bModified = true; 1130 1131 // Modify type container 1132 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1133 rElementType.bModified = true; 1134 1135 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1136 1137 // Create event to notify listener about replaced element settings 1138 ConfigurationEvent aEvent; 1139 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1140 1141 aEvent.ResourceURL = ResourceURL; 1142 aEvent.Accessor <<= xThis; 1143 aEvent.Source = xIfac; 1144 aEvent.ReplacedElement <<= xOldSettings; 1145 aEvent.Element <<= pDataSettings->xSettings; 1146 1147 aGuard.unlock(); 1148 1149 implts_notifyContainerListener( aEvent, NotifyOp_Replace ); 1150 } 1151 else 1152 { 1153 // we have no settings in our user-defined layer - insert 1154 UIElementData aUIElementData; 1155 1156 aUIElementData.bDefault = false; 1157 aUIElementData.bDefaultNode = false; 1158 aUIElementData.bModified = true; 1159 1160 // Create a copy of the data if the container is not const 1161 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); 1162 if ( xReplace.is() ) 1163 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); 1164 else 1165 aUIElementData.xSettings = aNewData; 1166 aUIElementData.aName = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix; 1167 aUIElementData.aResourceURL = ResourceURL; 1168 m_bModified = true; 1169 1170 // Modify type container 1171 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1172 rElementType.bModified = true; 1173 1174 UIElementDataHashMap& rElements = rElementType.aElementsHashMap; 1175 1176 // Check our user element settings hash map as it can already contain settings that have been set to default! 1177 // If no node can be found, we have to insert it. 1178 UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL ); 1179 if ( pIter != rElements.end() ) 1180 pIter->second = aUIElementData; 1181 else 1182 rElements.insert( UIElementDataHashMap::value_type( ResourceURL, aUIElementData )); 1183 1184 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1185 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1186 1187 // Create event to notify listener about replaced element settings 1188 ConfigurationEvent aEvent; 1189 1190 aEvent.ResourceURL = ResourceURL; 1191 aEvent.Accessor <<= xThis; 1192 aEvent.Source = xIfac; 1193 aEvent.ReplacedElement <<= pDataSettings->xSettings; 1194 aEvent.Element <<= aUIElementData.xSettings; 1195 1196 aGuard.unlock(); 1197 1198 implts_notifyContainerListener( aEvent, NotifyOp_Replace ); 1199 } 1200 } 1201 else 1202 throw NoSuchElementException(); 1203 } 1204 } 1205 1206 void SAL_CALL ModuleUIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL ) 1207 throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException) 1208 { 1209 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1210 1211 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1212 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1213 throw IllegalArgumentException(); 1214 else if ( m_bReadOnly ) 1215 throw IllegalAccessException(); 1216 else 1217 { 1218 ResetableGuard aGuard( m_aLock ); 1219 1220 if ( m_bDisposed ) 1221 throw DisposedException(); 1222 1223 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); 1224 if ( pDataSettings ) 1225 { 1226 // If element settings are default, we don't need to change anything! 1227 if ( pDataSettings->bDefault ) 1228 return; 1229 else 1230 { 1231 Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings; 1232 pDataSettings->bDefault = true; 1233 1234 // check if this is a default layer node 1235 if ( !pDataSettings->bDefaultNode ) 1236 pDataSettings->bModified = true; // we have to remove this node from the user layer! 1237 pDataSettings->xSettings.clear(); 1238 m_bModified = true; // user layer must be written 1239 1240 // Modify type container 1241 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1242 rElementType.bModified = true; 1243 1244 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1245 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1246 1247 // Check if we have settings in the default layer which replaces the user-defined one! 1248 UIElementData* pDefaultDataSettings = impl_findUIElementData( ResourceURL, nElementType ); 1249 if ( pDefaultDataSettings ) 1250 { 1251 // Create event to notify listener about replaced element settings 1252 ConfigurationEvent aEvent; 1253 1254 aEvent.ResourceURL = ResourceURL; 1255 aEvent.Accessor <<= xThis; 1256 aEvent.Source = xIfac; 1257 aEvent.Element <<= xRemovedSettings; 1258 aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings; 1259 1260 aGuard.unlock(); 1261 1262 implts_notifyContainerListener( aEvent, NotifyOp_Replace ); 1263 } 1264 else 1265 { 1266 // Create event to notify listener about removed element settings 1267 ConfigurationEvent aEvent; 1268 1269 aEvent.ResourceURL = ResourceURL; 1270 aEvent.Accessor <<= xThis; 1271 aEvent.Source = xIfac; 1272 aEvent.Element <<= xRemovedSettings; 1273 1274 aGuard.unlock(); 1275 1276 implts_notifyContainerListener( aEvent, NotifyOp_Remove ); 1277 } 1278 } 1279 } 1280 else 1281 throw NoSuchElementException(); 1282 } 1283 } 1284 1285 void SAL_CALL ModuleUIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData ) 1286 throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException ) 1287 { 1288 sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL ); 1289 1290 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1291 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1292 throw IllegalArgumentException(); 1293 else if ( m_bReadOnly ) 1294 throw IllegalAccessException(); 1295 else 1296 { 1297 ResetableGuard aGuard( m_aLock ); 1298 1299 if ( m_bDisposed ) 1300 throw DisposedException(); 1301 1302 UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType ); 1303 if ( !pDataSettings ) 1304 { 1305 UIElementData aUIElementData; 1306 1307 aUIElementData.bDefault = false; 1308 aUIElementData.bDefaultNode = false; 1309 aUIElementData.bModified = true; 1310 1311 // Create a copy of the data if the container is not const 1312 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); 1313 if ( xReplace.is() ) 1314 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); 1315 else 1316 aUIElementData.xSettings = aNewData; 1317 aUIElementData.aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix; 1318 aUIElementData.aResourceURL = NewResourceURL; 1319 m_bModified = true; 1320 1321 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1322 rElementType.bModified = true; 1323 1324 UIElementDataHashMap& rElements = rElementType.aElementsHashMap; 1325 rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, aUIElementData )); 1326 1327 Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings ); 1328 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1329 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1330 1331 // Create event to notify listener about removed element settings 1332 ConfigurationEvent aEvent; 1333 1334 aEvent.ResourceURL = NewResourceURL; 1335 aEvent.Accessor <<= xThis; 1336 aEvent.Source = xIfac; 1337 aEvent.Element <<= xInsertSettings; 1338 1339 aGuard.unlock(); 1340 1341 implts_notifyContainerListener( aEvent, NotifyOp_Insert ); 1342 } 1343 else 1344 throw ElementExistException(); 1345 } 1346 } 1347 1348 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getImageManager() throw (::com::sun::star::uno::RuntimeException) 1349 { 1350 ResetableGuard aGuard( m_aLock ); 1351 1352 if ( m_bDisposed ) 1353 throw DisposedException(); 1354 1355 if ( !m_xModuleImageManager.is() ) 1356 { 1357 m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ModuleImageManager( m_xServiceManager )), 1358 UNO_QUERY ); 1359 Reference< XInitialization > xInit( m_xModuleImageManager, UNO_QUERY ); 1360 1361 Sequence< Any > aPropSeq( 3 ); 1362 PropertyValue aPropValue; 1363 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" )); 1364 aPropValue.Value = makeAny( m_xUserConfigStorage ); 1365 aPropSeq[0] = makeAny( aPropValue ); 1366 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" )); 1367 aPropValue.Value = makeAny( m_aModuleIdentifier ); 1368 aPropSeq[1] = makeAny( aPropValue ); 1369 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" )); 1370 aPropValue.Value = makeAny( m_xUserRootCommit ); 1371 aPropSeq[2] = makeAny( aPropValue ); 1372 1373 xInit->initialize( aPropSeq ); 1374 } 1375 1376 return Reference< XInterface >( m_xModuleImageManager, UNO_QUERY ); 1377 } 1378 1379 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getShortCutManager() throw (::com::sun::star::uno::RuntimeException) 1380 { 1381 ResetableGuard aGuard( m_aLock ); 1382 1383 if ( m_bDisposed ) 1384 throw DisposedException(); 1385 1386 Reference< XMultiServiceFactory > xSMGR = m_xServiceManager; 1387 ::rtl::OUString aModule = m_aModuleIdentifier; 1388 1389 if ( !m_xModuleAcceleratorManager.is() ) 1390 { 1391 Reference< XInterface > xManager = xSMGR->createInstance(SERVICENAME_MODULEACCELERATORCONFIGURATION); 1392 Reference< XInitialization > xInit (xManager, UNO_QUERY_THROW); 1393 1394 PropertyValue aProp; 1395 aProp.Name = ::rtl::OUString::createFromAscii("ModuleIdentifier"); 1396 aProp.Value <<= aModule; 1397 1398 Sequence< Any > lArgs(1); 1399 lArgs[0] <<= aProp; 1400 1401 xInit->initialize(lArgs); 1402 m_xModuleAcceleratorManager = Reference< XInterface >( xManager, UNO_QUERY ); 1403 } 1404 1405 return m_xModuleAcceleratorManager; 1406 } 1407 1408 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getEventsManager() throw (::com::sun::star::uno::RuntimeException) 1409 { 1410 return Reference< XInterface >(); 1411 } 1412 1413 // XModuleUIConfigurationManager 1414 sal_Bool SAL_CALL ModuleUIConfigurationManager::isDefaultSettings( const ::rtl::OUString& ResourceURL ) 1415 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 1416 { 1417 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1418 1419 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1420 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1421 throw IllegalArgumentException(); 1422 else 1423 { 1424 ResetableGuard aGuard( m_aLock ); 1425 1426 if ( m_bDisposed ) 1427 throw DisposedException(); 1428 1429 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); 1430 if ( pDataSettings && pDataSettings->bDefaultNode ) 1431 return sal_True; 1432 } 1433 1434 return sal_False; 1435 } 1436 1437 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getDefaultSettings( const ::rtl::OUString& ResourceURL ) 1438 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 1439 { 1440 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1441 1442 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1443 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1444 throw IllegalArgumentException(); 1445 else 1446 { 1447 ResetableGuard aGuard( m_aLock ); 1448 1449 if ( m_bDisposed ) 1450 throw DisposedException(); 1451 1452 // preload list of element types on demand 1453 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); 1454 1455 // Look into our default vector/hash_map combination 1456 UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; 1457 UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL ); 1458 if ( pIter != rDefaultHashMap.end() ) 1459 { 1460 if ( !pIter->second.xSettings.is() ) 1461 impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second ); 1462 return pIter->second.xSettings; 1463 } 1464 } 1465 1466 // Nothing has been found! 1467 throw NoSuchElementException(); 1468 } 1469 1470 // XUIConfigurationPersistence 1471 void SAL_CALL ModuleUIConfigurationManager::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 1472 { 1473 ResetableGuard aGuard( m_aLock ); 1474 1475 if ( m_bDisposed ) 1476 throw DisposedException(); 1477 1478 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) 1479 { 1480 // Try to access our module sub folder 1481 ConfigEventNotifyContainer aRemoveNotifyContainer; 1482 ConfigEventNotifyContainer aReplaceNotifyContainer; 1483 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1484 { 1485 try 1486 { 1487 UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][i]; 1488 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i]; 1489 1490 if ( rUserElementType.bModified ) 1491 impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer ); 1492 } 1493 catch ( Exception& ) 1494 { 1495 throw IOException(); 1496 } 1497 } 1498 1499 m_bModified = sal_False; 1500 1501 // Unlock mutex before notify our listeners 1502 aGuard.unlock(); 1503 1504 // Notify our listeners 1505 for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ ) 1506 implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove ); 1507 for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ ) 1508 implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace ); 1509 } 1510 } 1511 1512 void SAL_CALL ModuleUIConfigurationManager::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 1513 { 1514 ResetableGuard aGuard( m_aLock ); 1515 1516 if ( m_bDisposed ) 1517 throw DisposedException(); 1518 1519 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) 1520 { 1521 // Try to access our module sub folder 1522 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1523 { 1524 try 1525 { 1526 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; 1527 Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY ); 1528 1529 if ( rElementType.bModified && xStorage.is() ) 1530 { 1531 impl_storeElementTypeData( xStorage, rElementType ); 1532 m_pStorageHandler[i]->commitUserChanges(); 1533 } 1534 } 1535 catch ( Exception& ) 1536 { 1537 throw IOException(); 1538 } 1539 } 1540 1541 m_bModified = false; 1542 } 1543 } 1544 1545 void SAL_CALL ModuleUIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 1546 { 1547 ResetableGuard aGuard( m_aLock ); 1548 1549 if ( m_bDisposed ) 1550 throw DisposedException(); 1551 1552 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) 1553 { 1554 // Try to access our module sub folder 1555 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1556 { 1557 try 1558 { 1559 Reference< XStorage > xElementTypeStorage( Storage->openStorageElement( 1560 OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE )); 1561 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; 1562 1563 if ( rElementType.bModified && xElementTypeStorage.is() ) 1564 impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag! 1565 } 1566 catch ( Exception& ) 1567 { 1568 throw IOException(); 1569 } 1570 } 1571 1572 Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY ); 1573 if ( xTransactedObject.is() ) 1574 xTransactedObject->commit(); 1575 } 1576 } 1577 1578 sal_Bool SAL_CALL ModuleUIConfigurationManager::isModified() throw (::com::sun::star::uno::RuntimeException) 1579 { 1580 ResetableGuard aGuard( m_aLock ); 1581 1582 return m_bModified; 1583 } 1584 1585 sal_Bool SAL_CALL ModuleUIConfigurationManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException) 1586 { 1587 ResetableGuard aGuard( m_aLock ); 1588 1589 return m_bReadOnly; 1590 } 1591 1592 void ModuleUIConfigurationManager::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp ) 1593 { 1594 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) ); 1595 if ( pContainer != NULL ) 1596 { 1597 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); 1598 while ( pIterator.hasMoreElements() ) 1599 { 1600 try 1601 { 1602 switch ( eOp ) 1603 { 1604 case NotifyOp_Replace: 1605 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent ); 1606 break; 1607 case NotifyOp_Insert: 1608 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent ); 1609 break; 1610 case NotifyOp_Remove: 1611 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent ); 1612 break; 1613 } 1614 } 1615 catch( css::uno::RuntimeException& ) 1616 { 1617 pIterator.remove(); 1618 } 1619 } 1620 } 1621 } 1622 1623 } // namespace framework 1624