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