1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_framework.hxx" 30 31 #include <imagemanagerimpl.hxx> 32 #include <threadhelp/resetableguard.hxx> 33 #include <xml/imagesconfiguration.hxx> 34 #include <uiconfiguration/graphicnameaccess.hxx> 35 #include <services.h> 36 37 #include "properties.h" 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/beans/PropertyValue.hpp> 47 #include <com/sun/star/embed/ElementModes.hpp> 48 #include <com/sun/star/io/XStream.hpp> 49 #include <com/sun/star/ui/ImageType.hpp> 50 51 //_________________________________________________________________________________________________________________ 52 // other includes 53 //_________________________________________________________________________________________________________________ 54 55 #include <vcl/svapp.hxx> 56 #include <rtl/ustrbuf.hxx> 57 #include <osl/mutex.hxx> 58 #include <comphelper/sequence.hxx> 59 #include <tools/urlobj.hxx> 60 #include <unotools/ucbstreamhelper.hxx> 61 #include <vcl/pngread.hxx> 62 #include <vcl/pngwrite.hxx> 63 #include <rtl/logfile.hxx> 64 #include "svtools/miscopt.hxx" 65 66 //_________________________________________________________________________________________________________________ 67 // namespaces 68 //_________________________________________________________________________________________________________________ 69 70 using ::rtl::OUString; 71 using ::com::sun::star::uno::Sequence; 72 using ::com::sun::star::uno::XInterface; 73 using ::com::sun::star::uno::Exception; 74 using ::com::sun::star::uno::RuntimeException; 75 using ::com::sun::star::uno::UNO_QUERY; 76 using ::com::sun::star::uno::Any; 77 using ::com::sun::star::uno::makeAny; 78 using ::com::sun::star::graphic::XGraphic; 79 using namespace ::com::sun::star; 80 using namespace ::com::sun::star::io; 81 using namespace ::com::sun::star::embed; 82 using namespace ::com::sun::star::lang; 83 using namespace ::com::sun::star::container; 84 using namespace ::com::sun::star::beans; 85 using namespace ::com::sun::star::ui; 86 using namespace ::cppu; 87 88 // Image sizes for our toolbars/menus 89 const sal_Int32 IMAGE_SIZE_NORMAL = 16; 90 const sal_Int32 IMAGE_SIZE_LARGE = 26; 91 const sal_Int16 MAX_IMAGETYPE_VALUE = ::com::sun::star::ui::ImageType::COLOR_HIGHCONTRAST| 92 ::com::sun::star::ui::ImageType::SIZE_LARGE; 93 94 static const char IMAGE_FOLDER[] = "images"; 95 static const char BITMAPS_FOLDER[] = "Bitmaps"; 96 static const char IMAGE_EXTENSION[] = ".png"; 97 98 static const char* IMAGELIST_XML_FILE[] = 99 { 100 "sc_imagelist.xml", 101 "lc_imagelist.xml", 102 "sch_imagelist.xml", 103 "lch_imagelist.xml" 104 }; 105 106 static const char* BITMAP_FILE_NAMES[] = 107 { 108 "sc_userimages.png", 109 "lc_userimages.png", 110 "sch_userimages.png", 111 "lch_userimages.png" 112 }; 113 114 namespace framework 115 { 116 static char ModuleImageList[] = "private:resource/images/moduleimages"; 117 static osl::Mutex* pImageListWrapperMutex = 0; 118 static GlobalImageList* pGlobalImageList = 0; 119 static const char* ImageType_Prefixes[ImageType_COUNT] = 120 { 121 "res/commandimagelist/sc_", 122 "res/commandimagelist/lc_", 123 "res/commandimagelist/sch_", 124 "res/commandimagelist/lch_" 125 }; 126 127 typedef GraphicNameAccess CmdToXGraphicNameAccess; 128 129 static osl::Mutex& getGlobalImageListMutex() 130 { 131 if ( pImageListWrapperMutex == 0 ) 132 { 133 osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; 134 if ( pImageListWrapperMutex == 0 ) 135 pImageListWrapperMutex = new osl::Mutex; 136 } 137 138 return *pImageListWrapperMutex; 139 } 140 141 static GlobalImageList* getGlobalImageList( const uno::Reference< XMultiServiceFactory >& rServiceManager ) 142 { 143 osl::MutexGuard guard( getGlobalImageListMutex() ); 144 145 if ( pGlobalImageList == 0 ) 146 pGlobalImageList = new GlobalImageList( rServiceManager ); 147 148 return pGlobalImageList; 149 } 150 151 static rtl::OUString getCanonicalName( const rtl::OUString& rFileName ) 152 { 153 bool bRemoveSlash( true ); 154 sal_Int32 nLength = rFileName.getLength(); 155 const sal_Unicode* pString = rFileName.getStr(); 156 157 rtl::OUStringBuffer aBuf( nLength ); 158 for ( sal_Int32 i = 0; i < nLength; i++ ) 159 { 160 const sal_Unicode c = pString[i]; 161 switch ( c ) 162 { 163 // map forbidden characters to escape 164 case '/' : if ( !bRemoveSlash ) 165 aBuf.appendAscii( "%2f" ); 166 break; 167 case '\\': aBuf.appendAscii( "%5c" ); bRemoveSlash = false; break; 168 case ':' : aBuf.appendAscii( "%3a" ); bRemoveSlash = false; break; 169 case '*' : aBuf.appendAscii( "%2a" ); bRemoveSlash = false; break; 170 case '?' : aBuf.appendAscii( "%3f" ); bRemoveSlash = false; break; 171 case '<' : aBuf.appendAscii( "%3c" ); bRemoveSlash = false; break; 172 case '>' : aBuf.appendAscii( "%3e" ); bRemoveSlash = false; break; 173 case '|' : aBuf.appendAscii( "%7c" ); bRemoveSlash = false; break; 174 default: aBuf.append( c ); bRemoveSlash = false; 175 } 176 } 177 return aBuf.makeStringAndClear(); 178 } 179 180 //_________________________________________________________________________________________________________________ 181 182 CmdImageList::CmdImageList( const uno::Reference< XMultiServiceFactory >& rServiceManager, const rtl::OUString& aModuleIdentifier ) : 183 m_bVectorInit( sal_False ), 184 m_aModuleIdentifier( aModuleIdentifier ), 185 m_xServiceManager( rServiceManager ), 186 m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) 187 { 188 for ( sal_Int32 n=0; n < ImageType_COUNT; n++ ) 189 m_pImageList[n] = 0; 190 } 191 192 CmdImageList::~CmdImageList() 193 { 194 for ( sal_Int32 n=0; n < ImageType_COUNT; n++ ) 195 delete m_pImageList[n]; 196 } 197 198 void CmdImageList::impl_fillCommandToImageNameMap() 199 { 200 RTL_LOGFILE_CONTEXT( aLog, "framework: CmdImageList::impl_fillCommandToImageNameMap" ); 201 202 if ( !m_bVectorInit ) 203 { 204 const rtl::OUString aCommandImageList( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDIMAGELIST )); 205 Sequence< OUString > aCmdImageSeq; 206 uno::Reference< XNameAccess > xCmdDesc( m_xServiceManager->createInstance( 207 SERVICENAME_UICOMMANDDESCRIPTION ), 208 UNO_QUERY ); 209 210 if ( m_aModuleIdentifier.getLength() > 0 ) 211 { 212 // If we have a module identifier - use to retrieve the command image name list from it. 213 // Otherwise we will use the global command image list 214 try 215 { 216 xCmdDesc->getByName( m_aModuleIdentifier ) >>= xCmdDesc; 217 if ( xCmdDesc.is() ) 218 xCmdDesc->getByName( aCommandImageList ) >>= aCmdImageSeq; 219 } 220 catch ( NoSuchElementException& ) 221 { 222 // Module unknown we will work with an empty command image list! 223 return; 224 } 225 } 226 227 if ( xCmdDesc.is() ) 228 { 229 try 230 { 231 xCmdDesc->getByName( aCommandImageList ) >>= aCmdImageSeq; 232 } 233 catch ( NoSuchElementException& ) 234 { 235 } 236 catch ( WrappedTargetException& ) 237 { 238 } 239 } 240 241 // We have to map commands which uses special characters like '/',':','?','\','<'.'>','|' 242 String aExt = String::CreateFromAscii( IMAGE_EXTENSION ); 243 m_aImageCommandNameVector.resize(aCmdImageSeq.getLength() ); 244 m_aImageNameVector.resize( aCmdImageSeq.getLength() ); 245 246 ::std::copy( aCmdImageSeq.getConstArray(), 247 aCmdImageSeq.getConstArray()+aCmdImageSeq.getLength(), 248 m_aImageCommandNameVector.begin() ); 249 250 // Create a image name vector that must be provided to the vcl imagelist. We also need 251 // a command to image name map to speed up access time for image retrieval. 252 OUString aUNOString( RTL_CONSTASCII_USTRINGPARAM( ".uno:" )); 253 String aEmptyString; 254 const sal_uInt32 nCount = m_aImageCommandNameVector.size(); 255 for ( sal_uInt32 i = 0; i < nCount; i++ ) 256 { 257 OUString aCommandName( m_aImageCommandNameVector[i] ); 258 String aImageName; 259 260 if ( aCommandName.indexOf( aUNOString ) != 0 ) 261 { 262 INetURLObject aUrlObject( aCommandName, INetURLObject::ENCODE_ALL ); 263 aImageName = aUrlObject.GetURLPath(); 264 aImageName = getCanonicalName( aImageName ); // convert to valid filename 265 } 266 else 267 { 268 // just remove the schema 269 if ( aCommandName.getLength() > 5 ) 270 aImageName = aCommandName.copy( 5 ); 271 else 272 aImageName = aEmptyString; 273 274 // Search for query part. 275 sal_Int32 nIndex = aImageName.Search( '?' ); 276 if ( nIndex != STRING_NOTFOUND ) 277 aImageName = getCanonicalName( aImageName ); // convert to valid filename 278 } 279 // Image names are not case-dependent. Always use lower case characters to 280 // reflect this. 281 aImageName += aExt; 282 aImageName.ToLowerAscii(); 283 284 m_aImageNameVector[i] = aImageName; 285 m_aCommandToImageNameMap.insert( CommandToImageNameMap::value_type( aCommandName, aImageName )); 286 } 287 288 m_bVectorInit = sal_True; 289 } 290 } 291 292 ImageList* CmdImageList::impl_getImageList( sal_Int16 nImageType ) 293 { 294 SvtMiscOptions aMiscOptions; 295 296 sal_Int16 nSymbolsStyle = aMiscOptions.GetCurrentSymbolsStyle(); 297 if ( nSymbolsStyle != m_nSymbolsStyle ) 298 { 299 m_nSymbolsStyle = nSymbolsStyle; 300 for ( sal_Int32 n=0; n < ImageType_COUNT; n++ ) 301 delete m_pImageList[n], m_pImageList[n] = NULL; 302 } 303 304 if ( !m_pImageList[nImageType] ) 305 { 306 m_pImageList[nImageType] = new ImageList( m_aImageNameVector, 307 OUString::createFromAscii( ImageType_Prefixes[nImageType] ) ); 308 } 309 310 return m_pImageList[nImageType]; 311 } 312 313 std::vector< ::rtl::OUString >& CmdImageList::impl_getImageNameVector() 314 { 315 return m_aImageNameVector; 316 } 317 318 std::vector< rtl::OUString >& CmdImageList::impl_getImageCommandNameVector() 319 { 320 return m_aImageCommandNameVector; 321 } 322 323 Image CmdImageList::getImageFromCommandURL( sal_Int16 nImageType, const rtl::OUString& rCommandURL ) 324 { 325 impl_fillCommandToImageNameMap(); 326 CommandToImageNameMap::const_iterator pIter = m_aCommandToImageNameMap.find( rCommandURL ); 327 if ( pIter != m_aCommandToImageNameMap.end() ) 328 { 329 ImageList* pImageList = impl_getImageList( nImageType ); 330 return pImageList->GetImage( pIter->second ); 331 } 332 333 return Image(); 334 } 335 336 bool CmdImageList::hasImage( sal_Int16 /*nImageType*/, const rtl::OUString& rCommandURL ) 337 { 338 impl_fillCommandToImageNameMap(); 339 CommandToImageNameMap::const_iterator pIter = m_aCommandToImageNameMap.find( rCommandURL ); 340 if ( pIter != m_aCommandToImageNameMap.end() ) 341 return true; 342 else 343 return false; 344 } 345 346 ::std::vector< rtl::OUString >& CmdImageList::getImageNames() 347 { 348 return impl_getImageNameVector(); 349 } 350 351 ::std::vector< rtl::OUString >& CmdImageList::getImageCommandNames() 352 { 353 return impl_getImageCommandNameVector(); 354 } 355 356 //_________________________________________________________________________________________________________________ 357 358 GlobalImageList::GlobalImageList( const uno::Reference< XMultiServiceFactory >& rServiceManager ) : 359 CmdImageList( rServiceManager, rtl::OUString() ), 360 m_nRefCount( 0 ) 361 { 362 } 363 364 GlobalImageList::~GlobalImageList() 365 { 366 } 367 368 Image GlobalImageList::getImageFromCommandURL( sal_Int16 nImageType, const rtl::OUString& rCommandURL ) 369 { 370 osl::MutexGuard guard( getGlobalImageListMutex() ); 371 return CmdImageList::getImageFromCommandURL( nImageType, rCommandURL ); 372 } 373 374 bool GlobalImageList::hasImage( sal_Int16 nImageType, const rtl::OUString& rCommandURL ) 375 { 376 osl::MutexGuard guard( getGlobalImageListMutex() ); 377 return CmdImageList::hasImage( nImageType, rCommandURL ); 378 } 379 380 ::std::vector< rtl::OUString >& GlobalImageList::getImageNames() 381 { 382 osl::MutexGuard guard( getGlobalImageListMutex() ); 383 return impl_getImageNameVector(); 384 } 385 386 ::std::vector< rtl::OUString >& GlobalImageList::getImageCommandNames() 387 { 388 osl::MutexGuard guard( getGlobalImageListMutex() ); 389 return impl_getImageCommandNameVector(); 390 } 391 392 oslInterlockedCount GlobalImageList::acquire() 393 { 394 osl_incrementInterlockedCount( &m_nRefCount ); 395 return m_nRefCount; 396 } 397 398 oslInterlockedCount GlobalImageList::release() 399 { 400 osl::MutexGuard guard( getGlobalImageListMutex() ); 401 402 if ( !osl_decrementInterlockedCount( &m_nRefCount )) 403 { 404 oslInterlockedCount nCount( m_nRefCount ); 405 // remove global pointer as we destroy the object now 406 pGlobalImageList = 0; 407 delete this; 408 return nCount; 409 } 410 411 return m_nRefCount; 412 } 413 414 static sal_Bool implts_checkAndScaleGraphic( uno::Reference< XGraphic >& rOutGraphic, const uno::Reference< XGraphic >& rInGraphic, sal_Int16 nImageType ) 415 { 416 static Size aNormSize( IMAGE_SIZE_NORMAL, IMAGE_SIZE_NORMAL ); 417 static Size aLargeSize( IMAGE_SIZE_LARGE, IMAGE_SIZE_LARGE ); 418 419 if ( !rInGraphic.is() ) 420 { 421 rOutGraphic = Image().GetXGraphic(); 422 return sal_False; 423 } 424 425 // Check size and scale it 426 Image aImage( rInGraphic ); 427 Size aSize = aImage.GetSizePixel(); 428 bool bMustScale( false ); 429 430 if (( nImageType == ImageType_Color_Large ) || 431 ( nImageType == ImageType_HC_Large )) 432 bMustScale = ( aSize != aLargeSize ); 433 else 434 bMustScale = ( aSize != aNormSize ); 435 436 if ( bMustScale ) 437 { 438 BitmapEx aBitmap = aImage.GetBitmapEx(); 439 aBitmap.Scale( aNormSize ); 440 aImage = Image( aBitmap ); 441 rOutGraphic = aImage.GetXGraphic(); 442 } 443 else 444 rOutGraphic = rInGraphic; 445 return sal_True; 446 } 447 448 static sal_Int16 implts_convertImageTypeToIndex( sal_Int16 nImageType ) 449 { 450 sal_Int16 nIndex( 0 ); 451 if ( nImageType & ::com::sun::star::ui::ImageType::SIZE_LARGE ) 452 nIndex += 1; 453 if ( nImageType & ::com::sun::star::ui::ImageType::COLOR_HIGHCONTRAST ) 454 nIndex += 2; 455 return nIndex; 456 } 457 458 ImageList* ImageManagerImpl::implts_getUserImageList( ImageType nImageType ) 459 { 460 ResetableGuard aGuard( m_aLock ); 461 if ( !m_pUserImageList[nImageType] ) 462 implts_loadUserImages( nImageType, m_xUserImageStorage, m_xUserBitmapsStorage ); 463 464 return m_pUserImageList[nImageType]; 465 } 466 467 void ImageManagerImpl::implts_initialize() 468 { 469 // Initialize the top-level structures with the storage data 470 if ( m_xUserConfigStorage.is() ) 471 { 472 long nModes = m_bReadOnly ? ElementModes::READ : ElementModes::READWRITE; 473 474 try 475 { 476 m_xUserImageStorage = m_xUserConfigStorage->openStorageElement( OUString::createFromAscii( IMAGE_FOLDER ), 477 nModes ); 478 if ( m_xUserImageStorage.is() ) 479 { 480 m_xUserBitmapsStorage = m_xUserImageStorage->openStorageElement( OUString::createFromAscii( BITMAPS_FOLDER ), 481 nModes ); 482 } 483 } 484 catch ( com::sun::star::container::NoSuchElementException& ) 485 { 486 } 487 catch ( ::com::sun::star::embed::InvalidStorageException& ) 488 { 489 } 490 catch ( ::com::sun::star::lang::IllegalArgumentException& ) 491 { 492 } 493 catch ( ::com::sun::star::io::IOException& ) 494 { 495 } 496 catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) 497 { 498 } 499 } 500 } 501 502 sal_Bool ImageManagerImpl::implts_loadUserImages( 503 ImageType nImageType, 504 const uno::Reference< XStorage >& xUserImageStorage, 505 const uno::Reference< XStorage >& xUserBitmapsStorage ) 506 { 507 ResetableGuard aGuard( m_aLock ); 508 509 if ( xUserImageStorage.is() && xUserBitmapsStorage.is() ) 510 { 511 try 512 { 513 uno::Reference< XStream > xStream = xUserImageStorage->openStreamElement( rtl::OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ), 514 ElementModes::READ ); 515 uno::Reference< XInputStream > xInputStream = xStream->getInputStream(); 516 517 ImageListsDescriptor aUserImageListInfo; 518 ImagesConfiguration::LoadImages( m_xServiceManager, 519 xInputStream, 520 aUserImageListInfo ); 521 if (( aUserImageListInfo.pImageList != 0 ) && 522 ( aUserImageListInfo.pImageList->Count() > 0 )) 523 { 524 ImageListItemDescriptor* pList = aUserImageListInfo.pImageList->GetObject(0); 525 sal_Int32 nCount = pList->pImageItemList->Count(); 526 std::vector< OUString > aUserImagesVector; 527 aUserImagesVector.reserve(nCount); 528 for ( sal_uInt16 i=0; i < nCount; i++ ) 529 { 530 const ImageItemDescriptor* pItem = pList->pImageItemList->GetObject(i); 531 aUserImagesVector.push_back( pItem->aCommandURL ); 532 } 533 534 uno::Reference< XStream > xBitmapStream = xUserBitmapsStorage->openStreamElement( 535 rtl::OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ), 536 ElementModes::READ ); 537 538 if ( xBitmapStream.is() ) 539 { 540 SvStream* pSvStream( 0 ); 541 BitmapEx aUserBitmap; 542 { 543 pSvStream = utl::UcbStreamHelper::CreateStream( xBitmapStream ); 544 vcl::PNGReader aPngReader( *pSvStream ); 545 aUserBitmap = aPngReader.Read(); 546 } 547 delete pSvStream; 548 549 // Delete old image list and create a new one from the read bitmap 550 delete m_pUserImageList[nImageType]; 551 m_pUserImageList[nImageType] = new ImageList(); 552 m_pUserImageList[nImageType]->InsertFromHorizontalStrip 553 ( aUserBitmap, aUserImagesVector ); 554 return sal_True; 555 } 556 } 557 } 558 catch ( com::sun::star::container::NoSuchElementException& ) 559 { 560 } 561 catch ( ::com::sun::star::embed::InvalidStorageException& ) 562 { 563 } 564 catch ( ::com::sun::star::lang::IllegalArgumentException& ) 565 { 566 } 567 catch ( ::com::sun::star::io::IOException& ) 568 { 569 } 570 catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) 571 { 572 } 573 } 574 575 // Destroy old image list - create a new empty one 576 delete m_pUserImageList[nImageType]; 577 m_pUserImageList[nImageType] = new ImageList; 578 579 return sal_True; 580 } 581 582 sal_Bool ImageManagerImpl::implts_storeUserImages( 583 ImageType nImageType, 584 const uno::Reference< XStorage >& xUserImageStorage, 585 const uno::Reference< XStorage >& xUserBitmapsStorage ) 586 { 587 ResetableGuard aGuard( m_aLock ); 588 589 if ( m_bModified ) 590 { 591 ImageList* pImageList = implts_getUserImageList( nImageType ); 592 if ( pImageList->GetImageCount() > 0 ) 593 { 594 ImageListsDescriptor aUserImageListInfo; 595 aUserImageListInfo.pImageList = new ImageListDescriptor; 596 597 ImageListItemDescriptor* pList = new ImageListItemDescriptor; 598 aUserImageListInfo.pImageList->Insert( pList, 0 ); 599 600 pList->pImageItemList = new ImageItemListDescriptor; 601 for ( sal_uInt16 i=0; i < pImageList->GetImageCount(); i++ ) 602 { 603 ImageItemDescriptor* pItem = new ::framework::ImageItemDescriptor; 604 605 pItem->nIndex = i; 606 pItem->aCommandURL = pImageList->GetImageName( i ); 607 pList->pImageItemList->Insert( pItem, pList->pImageItemList->Count() ); 608 } 609 610 pList->aURL = String::CreateFromAscii("Bitmaps/"); 611 pList->aURL += String::CreateFromAscii( BITMAP_FILE_NAMES[nImageType] ); 612 613 uno::Reference< XTransactedObject > xTransaction; 614 uno::Reference< XOutputStream > xOutputStream; 615 uno::Reference< XStream > xStream = xUserImageStorage->openStreamElement( rtl::OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ), 616 ElementModes::WRITE|ElementModes::TRUNCATE ); 617 if ( xStream.is() ) 618 { 619 uno::Reference< XStream > xBitmapStream = 620 xUserBitmapsStorage->openStreamElement( rtl::OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ), 621 ElementModes::WRITE|ElementModes::TRUNCATE ); 622 if ( xBitmapStream.is() ) 623 { 624 SvStream* pSvStream = utl::UcbStreamHelper::CreateStream( xBitmapStream ); 625 { 626 vcl::PNGWriter aPngWriter( pImageList->GetAsHorizontalStrip() ); 627 aPngWriter.Write( *pSvStream ); 628 } 629 delete pSvStream; 630 631 // Commit user bitmaps storage 632 xTransaction = uno::Reference< XTransactedObject >( xUserBitmapsStorage, UNO_QUERY ); 633 if ( xTransaction.is() ) 634 xTransaction->commit(); 635 } 636 637 xOutputStream = xStream->getOutputStream(); 638 if ( xOutputStream.is() ) 639 ImagesConfiguration::StoreImages( m_xServiceManager, xOutputStream, aUserImageListInfo ); 640 641 // Commit user image storage 642 xTransaction = uno::Reference< XTransactedObject >( xUserImageStorage, UNO_QUERY ); 643 if ( xTransaction.is() ) 644 xTransaction->commit(); 645 } 646 647 return sal_True; 648 } 649 else 650 { 651 // Remove the streams from the storage, if we have no data. We have to catch 652 // the NoSuchElementException as it can be possible that there is no stream at all! 653 try 654 { 655 xUserImageStorage->removeElement( rtl::OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] )); 656 } 657 catch ( ::com::sun::star::container::NoSuchElementException& ) 658 { 659 } 660 661 try 662 { 663 xUserBitmapsStorage->removeElement( rtl::OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] )); 664 } 665 catch ( ::com::sun::star::container::NoSuchElementException& ) 666 { 667 } 668 669 uno::Reference< XTransactedObject > xTransaction; 670 671 // Commit user image storage 672 xTransaction = uno::Reference< XTransactedObject >( xUserImageStorage, UNO_QUERY ); 673 if ( xTransaction.is() ) 674 xTransaction->commit(); 675 676 // Commit user bitmaps storage 677 xTransaction = uno::Reference< XTransactedObject >( xUserBitmapsStorage, UNO_QUERY ); 678 if ( xTransaction.is() ) 679 xTransaction->commit(); 680 681 return sal_True; 682 } 683 } 684 685 return sal_False; 686 } 687 const rtl::Reference< GlobalImageList >& ImageManagerImpl::implts_getGlobalImageList() 688 { 689 ResetableGuard aGuard( m_aLock ); 690 691 if ( !m_pGlobalImageList.is() ) 692 m_pGlobalImageList = getGlobalImageList( m_xServiceManager ); 693 return m_pGlobalImageList; 694 } 695 696 CmdImageList* ImageManagerImpl::implts_getDefaultImageList() 697 { 698 ResetableGuard aGuard( m_aLock ); 699 700 if ( !m_pDefaultImageList ) 701 m_pDefaultImageList = new CmdImageList( m_xServiceManager, m_aModuleIdentifier ); 702 703 return m_pDefaultImageList; 704 } 705 706 ImageManagerImpl::ImageManagerImpl( const uno::Reference< XMultiServiceFactory >& xServiceManager,const uno::Reference< XInterface >& _xOwner,bool _bUseGlobal ) : 707 ThreadHelpBase( &Application::GetSolarMutex() ) 708 , m_xServiceManager( xServiceManager ) 709 , m_xOwner(_xOwner) 710 , m_pDefaultImageList( 0 ) 711 , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" )) 712 , m_aResourceString( RTL_CONSTASCII_USTRINGPARAM( ModuleImageList )) 713 , m_aListenerContainer( m_aLock.getShareableOslMutex() ) 714 , m_bUseGlobal(_bUseGlobal) 715 , m_bReadOnly( true ) 716 , m_bInitialized( false ) 717 , m_bModified( false ) 718 , m_bConfigRead( false ) 719 , m_bDisposed( false ) 720 { 721 for ( sal_Int32 n=0; n < ImageType_COUNT; n++ ) 722 { 723 m_pUserImageList[n] = 0; 724 m_bUserImageListModified[n] = false; 725 } 726 } 727 728 ImageManagerImpl::~ImageManagerImpl() 729 { 730 clear(); 731 } 732 733 void ImageManagerImpl::dispose() 734 { 735 css::lang::EventObject aEvent( m_xOwner ); 736 m_aListenerContainer.disposeAndClear( aEvent ); 737 738 { 739 ResetableGuard aGuard( m_aLock ); 740 m_xUserConfigStorage.clear(); 741 m_xUserImageStorage.clear(); 742 m_xUserRootCommit.clear(); 743 m_bConfigRead = false; 744 m_bModified = false; 745 m_bDisposed = true; 746 747 // delete user and default image list on dispose 748 for ( sal_Int32 n=0; n < ImageType_COUNT; n++ ) 749 { 750 delete m_pUserImageList[n]; 751 m_pUserImageList[n] = 0; 752 } 753 delete m_pDefaultImageList; 754 m_pDefaultImageList = 0; 755 } 756 757 } 758 void ImageManagerImpl::addEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) 759 { 760 { 761 ResetableGuard aGuard( m_aLock ); 762 763 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 764 if ( m_bDisposed ) 765 throw DisposedException(); 766 } 767 768 m_aListenerContainer.addInterface( ::getCppuType( ( const uno::Reference< XEventListener >* ) NULL ), xListener ); 769 } 770 771 void ImageManagerImpl::removeEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) 772 { 773 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 774 m_aListenerContainer.removeInterface( ::getCppuType( ( const uno::Reference< XEventListener >* ) NULL ), xListener ); 775 } 776 777 // XInitialization 778 void ImageManagerImpl::initialize( const Sequence< Any >& aArguments ) 779 { 780 ResetableGuard aLock( m_aLock ); 781 782 if ( !m_bInitialized ) 783 { 784 for ( sal_Int32 n = 0; n < aArguments.getLength(); n++ ) 785 { 786 PropertyValue aPropValue; 787 if ( aArguments[n] >>= aPropValue ) 788 { 789 if ( aPropValue.Name.equalsAscii( "UserConfigStorage" )) 790 { 791 aPropValue.Value >>= m_xUserConfigStorage; 792 } 793 else if ( aPropValue.Name.equalsAscii( "ModuleIdentifier" )) 794 { 795 aPropValue.Value >>= m_aModuleIdentifier; 796 } 797 else if ( aPropValue.Name.equalsAscii( "UserRootCommit" )) 798 { 799 aPropValue.Value >>= m_xUserRootCommit; 800 } 801 } 802 } 803 804 if ( m_xUserConfigStorage.is() ) 805 { 806 uno::Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY ); 807 if ( xPropSet.is() ) 808 { 809 long nOpenMode = 0; 810 if ( xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ))) >>= nOpenMode ) 811 m_bReadOnly = !( nOpenMode & ElementModes::WRITE ); 812 } 813 } 814 815 implts_initialize(); 816 817 m_bInitialized = true; 818 } 819 } 820 821 // XImageManagerImpl 822 void ImageManagerImpl::reset() 823 throw (::com::sun::star::uno::RuntimeException) 824 { 825 ResetableGuard aLock( m_aLock ); 826 827 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 828 if ( m_bDisposed ) 829 throw DisposedException(); 830 831 std::vector< OUString > aUserImageNames; 832 833 for ( sal_Int32 i = 0; i < ImageType_COUNT; i++ ) 834 { 835 aUserImageNames.clear(); 836 ImageList* pImageList = implts_getUserImageList( ImageType(i)); 837 pImageList->GetImageNames( aUserImageNames ); 838 839 Sequence< rtl::OUString > aRemoveList( aUserImageNames.size() ); 840 const sal_uInt32 nCount = aUserImageNames.size(); 841 for ( sal_uInt32 j = 0; j < nCount; j++ ) 842 aRemoveList[j] = aUserImageNames[j]; 843 844 // Remove images 845 removeImages( sal_Int16( i ), aRemoveList ); 846 m_bUserImageListModified[i] = true; 847 } 848 849 m_bModified = sal_True; 850 } 851 852 Sequence< ::rtl::OUString > ImageManagerImpl::getAllImageNames( ::sal_Int16 nImageType ) 853 throw (::com::sun::star::uno::RuntimeException) 854 { 855 ResetableGuard aLock( m_aLock ); 856 857 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 858 if ( m_bDisposed ) 859 throw DisposedException(); 860 861 ImageNameMap aImageCmdNameMap; 862 863 sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType ); 864 865 sal_uInt32 i( 0 ); 866 if ( m_bUseGlobal ) 867 { 868 rtl::Reference< GlobalImageList > rGlobalImageList = implts_getGlobalImageList(); 869 870 const std::vector< OUString >& rGlobalImageNameVector = rGlobalImageList->getImageCommandNames(); 871 const sal_uInt32 nGlobalCount = rGlobalImageNameVector.size(); 872 for ( i = 0; i < nGlobalCount; i++ ) 873 aImageCmdNameMap.insert( ImageNameMap::value_type( rGlobalImageNameVector[i], sal_True )); 874 875 const std::vector< OUString >& rModuleImageNameVector = implts_getDefaultImageList()->getImageCommandNames(); 876 const sal_uInt32 nModuleCount = rModuleImageNameVector.size(); 877 for ( i = 0; i < nModuleCount; i++ ) 878 aImageCmdNameMap.insert( ImageNameMap::value_type( rModuleImageNameVector[i], sal_True )); 879 } 880 881 ImageList* pImageList = implts_getUserImageList( ImageType( nIndex )); 882 std::vector< OUString > rUserImageNames; 883 pImageList->GetImageNames( rUserImageNames ); 884 const sal_uInt32 nUserCount = rUserImageNames.size(); 885 for ( i = 0; i < nUserCount; i++ ) 886 aImageCmdNameMap.insert( ImageNameMap::value_type( rUserImageNames[i], sal_True )); 887 888 Sequence< OUString > aImageNameSeq( aImageCmdNameMap.size() ); 889 ImageNameMap::const_iterator pIter; 890 i = 0; 891 for ( pIter = aImageCmdNameMap.begin(); pIter != aImageCmdNameMap.end(); pIter++ ) 892 aImageNameSeq[i++] = pIter->first; 893 894 return aImageNameSeq; 895 } 896 897 ::sal_Bool ImageManagerImpl::hasImage( ::sal_Int16 nImageType, const ::rtl::OUString& aCommandURL ) 898 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 899 { 900 ResetableGuard aLock( m_aLock ); 901 902 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 903 if ( m_bDisposed ) 904 throw DisposedException(); 905 906 if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE )) 907 throw IllegalArgumentException(); 908 909 sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType ); 910 if ( m_bUseGlobal && implts_getGlobalImageList()->hasImage( nIndex, aCommandURL )) 911 return sal_True; 912 else 913 { 914 if ( m_bUseGlobal && implts_getDefaultImageList()->hasImage( nIndex, aCommandURL )) 915 return sal_True; 916 else 917 { 918 // User layer 919 ImageList* pImageList = implts_getUserImageList( ImageType( nIndex )); 920 if ( pImageList ) 921 return ( pImageList->GetImagePos( aCommandURL ) != IMAGELIST_IMAGE_NOTFOUND ); 922 } 923 } 924 925 return sal_False; 926 } 927 928 Sequence< uno::Reference< XGraphic > > ImageManagerImpl::getImages( 929 ::sal_Int16 nImageType, 930 const Sequence< ::rtl::OUString >& aCommandURLSequence ) 931 throw ( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ) 932 { 933 ResetableGuard aLock( m_aLock ); 934 935 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 936 if ( m_bDisposed ) 937 throw DisposedException(); 938 939 if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE )) 940 throw IllegalArgumentException(); 941 942 Sequence< uno::Reference< XGraphic > > aGraphSeq( aCommandURLSequence.getLength() ); 943 944 const rtl::OUString* aStrArray = aCommandURLSequence.getConstArray(); 945 946 sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType ); 947 rtl::Reference< GlobalImageList > rGlobalImageList; 948 CmdImageList* pDefaultImageList = NULL; 949 if ( m_bUseGlobal ) 950 { 951 rGlobalImageList = implts_getGlobalImageList(); 952 pDefaultImageList = implts_getDefaultImageList(); 953 } 954 ImageList* pUserImageList = implts_getUserImageList( ImageType( nIndex )); 955 956 // We have to search our image list in the following order: 957 // 1. user image list (read/write) 958 // 2. module image list (read) 959 // 3. global image list (read) 960 for ( sal_Int32 n = 0; n < aCommandURLSequence.getLength(); n++ ) 961 { 962 Image aImage = pUserImageList->GetImage( aStrArray[n] ); 963 if ( !aImage && m_bUseGlobal ) 964 { 965 aImage = pDefaultImageList->getImageFromCommandURL( nIndex, aStrArray[n] ); 966 if ( !aImage ) 967 aImage = rGlobalImageList->getImageFromCommandURL( nIndex, aStrArray[n] ); 968 } 969 970 aGraphSeq[n] = aImage.GetXGraphic(); 971 } 972 973 return aGraphSeq; 974 } 975 976 void ImageManagerImpl::replaceImages( 977 ::sal_Int16 nImageType, 978 const Sequence< ::rtl::OUString >& aCommandURLSequence, 979 const Sequence< uno::Reference< XGraphic > >& aGraphicsSequence ) 980 throw ( ::com::sun::star::lang::IllegalArgumentException, 981 ::com::sun::star::lang::IllegalAccessException, 982 ::com::sun::star::uno::RuntimeException) 983 { 984 CmdToXGraphicNameAccess* pInsertedImages( 0 ); 985 CmdToXGraphicNameAccess* pReplacedImages( 0 ); 986 987 { 988 ResetableGuard aLock( m_aLock ); 989 990 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 991 if ( m_bDisposed ) 992 throw DisposedException(); 993 994 if (( aCommandURLSequence.getLength() != aGraphicsSequence.getLength() ) || 995 (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE ))) 996 throw IllegalArgumentException(); 997 998 if ( m_bReadOnly ) 999 throw IllegalAccessException(); 1000 1001 sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType ); 1002 ImageList* pImageList = implts_getUserImageList( ImageType( nIndex )); 1003 1004 uno::Reference< XGraphic > xGraphic; 1005 for ( sal_Int32 i = 0; i < aCommandURLSequence.getLength(); i++ ) 1006 { 1007 // Check size and scale. If we don't have any graphics ignore it 1008 if ( !implts_checkAndScaleGraphic( xGraphic, aGraphicsSequence[i], nIndex )) 1009 continue; 1010 1011 sal_uInt16 nPos = pImageList->GetImagePos( aCommandURLSequence[i] ); 1012 if ( nPos == IMAGELIST_IMAGE_NOTFOUND ) 1013 { 1014 pImageList->AddImage( aCommandURLSequence[i], xGraphic ); 1015 if ( !pInsertedImages ) 1016 pInsertedImages = new CmdToXGraphicNameAccess(); 1017 pInsertedImages->addElement( aCommandURLSequence[i], xGraphic ); 1018 } 1019 else 1020 { 1021 pImageList->ReplaceImage( aCommandURLSequence[i], xGraphic ); 1022 if ( !pReplacedImages ) 1023 pReplacedImages = new CmdToXGraphicNameAccess(); 1024 pReplacedImages->addElement( aCommandURLSequence[i], xGraphic ); 1025 } 1026 } 1027 1028 if (( pInsertedImages != 0 ) || ( pReplacedImages != 0 )) 1029 { 1030 m_bModified = sal_True; 1031 m_bUserImageListModified[nIndex] = true; 1032 } 1033 } 1034 1035 // Notify listeners 1036 if ( pInsertedImages != 0 ) 1037 { 1038 ConfigurationEvent aInsertEvent; 1039 aInsertEvent.aInfo <<= nImageType; 1040 aInsertEvent.Accessor <<= m_xOwner; 1041 aInsertEvent.Source = m_xOwner; 1042 aInsertEvent.ResourceURL = m_aResourceString; 1043 aInsertEvent.Element = uno::makeAny( uno::Reference< XNameAccess >( 1044 static_cast< OWeakObject *>( pInsertedImages ), UNO_QUERY )); 1045 implts_notifyContainerListener( aInsertEvent, NotifyOp_Insert ); 1046 } 1047 if ( pReplacedImages != 0 ) 1048 { 1049 ConfigurationEvent aReplaceEvent; 1050 aReplaceEvent.aInfo <<= nImageType; 1051 aReplaceEvent.Accessor <<= m_xOwner; 1052 aReplaceEvent.Source = m_xOwner; 1053 aReplaceEvent.ResourceURL = m_aResourceString; 1054 aReplaceEvent.ReplacedElement = Any(); 1055 aReplaceEvent.Element = uno::makeAny( uno::Reference< XNameAccess >( 1056 static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY )); 1057 implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace ); 1058 } 1059 } 1060 1061 void ImageManagerImpl::removeImages( ::sal_Int16 nImageType, const Sequence< ::rtl::OUString >& aCommandURLSequence ) 1062 throw ( ::com::sun::star::lang::IllegalArgumentException, 1063 ::com::sun::star::lang::IllegalAccessException, 1064 ::com::sun::star::uno::RuntimeException) 1065 { 1066 CmdToXGraphicNameAccess* pRemovedImages( 0 ); 1067 CmdToXGraphicNameAccess* pReplacedImages( 0 ); 1068 1069 { 1070 ResetableGuard aLock( m_aLock ); 1071 1072 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 1073 if ( m_bDisposed ) 1074 throw DisposedException(); 1075 1076 if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE )) 1077 throw IllegalArgumentException(); 1078 1079 if ( m_bReadOnly ) 1080 throw IllegalAccessException(); 1081 1082 sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType ); 1083 rtl::Reference< GlobalImageList > rGlobalImageList; 1084 CmdImageList* pDefaultImageList = NULL; 1085 if ( m_bUseGlobal ) 1086 { 1087 rGlobalImageList = implts_getGlobalImageList(); 1088 pDefaultImageList = implts_getDefaultImageList(); 1089 } 1090 ImageList* pImageList = implts_getUserImageList( ImageType( nIndex )); 1091 uno::Reference< XGraphic > xEmptyGraphic( Image().GetXGraphic() ); 1092 1093 for ( sal_Int32 i = 0; i < aCommandURLSequence.getLength(); i++ ) 1094 { 1095 sal_uInt16 nPos = pImageList->GetImagePos( aCommandURLSequence[i] ); 1096 if ( nPos != IMAGELIST_IMAGE_NOTFOUND ) 1097 { 1098 Image aImage = pImageList->GetImage( nPos ); 1099 sal_uInt16 nId = pImageList->GetImageId( nPos ); 1100 pImageList->RemoveImage( nId ); 1101 1102 if ( m_bUseGlobal ) 1103 { 1104 // Check, if we have a image in our module/global image list. If we find one => 1105 // this is a replace instead of a remove operation! 1106 Image aNewImage = pDefaultImageList->getImageFromCommandURL( nIndex, aCommandURLSequence[i] ); 1107 if ( !aNewImage ) 1108 aNewImage = rGlobalImageList->getImageFromCommandURL( nIndex, aCommandURLSequence[i] ); 1109 if ( !aNewImage ) 1110 { 1111 if ( !pRemovedImages ) 1112 pRemovedImages = new CmdToXGraphicNameAccess(); 1113 pRemovedImages->addElement( aCommandURLSequence[i], xEmptyGraphic ); 1114 } 1115 else 1116 { 1117 if ( !pReplacedImages ) 1118 pReplacedImages = new CmdToXGraphicNameAccess(); 1119 pReplacedImages->addElement( aCommandURLSequence[i], aNewImage.GetXGraphic() ); 1120 } 1121 } // if ( m_bUseGlobal ) 1122 else 1123 { 1124 if ( !pRemovedImages ) 1125 pRemovedImages = new CmdToXGraphicNameAccess(); 1126 pRemovedImages->addElement( aCommandURLSequence[i], xEmptyGraphic ); 1127 } 1128 } 1129 } 1130 1131 if (( pReplacedImages != 0 ) || ( pRemovedImages != 0 )) 1132 { 1133 m_bModified = sal_True; 1134 m_bUserImageListModified[nIndex] = true; 1135 } 1136 } 1137 1138 // Notify listeners 1139 if ( pRemovedImages != 0 ) 1140 { 1141 ConfigurationEvent aRemoveEvent; 1142 aRemoveEvent.aInfo = uno::makeAny( nImageType ); 1143 aRemoveEvent.Accessor = uno::makeAny( m_xOwner ); 1144 aRemoveEvent.Source = m_xOwner; 1145 aRemoveEvent.ResourceURL = m_aResourceString; 1146 aRemoveEvent.Element = uno::makeAny( uno::Reference< XNameAccess >( 1147 static_cast< OWeakObject *>( pRemovedImages ), UNO_QUERY )); 1148 implts_notifyContainerListener( aRemoveEvent, NotifyOp_Remove ); 1149 } 1150 if ( pReplacedImages != 0 ) 1151 { 1152 ConfigurationEvent aReplaceEvent; 1153 aReplaceEvent.aInfo = uno::makeAny( nImageType ); 1154 aReplaceEvent.Accessor = uno::makeAny( m_xOwner ); 1155 aReplaceEvent.Source = m_xOwner; 1156 aReplaceEvent.ResourceURL = m_aResourceString; 1157 aReplaceEvent.ReplacedElement = Any(); 1158 aReplaceEvent.Element = uno::makeAny( uno::Reference< XNameAccess >( 1159 static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY )); 1160 implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace ); 1161 } 1162 } 1163 1164 void ImageManagerImpl::insertImages( ::sal_Int16 nImageType, const Sequence< ::rtl::OUString >& aCommandURLSequence, const Sequence< uno::Reference< XGraphic > >& aGraphicSequence ) 1165 throw ( ::com::sun::star::container::ElementExistException, 1166 ::com::sun::star::lang::IllegalArgumentException, 1167 ::com::sun::star::lang::IllegalAccessException, 1168 ::com::sun::star::uno::RuntimeException) 1169 { 1170 replaceImages(nImageType,aCommandURLSequence,aGraphicSequence); 1171 } 1172 1173 1174 // XUIConfigurationPersistence 1175 void ImageManagerImpl::reload() 1176 throw ( ::com::sun::star::uno::Exception, 1177 ::com::sun::star::uno::RuntimeException ) 1178 { 1179 ResetableGuard aGuard( m_aLock ); 1180 1181 if ( m_bDisposed ) 1182 throw DisposedException(); 1183 1184 CommandMap aOldUserCmdImageSet; 1185 std::vector< rtl::OUString > aNewUserCmdImageSet; 1186 1187 if ( m_bModified ) 1188 { 1189 for ( sal_Int16 i = 0; i < sal_Int16( ImageType_COUNT ); i++ ) 1190 { 1191 if ( !m_bDisposed && m_bUserImageListModified[i] ) 1192 { 1193 std::vector< rtl::OUString > aOldUserCmdImageVector; 1194 ImageList* pImageList = implts_getUserImageList( (ImageType)i ); 1195 pImageList->GetImageNames( aOldUserCmdImageVector ); 1196 1197 // Fill hash map to speed up search afterwards 1198 sal_uInt32 j( 0 ); 1199 const sal_uInt32 nOldCount = aOldUserCmdImageVector.size(); 1200 for ( j = 0; j < nOldCount; j++ ) 1201 aOldUserCmdImageSet.insert( CommandMap::value_type( aOldUserCmdImageVector[j], false )); 1202 1203 // Attention: This can make the old image list pointer invalid! 1204 implts_loadUserImages( (ImageType)i, m_xUserImageStorage, m_xUserBitmapsStorage ); 1205 pImageList = implts_getUserImageList( (ImageType)i ); 1206 pImageList->GetImageNames( aNewUserCmdImageSet ); 1207 1208 CmdToXGraphicNameAccess* pInsertedImages( 0 ); 1209 CmdToXGraphicNameAccess* pReplacedImages( 0 ); 1210 CmdToXGraphicNameAccess* pRemovedImages( 0 ); 1211 1212 const sal_uInt32 nNewCount = aNewUserCmdImageSet.size(); 1213 for ( j = 0; j < nNewCount; j++ ) 1214 { 1215 CommandMap::iterator pIter = aOldUserCmdImageSet.find( aNewUserCmdImageSet[j] ); 1216 if ( pIter != aOldUserCmdImageSet.end() ) 1217 { 1218 pIter->second = true; // mark entry as replaced 1219 if ( !pReplacedImages ) 1220 pReplacedImages = new CmdToXGraphicNameAccess(); 1221 pReplacedImages->addElement( aNewUserCmdImageSet[j], 1222 pImageList->GetImage( aNewUserCmdImageSet[j] ).GetXGraphic() ); 1223 } 1224 else 1225 { 1226 if ( !pInsertedImages ) 1227 pInsertedImages = new CmdToXGraphicNameAccess(); 1228 pInsertedImages->addElement( aNewUserCmdImageSet[j], 1229 pImageList->GetImage( aNewUserCmdImageSet[j] ).GetXGraphic() ); 1230 } 1231 } 1232 1233 // Search map for unmarked entries => they have been removed from the user list 1234 // through this reload operation. 1235 // We have to search the module and global image list! 1236 rtl::Reference< GlobalImageList > rGlobalImageList; 1237 CmdImageList* pDefaultImageList = NULL; 1238 if ( m_bUseGlobal ) 1239 { 1240 rGlobalImageList = implts_getGlobalImageList(); 1241 pDefaultImageList = implts_getDefaultImageList(); 1242 } 1243 uno::Reference< XGraphic > xEmptyGraphic( Image().GetXGraphic() ); 1244 CommandMap::const_iterator pIter = aOldUserCmdImageSet.begin(); 1245 while ( pIter != aOldUserCmdImageSet.end() ) 1246 { 1247 if ( !pIter->second ) 1248 { 1249 if ( m_bUseGlobal ) 1250 { 1251 Image aImage = pDefaultImageList->getImageFromCommandURL( i, pIter->first ); 1252 if ( !aImage ) 1253 aImage = rGlobalImageList->getImageFromCommandURL( i, pIter->first ); 1254 1255 if ( !aImage ) 1256 { 1257 // No image in the module/global image list => remove user image 1258 if ( !pRemovedImages ) 1259 pRemovedImages = new CmdToXGraphicNameAccess(); 1260 pRemovedImages->addElement( pIter->first, xEmptyGraphic ); 1261 } 1262 else 1263 { 1264 // Image has been found in the module/global image list => replace user image 1265 if ( !pReplacedImages ) 1266 pReplacedImages = new CmdToXGraphicNameAccess(); 1267 pReplacedImages->addElement( pIter->first, aImage.GetXGraphic() ); 1268 } 1269 } // if ( m_bUseGlobal ) 1270 else 1271 { 1272 // No image in the user image list => remove user image 1273 if ( !pRemovedImages ) 1274 pRemovedImages = new CmdToXGraphicNameAccess(); 1275 pRemovedImages->addElement( pIter->first, xEmptyGraphic ); 1276 } 1277 } 1278 ++pIter; 1279 } 1280 1281 aGuard.unlock(); 1282 1283 // Now notify our listeners. Unlock mutex to prevent deadlocks 1284 if ( pInsertedImages != 0 ) 1285 { 1286 ConfigurationEvent aInsertEvent; 1287 aInsertEvent.aInfo = uno::makeAny( i ); 1288 aInsertEvent.Accessor = uno::makeAny( m_xOwner ); 1289 aInsertEvent.Source = m_xOwner; 1290 aInsertEvent.ResourceURL = m_aResourceString; 1291 aInsertEvent.Element = uno::makeAny( uno::Reference< XNameAccess >( 1292 static_cast< OWeakObject *>( pInsertedImages ), UNO_QUERY )); 1293 implts_notifyContainerListener( aInsertEvent, NotifyOp_Insert ); 1294 } 1295 if ( pReplacedImages != 0 ) 1296 { 1297 ConfigurationEvent aReplaceEvent; 1298 aReplaceEvent.aInfo = uno::makeAny( i ); 1299 aReplaceEvent.Accessor = uno::makeAny( m_xOwner ); 1300 aReplaceEvent.Source = m_xOwner; 1301 aReplaceEvent.ResourceURL = m_aResourceString; 1302 aReplaceEvent.ReplacedElement = Any(); 1303 aReplaceEvent.Element = uno::makeAny( uno::Reference< XNameAccess >( 1304 static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY )); 1305 implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace ); 1306 } 1307 if ( pRemovedImages != 0 ) 1308 { 1309 ConfigurationEvent aRemoveEvent; 1310 aRemoveEvent.aInfo = uno::makeAny( i ); 1311 aRemoveEvent.Accessor = uno::makeAny( m_xOwner ); 1312 aRemoveEvent.Source = m_xOwner; 1313 aRemoveEvent.ResourceURL = m_aResourceString; 1314 aRemoveEvent.Element = uno::makeAny( uno::Reference< XNameAccess >( 1315 static_cast< OWeakObject *>( pRemovedImages ), UNO_QUERY )); 1316 implts_notifyContainerListener( aRemoveEvent, NotifyOp_Remove ); 1317 } 1318 1319 aGuard.lock(); 1320 } 1321 } 1322 } 1323 } 1324 1325 void ImageManagerImpl::store() 1326 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 1327 { 1328 ResetableGuard aGuard( m_aLock ); 1329 1330 if ( m_bDisposed ) 1331 throw DisposedException(); 1332 1333 if ( m_bModified ) 1334 { 1335 sal_Bool bWritten( sal_False ); 1336 for ( sal_Int32 i = 0; i < ImageType_COUNT; i++ ) 1337 { 1338 sal_Bool bSuccess = implts_storeUserImages( ImageType(i), m_xUserImageStorage, m_xUserBitmapsStorage ); 1339 if ( bSuccess ) 1340 bWritten = sal_True; 1341 m_bUserImageListModified[i] = false; 1342 } 1343 1344 if ( bWritten && 1345 m_xUserConfigStorage.is() ) 1346 { 1347 uno::Reference< XTransactedObject > xUserConfigStorageCommit( m_xUserConfigStorage, UNO_QUERY ); 1348 if ( xUserConfigStorageCommit.is() ) 1349 xUserConfigStorageCommit->commit(); 1350 if ( m_xUserRootCommit.is() ) 1351 m_xUserRootCommit->commit(); 1352 } 1353 1354 m_bModified = sal_False; 1355 } 1356 } 1357 1358 void ImageManagerImpl::storeToStorage( const uno::Reference< XStorage >& Storage ) 1359 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 1360 { 1361 ResetableGuard aGuard( m_aLock ); 1362 1363 if ( m_bDisposed ) 1364 throw DisposedException(); 1365 1366 if ( m_bModified && Storage.is() ) 1367 { 1368 long nModes = ElementModes::READWRITE; 1369 1370 uno::Reference< XStorage > xUserImageStorage = Storage->openStorageElement( OUString::createFromAscii( IMAGE_FOLDER ), 1371 nModes ); 1372 if ( xUserImageStorage.is() ) 1373 { 1374 uno::Reference< XStorage > xUserBitmapsStorage = xUserImageStorage->openStorageElement( OUString::createFromAscii( BITMAPS_FOLDER ), 1375 nModes ); 1376 for ( sal_Int32 i = 0; i < ImageType_COUNT; i++ ) 1377 { 1378 implts_getUserImageList( (ImageType)i ); 1379 implts_storeUserImages( (ImageType)i, xUserImageStorage, xUserBitmapsStorage ); 1380 } 1381 1382 uno::Reference< XTransactedObject > xTransaction( Storage, UNO_QUERY ); 1383 if ( xTransaction.is() ) 1384 xTransaction->commit(); 1385 } 1386 } 1387 } 1388 1389 sal_Bool ImageManagerImpl::isModified() 1390 throw (::com::sun::star::uno::RuntimeException) 1391 { 1392 ResetableGuard aGuard( m_aLock ); 1393 return m_bModified; 1394 } 1395 1396 sal_Bool ImageManagerImpl::isReadOnly() throw (::com::sun::star::uno::RuntimeException) 1397 { 1398 ResetableGuard aGuard( m_aLock ); 1399 return m_bReadOnly; 1400 } 1401 // XUIConfiguration 1402 void ImageManagerImpl::addConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) 1403 throw (::com::sun::star::uno::RuntimeException) 1404 { 1405 { 1406 ResetableGuard aGuard( m_aLock ); 1407 1408 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 1409 if ( m_bDisposed ) 1410 throw DisposedException(); 1411 } 1412 1413 m_aListenerContainer.addInterface( ::getCppuType( ( const uno::Reference< XUIConfigurationListener >* ) NULL ), xListener ); 1414 } 1415 1416 void ImageManagerImpl::removeConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) 1417 throw (::com::sun::star::uno::RuntimeException) 1418 { 1419 /* SAFE AREA ----------------------------------------------------------------------------------------------- */ 1420 m_aListenerContainer.removeInterface( ::getCppuType( ( const uno::Reference< XUIConfigurationListener >* ) NULL ), xListener ); 1421 } 1422 1423 1424 void ImageManagerImpl::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp ) 1425 { 1426 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( 1427 ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) ); 1428 if ( pContainer != NULL ) 1429 { 1430 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); 1431 while ( pIterator.hasMoreElements() ) 1432 { 1433 try 1434 { 1435 switch ( eOp ) 1436 { 1437 case NotifyOp_Replace: 1438 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent ); 1439 break; 1440 case NotifyOp_Insert: 1441 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent ); 1442 break; 1443 case NotifyOp_Remove: 1444 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent ); 1445 break; 1446 } 1447 } 1448 catch( css::uno::RuntimeException& ) 1449 { 1450 pIterator.remove(); 1451 } 1452 } 1453 } 1454 } 1455 void ImageManagerImpl::clear() 1456 { 1457 ResetableGuard aGuard( m_aLock ); 1458 for ( sal_Int32 n = 0; n < ImageType_COUNT; n++ ) 1459 { 1460 delete m_pUserImageList[n]; 1461 m_pUserImageList[n] = 0; 1462 } 1463 } 1464 } // namespace framework 1465