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