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