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