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 successful, 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() 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 Reference< XComponent > xCompMAM( m_xModuleAcceleratorManager, UNO_QUERY ); 781 if ( xCompMAM.is() ) 782 xCompMAM->dispose(); 783 m_xModuleAcceleratorManager.clear(); 784 m_aUIElements[LAYER_USERDEFINED].clear(); 785 m_aUIElements[LAYER_DEFAULT].clear(); 786 m_xDefaultConfigStorage.clear(); 787 m_xUserConfigStorage.clear(); 788 m_xUserRootCommit.clear(); 789 m_bConfigRead = false; 790 m_bModified = false; 791 m_bDisposed = true; 792 aGuard.unlock(); 793 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 794 795 try 796 { 797 if ( xModuleImageManager.is() ) 798 xModuleImageManager->dispose(); 799 } 800 catch ( Exception& ) 801 { 802 } 803 } 804 805 void SAL_CALL ModuleUIConfigurationManager::addEventListener( const Reference< XEventListener >& xListener ) 806 { 807 { 808 ResetableGuard aGuard( m_aLock ); 809 810 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 811 if ( m_bDisposed ) 812 throw DisposedException(); 813 } 814 815 m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); 816 } 817 818 void SAL_CALL ModuleUIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) 819 { 820 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 821 m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); 822 } 823 824 // XInitialization 825 void SAL_CALL ModuleUIConfigurationManager::initialize( const Sequence< Any >& aArguments ) 826 { 827 ResetableGuard aLock( m_aLock ); 828 829 if ( !m_bInitialized ) 830 { 831 ::comphelper::SequenceAsHashMap lArgs(aArguments); 832 m_aModuleIdentifier = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleIdentifier"), ::rtl::OUString()); 833 m_aModuleShortName = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleShortName"), ::rtl::OUString()); 834 835 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 836 { 837 rtl::OUString aResourceType; 838 if ( i == ::com::sun::star::ui::UIElementType::MENUBAR ) 839 aResourceType = PresetHandler::RESOURCETYPE_MENUBAR(); 840 else if ( i == ::com::sun::star::ui::UIElementType::TOOLBAR ) 841 aResourceType = PresetHandler::RESOURCETYPE_TOOLBAR(); 842 else if ( i == ::com::sun::star::ui::UIElementType::STATUSBAR ) 843 aResourceType = PresetHandler::RESOURCETYPE_STATUSBAR(); 844 845 if ( aResourceType.getLength() > 0 ) 846 { 847 m_pStorageHandler[i] = new PresetHandler( m_xServiceManager ); 848 m_pStorageHandler[i]->connectToResource( PresetHandler::E_MODULES, 849 aResourceType, // this path won't be used later ... see next lines! 850 m_aModuleShortName, 851 css::uno::Reference< css::embed::XStorage >()); // no document root used here! 852 } 853 } 854 855 // initialize root storages for all resource types 856 m_xUserRootCommit = css::uno::Reference< css::embed::XTransactedObject >( 857 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY); // can be empty 858 m_xDefaultConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageShare( 859 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageShare()); 860 m_xUserConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageUser( 861 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageUser()); 862 863 if ( m_xUserConfigStorage.is() ) 864 { 865 Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY ); 866 if ( xPropSet.is() ) 867 { 868 long nOpenMode = 0; 869 Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ))); 870 if ( a >>= nOpenMode ) 871 m_bReadOnly = !( nOpenMode & ElementModes::WRITE ); 872 } 873 } 874 875 impl_Initialize(); 876 877 m_bInitialized = true; 878 } 879 } 880 881 // XUIConfiguration 882 void SAL_CALL ModuleUIConfigurationManager::addConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) 883 { 884 { 885 ResetableGuard aGuard( m_aLock ); 886 887 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 888 if ( m_bDisposed ) 889 throw DisposedException(); 890 } 891 892 m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener ); 893 } 894 895 void SAL_CALL ModuleUIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) 896 { 897 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 898 m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener ); 899 } 900 901 902 // XUIConfigurationManager 903 void SAL_CALL ModuleUIConfigurationManager::reset() 904 { 905 ResetableGuard aGuard( m_aLock ); 906 907 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 908 if ( m_bDisposed ) 909 throw DisposedException(); 910 911 bool bResetStorage( false ); 912 913 if ( !isReadOnly() ) 914 { 915 // Remove all elements from our user-defined storage! 916 try 917 { 918 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 919 { 920 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; 921 Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY ); 922 923 if ( xSubStorage.is() ) 924 { 925 bool bCommitSubStorage( false ); 926 Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY ); 927 Sequence< OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames(); 928 for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ ) 929 { 930 xSubStorage->removeElement( aUIElementStreamNames[j] ); 931 bCommitSubStorage = true; 932 } 933 934 if ( bCommitSubStorage ) 935 { 936 Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY ); 937 if ( xTransactedObject.is() ) 938 xTransactedObject->commit(); 939 m_pStorageHandler[i]->commitUserChanges(); 940 } 941 } 942 } 943 944 bResetStorage = true; 945 946 // remove settings from user defined layer and notify listener about removed settings data! 947 ConfigEventNotifyContainer aRemoveEventNotifyContainer; 948 ConfigEventNotifyContainer aReplaceEventNotifyContainer; 949 for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ ) 950 { 951 try 952 { 953 UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][j]; 954 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][j]; 955 956 impl_resetElementTypeData( rUserElementType, rDefaultElementType, aRemoveEventNotifyContainer, aReplaceEventNotifyContainer ); 957 rUserElementType.bModified = sal_False; 958 } 959 catch ( Exception& ) 960 { 961 throw IOException(); 962 } 963 } 964 965 m_bModified = sal_False; 966 967 // Unlock mutex before notify our listeners 968 aGuard.unlock(); 969 970 // Notify our listeners 971 sal_uInt32 k = 0; 972 for ( k = 0; k < aRemoveEventNotifyContainer.size(); k++ ) 973 implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove ); 974 for ( k = 0; k < aReplaceEventNotifyContainer.size(); k++ ) 975 implts_notifyContainerListener( aReplaceEventNotifyContainer[k], NotifyOp_Replace ); 976 } 977 catch ( ::com::sun::star::lang::IllegalArgumentException& ) 978 { 979 } 980 catch ( ::com::sun::star::container::NoSuchElementException& ) 981 { 982 } 983 catch ( ::com::sun::star::embed::InvalidStorageException& ) 984 { 985 } 986 catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) 987 { 988 } 989 } 990 } 991 992 Sequence< Sequence< PropertyValue > > SAL_CALL ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType ) 993 { 994 if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 995 throw IllegalArgumentException(); 996 997 ResetableGuard aGuard( m_aLock ); 998 if ( m_bDisposed ) 999 throw DisposedException(); 1000 1001 Sequence< Sequence< PropertyValue > > aElementInfoSeq; 1002 UIElementInfoHashMap aUIElementInfoCollection; 1003 1004 if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) 1005 { 1006 for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1007 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) ); 1008 } 1009 else 1010 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType ); 1011 1012 Sequence< PropertyValue > aUIElementInfo( 2 ); 1013 aUIElementInfo[0].Name = m_aPropResourceURL; 1014 aUIElementInfo[1].Name = m_aPropUIName; 1015 1016 aElementInfoSeq.realloc( aUIElementInfoCollection.size() ); 1017 UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin(); 1018 1019 sal_Int32 n = 0; 1020 while ( pIter != aUIElementInfoCollection.end() ) 1021 { 1022 aUIElementInfo[0].Value <<= pIter->second.aResourceURL; 1023 aUIElementInfo[1].Value <<= pIter->second.aUIName; 1024 aElementInfoSeq[n++] = aUIElementInfo; 1025 ++pIter; 1026 } 1027 1028 return aElementInfoSeq; 1029 } 1030 1031 Reference< XIndexContainer > SAL_CALL ModuleUIConfigurationManager::createSettings() 1032 { 1033 ResetableGuard aGuard( m_aLock ); 1034 1035 if ( m_bDisposed ) 1036 throw DisposedException(); 1037 1038 // Creates an empty item container which can be filled from outside 1039 return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); 1040 } 1041 1042 sal_Bool SAL_CALL ModuleUIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL ) 1043 { 1044 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1045 1046 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1047 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1048 throw IllegalArgumentException(); 1049 else 1050 { 1051 ResetableGuard aGuard( m_aLock ); 1052 1053 if ( m_bDisposed ) 1054 throw DisposedException(); 1055 1056 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); 1057 if ( pDataSettings ) 1058 return sal_True; 1059 } 1060 1061 return sal_False; 1062 } 1063 1064 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable ) 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 { 1094 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1095 1096 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1097 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1098 throw IllegalArgumentException(); 1099 else if ( m_bReadOnly ) 1100 throw IllegalAccessException(); 1101 else 1102 { 1103 ResetableGuard aGuard( m_aLock ); 1104 1105 if ( m_bDisposed ) 1106 throw DisposedException(); 1107 1108 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); 1109 if ( pDataSettings ) 1110 { 1111 if ( !pDataSettings->bDefaultNode ) 1112 { 1113 // we have a settings entry in our user-defined layer - replace 1114 Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings; 1115 1116 // Create a copy of the data if the container is not const 1117 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); 1118 if ( xReplace.is() ) 1119 pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); 1120 else 1121 pDataSettings->xSettings = aNewData; 1122 pDataSettings->bDefault = false; 1123 pDataSettings->bModified = true; 1124 m_bModified = true; 1125 1126 // Modify type container 1127 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1128 rElementType.bModified = true; 1129 1130 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1131 1132 // Create event to notify listener about replaced element settings 1133 ConfigurationEvent aEvent; 1134 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1135 1136 aEvent.ResourceURL = ResourceURL; 1137 aEvent.Accessor <<= xThis; 1138 aEvent.Source = xIfac; 1139 aEvent.ReplacedElement <<= xOldSettings; 1140 aEvent.Element <<= pDataSettings->xSettings; 1141 1142 aGuard.unlock(); 1143 1144 implts_notifyContainerListener( aEvent, NotifyOp_Replace ); 1145 } 1146 else 1147 { 1148 // we have no settings in our user-defined layer - insert 1149 UIElementData aUIElementData; 1150 1151 aUIElementData.bDefault = false; 1152 aUIElementData.bDefaultNode = false; 1153 aUIElementData.bModified = true; 1154 1155 // Create a copy of the data if the container is not const 1156 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); 1157 if ( xReplace.is() ) 1158 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); 1159 else 1160 aUIElementData.xSettings = aNewData; 1161 aUIElementData.aName = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix; 1162 aUIElementData.aResourceURL = ResourceURL; 1163 m_bModified = true; 1164 1165 // Modify type container 1166 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1167 rElementType.bModified = true; 1168 1169 UIElementDataHashMap& rElements = rElementType.aElementsHashMap; 1170 1171 // Check our user element settings hash map as it can already contain settings that have been set to default! 1172 // If no node can be found, we have to insert it. 1173 UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL ); 1174 if ( pIter != rElements.end() ) 1175 pIter->second = aUIElementData; 1176 else 1177 rElements.insert( UIElementDataHashMap::value_type( ResourceURL, aUIElementData )); 1178 1179 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1180 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1181 1182 // Create event to notify listener about replaced element settings 1183 ConfigurationEvent aEvent; 1184 1185 aEvent.ResourceURL = ResourceURL; 1186 aEvent.Accessor <<= xThis; 1187 aEvent.Source = xIfac; 1188 aEvent.ReplacedElement <<= pDataSettings->xSettings; 1189 aEvent.Element <<= aUIElementData.xSettings; 1190 1191 aGuard.unlock(); 1192 1193 implts_notifyContainerListener( aEvent, NotifyOp_Replace ); 1194 } 1195 } 1196 else 1197 throw NoSuchElementException(); 1198 } 1199 } 1200 1201 void SAL_CALL ModuleUIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL ) 1202 { 1203 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1204 1205 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1206 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1207 throw IllegalArgumentException(); 1208 else if ( m_bReadOnly ) 1209 throw IllegalAccessException(); 1210 else 1211 { 1212 ResetableGuard aGuard( m_aLock ); 1213 1214 if ( m_bDisposed ) 1215 throw DisposedException(); 1216 1217 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); 1218 if ( pDataSettings ) 1219 { 1220 // If element settings are default, we don't need to change anything! 1221 if ( pDataSettings->bDefault ) 1222 return; 1223 else 1224 { 1225 Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings; 1226 pDataSettings->bDefault = true; 1227 1228 // check if this is a default layer node 1229 if ( !pDataSettings->bDefaultNode ) 1230 pDataSettings->bModified = true; // we have to remove this node from the user layer! 1231 pDataSettings->xSettings.clear(); 1232 m_bModified = true; // user layer must be written 1233 1234 // Modify type container 1235 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1236 rElementType.bModified = true; 1237 1238 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1239 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1240 1241 // Check if we have settings in the default layer which replaces the user-defined one! 1242 UIElementData* pDefaultDataSettings = impl_findUIElementData( ResourceURL, nElementType ); 1243 if ( pDefaultDataSettings ) 1244 { 1245 // Create event to notify listener about replaced element settings 1246 ConfigurationEvent aEvent; 1247 1248 aEvent.ResourceURL = ResourceURL; 1249 aEvent.Accessor <<= xThis; 1250 aEvent.Source = xIfac; 1251 aEvent.Element <<= xRemovedSettings; 1252 aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings; 1253 1254 aGuard.unlock(); 1255 1256 implts_notifyContainerListener( aEvent, NotifyOp_Replace ); 1257 } 1258 else 1259 { 1260 // Create event to notify listener about removed element settings 1261 ConfigurationEvent aEvent; 1262 1263 aEvent.ResourceURL = ResourceURL; 1264 aEvent.Accessor <<= xThis; 1265 aEvent.Source = xIfac; 1266 aEvent.Element <<= xRemovedSettings; 1267 1268 aGuard.unlock(); 1269 1270 implts_notifyContainerListener( aEvent, NotifyOp_Remove ); 1271 } 1272 } 1273 } 1274 else 1275 throw NoSuchElementException(); 1276 } 1277 } 1278 1279 void SAL_CALL ModuleUIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData ) 1280 { 1281 sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL ); 1282 1283 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1284 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1285 throw IllegalArgumentException(); 1286 else if ( m_bReadOnly ) 1287 throw IllegalAccessException(); 1288 else 1289 { 1290 ResetableGuard aGuard( m_aLock ); 1291 1292 if ( m_bDisposed ) 1293 throw DisposedException(); 1294 1295 UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType ); 1296 if ( !pDataSettings ) 1297 { 1298 UIElementData aUIElementData; 1299 1300 aUIElementData.bDefault = false; 1301 aUIElementData.bDefaultNode = false; 1302 aUIElementData.bModified = true; 1303 1304 // Create a copy of the data if the container is not const 1305 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); 1306 if ( xReplace.is() ) 1307 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); 1308 else 1309 aUIElementData.xSettings = aNewData; 1310 aUIElementData.aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix; 1311 aUIElementData.aResourceURL = NewResourceURL; 1312 m_bModified = true; 1313 1314 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; 1315 rElementType.bModified = true; 1316 1317 UIElementDataHashMap& rElements = rElementType.aElementsHashMap; 1318 rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, aUIElementData )); 1319 1320 Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings ); 1321 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); 1322 Reference< XInterface > xIfac( xThis, UNO_QUERY ); 1323 1324 // Create event to notify listener about removed element settings 1325 ConfigurationEvent aEvent; 1326 1327 aEvent.ResourceURL = NewResourceURL; 1328 aEvent.Accessor <<= xThis; 1329 aEvent.Source = xIfac; 1330 aEvent.Element <<= xInsertSettings; 1331 1332 aGuard.unlock(); 1333 1334 implts_notifyContainerListener( aEvent, NotifyOp_Insert ); 1335 } 1336 else 1337 throw ElementExistException(); 1338 } 1339 } 1340 1341 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getImageManager() 1342 { 1343 ResetableGuard aGuard( m_aLock ); 1344 1345 if ( m_bDisposed ) 1346 throw DisposedException(); 1347 1348 if ( !m_xModuleImageManager.is() ) 1349 { 1350 m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ModuleImageManager( m_xServiceManager )), 1351 UNO_QUERY ); 1352 Reference< XInitialization > xInit( m_xModuleImageManager, UNO_QUERY ); 1353 1354 Sequence< Any > aPropSeq( 3 ); 1355 PropertyValue aPropValue; 1356 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" )); 1357 aPropValue.Value = makeAny( m_xUserConfigStorage ); 1358 aPropSeq[0] = makeAny( aPropValue ); 1359 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" )); 1360 aPropValue.Value = makeAny( m_aModuleIdentifier ); 1361 aPropSeq[1] = makeAny( aPropValue ); 1362 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" )); 1363 aPropValue.Value = makeAny( m_xUserRootCommit ); 1364 aPropSeq[2] = makeAny( aPropValue ); 1365 1366 xInit->initialize( aPropSeq ); 1367 } 1368 1369 return Reference< XInterface >( m_xModuleImageManager, UNO_QUERY ); 1370 } 1371 1372 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getShortCutManager() 1373 { 1374 ResetableGuard aGuard( m_aLock ); 1375 1376 if ( m_bDisposed ) 1377 throw DisposedException(); 1378 1379 Reference< XMultiServiceFactory > xSMGR = m_xServiceManager; 1380 ::rtl::OUString aModule = m_aModuleIdentifier; 1381 1382 if ( !m_xModuleAcceleratorManager.is() ) 1383 { 1384 Reference< XInterface > xManager = xSMGR->createInstance(SERVICENAME_MODULEACCELERATORCONFIGURATION); 1385 Reference< XInitialization > xInit (xManager, UNO_QUERY_THROW); 1386 1387 PropertyValue aProp; 1388 aProp.Name = ::rtl::OUString::createFromAscii("ModuleIdentifier"); 1389 aProp.Value <<= aModule; 1390 1391 Sequence< Any > lArgs(1); 1392 lArgs[0] <<= aProp; 1393 1394 xInit->initialize(lArgs); 1395 m_xModuleAcceleratorManager = Reference< XInterface >( xManager, UNO_QUERY ); 1396 } 1397 1398 return m_xModuleAcceleratorManager; 1399 } 1400 1401 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getEventsManager() 1402 { 1403 return Reference< XInterface >(); 1404 } 1405 1406 // XModuleUIConfigurationManager 1407 sal_Bool SAL_CALL ModuleUIConfigurationManager::isDefaultSettings( const ::rtl::OUString& ResourceURL ) 1408 { 1409 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1410 1411 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1412 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1413 throw IllegalArgumentException(); 1414 else 1415 { 1416 ResetableGuard aGuard( m_aLock ); 1417 1418 if ( m_bDisposed ) 1419 throw DisposedException(); 1420 1421 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); 1422 if ( pDataSettings && pDataSettings->bDefaultNode ) 1423 return sal_True; 1424 } 1425 1426 return sal_False; 1427 } 1428 1429 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getDefaultSettings( const ::rtl::OUString& ResourceURL ) 1430 { 1431 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); 1432 1433 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || 1434 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) 1435 throw IllegalArgumentException(); 1436 else 1437 { 1438 ResetableGuard aGuard( m_aLock ); 1439 1440 if ( m_bDisposed ) 1441 throw DisposedException(); 1442 1443 // preload list of element types on demand 1444 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); 1445 1446 // Look into our default vector/hash_map combination 1447 UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; 1448 UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL ); 1449 if ( pIter != rDefaultHashMap.end() ) 1450 { 1451 if ( !pIter->second.xSettings.is() ) 1452 impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second ); 1453 return pIter->second.xSettings; 1454 } 1455 } 1456 1457 // Nothing has been found! 1458 throw NoSuchElementException(); 1459 } 1460 1461 // XUIConfigurationPersistence 1462 void SAL_CALL ModuleUIConfigurationManager::reload() 1463 { 1464 ResetableGuard aGuard( m_aLock ); 1465 1466 if ( m_bDisposed ) 1467 throw DisposedException(); 1468 1469 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) 1470 { 1471 // Try to access our module sub folder 1472 ConfigEventNotifyContainer aRemoveNotifyContainer; 1473 ConfigEventNotifyContainer aReplaceNotifyContainer; 1474 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1475 { 1476 try 1477 { 1478 UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][i]; 1479 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i]; 1480 1481 if ( rUserElementType.bModified ) 1482 impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer ); 1483 } 1484 catch ( Exception& ) 1485 { 1486 throw IOException(); 1487 } 1488 } 1489 1490 m_bModified = sal_False; 1491 1492 // Unlock mutex before notify our listeners 1493 aGuard.unlock(); 1494 1495 // Notify our listeners 1496 for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ ) 1497 implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove ); 1498 for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ ) 1499 implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace ); 1500 } 1501 } 1502 1503 void SAL_CALL ModuleUIConfigurationManager::store() 1504 { 1505 ResetableGuard aGuard( m_aLock ); 1506 1507 if ( m_bDisposed ) 1508 throw DisposedException(); 1509 1510 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) 1511 { 1512 // Try to access our module sub folder 1513 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1514 { 1515 try 1516 { 1517 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; 1518 Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY ); 1519 1520 if ( rElementType.bModified && xStorage.is() ) 1521 { 1522 impl_storeElementTypeData( xStorage, rElementType ); 1523 m_pStorageHandler[i]->commitUserChanges(); 1524 } 1525 } 1526 catch ( Exception& ) 1527 { 1528 throw IOException(); 1529 } 1530 } 1531 1532 m_bModified = false; 1533 } 1534 } 1535 1536 void SAL_CALL ModuleUIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage ) 1537 { 1538 ResetableGuard aGuard( m_aLock ); 1539 1540 if ( m_bDisposed ) 1541 throw DisposedException(); 1542 1543 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) 1544 { 1545 // Try to access our module sub folder 1546 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) 1547 { 1548 try 1549 { 1550 Reference< XStorage > xElementTypeStorage( Storage->openStorageElement( 1551 OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE )); 1552 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; 1553 1554 if ( rElementType.bModified && xElementTypeStorage.is() ) 1555 impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag! 1556 } 1557 catch ( Exception& ) 1558 { 1559 throw IOException(); 1560 } 1561 } 1562 1563 Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY ); 1564 if ( xTransactedObject.is() ) 1565 xTransactedObject->commit(); 1566 } 1567 } 1568 1569 sal_Bool SAL_CALL ModuleUIConfigurationManager::isModified() 1570 { 1571 ResetableGuard aGuard( m_aLock ); 1572 1573 return m_bModified; 1574 } 1575 1576 sal_Bool SAL_CALL ModuleUIConfigurationManager::isReadOnly() 1577 { 1578 ResetableGuard aGuard( m_aLock ); 1579 1580 return m_bReadOnly; 1581 } 1582 1583 void ModuleUIConfigurationManager::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp ) 1584 { 1585 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) ); 1586 if ( pContainer != NULL ) 1587 { 1588 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); 1589 while ( pIterator.hasMoreElements() ) 1590 { 1591 try 1592 { 1593 switch ( eOp ) 1594 { 1595 case NotifyOp_Replace: 1596 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent ); 1597 break; 1598 case NotifyOp_Insert: 1599 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent ); 1600 break; 1601 case NotifyOp_Remove: 1602 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent ); 1603 break; 1604 } 1605 } 1606 catch( css::uno::RuntimeException& ) 1607 { 1608 pIterator.remove(); 1609 } 1610 } 1611 } 1612 } 1613 1614 } // namespace framework 1615