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