xref: /AOO41X/main/svx/source/gallery2/gallery1.cxx (revision d5370dc8b91641fa460c79c207c7018af41d7460)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #define ENABLE_BYTESTRING_STREAM_OPERATORS
28 
29 #include <tools/vcompat.hxx>
30 #include <ucbhelper/content.hxx>
31 #include <unotools/ucbstreamhelper.hxx>
32 #include <unotools/pathoptions.hxx>
33 #include <sfx2/docfile.hxx>
34 #include "svx/gallery.hxx"
35 #include "gallery.hrc"
36 #include "svx/galmisc.hxx"
37 #include "svx/galtheme.hxx"
38 #include "svx/gallery1.hxx"
39 #include <com/sun/star/sdbc/XResultSet.hpp>
40 #include <com/sun/star/ucb/XContentAccess.hpp>
41 
42 #define ENABLE_BYTESTRING_STREAM_OPERATORS
43 
44 // --------------
45 // - Namespaces -
46 // --------------
47 
48 using namespace ::rtl;
49 using namespace ::com::sun::star;
50 
51 // ---------------------
52 // - GalleryThemeEntry -
53 // ---------------------
54 
55 GalleryThemeEntry::GalleryThemeEntry( const INetURLObject& rBaseURL, const String& rName,
56 									  sal_uInt32 _nFileNumber, sal_Bool _bReadOnly, sal_Bool _bImported,
57 									  sal_Bool _bNewFile, sal_uInt32 _nId, sal_Bool _bThemeNameFromResource ) :
58 		nFileNumber                             ( _nFileNumber ),
59 		nId                                     ( _nId ),
60 		bReadOnly                               ( _bReadOnly || _bImported ),
61 		bImported                               ( _bImported ),
62 		bThemeNameFromResource  ( _bThemeNameFromResource )
63 {
64 	INetURLObject aURL( rBaseURL );
65 	DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
66 	String aFileName( String( RTL_CONSTASCII_USTRINGPARAM( "sg" ) ) );
67 
68 	aURL.Append( ( aFileName += String::CreateFromInt32( nFileNumber ) ) += String( RTL_CONSTASCII_USTRINGPARAM( ".thm" ) ) );
69 	aThmURL = ImplGetURLIgnoreCase( aURL );
70 
71 	aURL.setExtension( String( RTL_CONSTASCII_USTRINGPARAM( "sdg" ) ) );
72 	aSdgURL = ImplGetURLIgnoreCase( aURL );
73 
74 	aURL.setExtension( String( RTL_CONSTASCII_USTRINGPARAM( "sdv" ) ) );
75 	aSdvURL = ImplGetURLIgnoreCase( aURL );
76 
77 	SetModified( _bNewFile );
78 
79 	if( nId && bThemeNameFromResource )
80     {
81         const ResId aId (GAL_RESID( RID_GALLERYSTR_THEME_START + (sal_uInt16) nId));
82         if (aId.GetpResource() == NULL)
83             OSL_TRACE("");
84         aName = String(aId);
85     }
86 
87 	if( !aName.Len() )
88 		aName = rName;
89 }
90 
91 // -----------------------------------------------------------------------------
92 
93 INetURLObject GalleryThemeEntry::ImplGetURLIgnoreCase( const INetURLObject& rURL ) const
94 {
95 	INetURLObject	aURL( rURL );
96 	String			aFileName;
97 	sal_Bool			bExists = sal_False;
98 
99 	// check original file name
100 	if( FileExists( aURL ) )
101 		bExists = sal_True;
102 	else
103 	{
104 		// check upper case file name
105 		aURL.setName( aURL.getName().toAsciiUpperCase() );
106 
107 		if( FileExists( aURL ) )
108 			bExists = sal_True;
109 		else
110 		{
111 			// check lower case file name
112 			aURL.setName( aURL.getName().toAsciiLowerCase() );
113 
114 			if( FileExists( aURL ) )
115 				bExists = sal_True;
116 		}
117 	}
118 
119 	return aURL;
120 }
121 
122 // -----------------------------------------------------------------------------
123 
124 void GalleryThemeEntry::SetName( const String& rNewName )
125 {
126 	if( aName != rNewName )
127 	{
128 		aName = rNewName;
129 		SetModified( sal_True );
130 		bThemeNameFromResource = sal_False;
131 	}
132 }
133 
134 // -----------------------------------------------------------------------------
135 
136 void GalleryThemeEntry::SetId( sal_uInt32 nNewId, sal_Bool bResetThemeName )
137 {
138 	nId = nNewId;
139 	SetModified( sal_True );
140 	bThemeNameFromResource = ( nId && bResetThemeName );
141 }
142 
143 // ---------------------------
144 // - GalleryImportThemeEntry -
145 // ---------------------------
146 
147 SvStream& operator<<( SvStream& rOut, const GalleryImportThemeEntry& rEntry )
148 {
149 	ByteString aDummy;
150 
151 	rOut << ByteString( rEntry.aThemeName, RTL_TEXTENCODING_UTF8 ) <<
152 			ByteString( rEntry.aUIName, RTL_TEXTENCODING_UTF8 ) <<
153 			ByteString( String(rEntry.aURL.GetMainURL( INetURLObject::NO_DECODE )), RTL_TEXTENCODING_UTF8 ) <<
154 			ByteString( rEntry.aImportName, RTL_TEXTENCODING_UTF8 ) <<
155 			aDummy;
156 
157 	return rOut;
158 }
159 
160 // ------------------------------------------------------------------------
161 
162 SvStream& operator>>( SvStream& rIn, GalleryImportThemeEntry& rEntry )
163 {
164 	ByteString aTmpStr;
165 
166 	rIn >> aTmpStr; rEntry.aThemeName = String( aTmpStr, RTL_TEXTENCODING_UTF8 );
167 	rIn >> aTmpStr; rEntry.aUIName = String( aTmpStr, RTL_TEXTENCODING_UTF8 );
168 	rIn >> aTmpStr; rEntry.aURL = INetURLObject( String( aTmpStr, RTL_TEXTENCODING_UTF8 ) );
169 	rIn >> aTmpStr; rEntry.aImportName = String( aTmpStr, RTL_TEXTENCODING_UTF8 );
170 	rIn >> aTmpStr;
171 
172 	return rIn;
173 }
174 
175 // --------------------------
176 // - GalleryThemeCacheEntry -
177 // --------------------------
178 
179 class GalleryThemeCacheEntry;
180 DBG_NAME(GalleryThemeCacheEntry)
181 class GalleryThemeCacheEntry
182 {
183 private:
184 
185 	const GalleryThemeEntry*        mpThemeEntry;
186 	GalleryTheme*                           mpTheme;
187 
188 public:
189 
190 								GalleryThemeCacheEntry( const GalleryThemeEntry* pThemeEntry, GalleryTheme* pTheme ) :
191 									mpThemeEntry( pThemeEntry ), mpTheme( pTheme ) {DBG_CTOR(GalleryThemeCacheEntry,NULL);}
192 								~GalleryThemeCacheEntry() { delete mpTheme;DBG_DTOR(GalleryThemeCacheEntry,NULL); }
193 
194 	const GalleryThemeEntry*        GetThemeEntry() const { return mpThemeEntry; }
195 	GalleryTheme*                           GetTheme() const { return mpTheme; }
196 };
197 
198 // -----------
199 // - Gallery -
200 // -----------
201 Gallery::Gallery( const String& rMultiPath )
202 :		nReadTextEncoding	( gsl_getSystemTextEncoding() )
203 ,		nLastFileNumber		( 0 )
204 ,		bMultiPath			( sal_False )
205 {
206 	ImplLoad( rMultiPath );
207 }
208 
209 // ------------------------------------------------------------------------
210 
211 Gallery::~Gallery()
212 {
213 	// Themen-Liste loeschen
214 	for( GalleryThemeEntry* pThemeEntry = aThemeList.First(); pThemeEntry; pThemeEntry = aThemeList.Next() )
215 		delete pThemeEntry;
216 
217 	// Import-Liste loeschen
218 	for( GalleryImportThemeEntry* pImportEntry = aImportList.First(); pImportEntry; pImportEntry = aImportList.Next() )
219 		delete pImportEntry;
220 }
221 
222 // ------------------------------------------------------------------------
223 
224 Gallery* Gallery::GetGalleryInstance()
225 {
226 	static Gallery* pGallery = NULL;
227 
228 	if( !pGallery )
229 	{
230 	    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
231 		if( !pGallery )
232 		{
233 			pGallery = new Gallery( SvtPathOptions().GetGalleryPath() );
234 		}
235 	}
236 
237 	return pGallery;
238 }
239 
240 // ------------------------------------------------------------------------
241 
242 void Gallery::ImplLoad( const String& rMultiPath )
243 {
244 	const sal_uInt16    nTokenCount = rMultiPath.GetTokenCount( ';' );
245     sal_Bool        bIsReadOnlyDir;
246 
247 	bMultiPath = ( nTokenCount > 0 );
248 
249     INetURLObject aCurURL(SvtPathOptions().GetConfigPath());
250 	ImplLoadSubDirs( aCurURL, bIsReadOnlyDir );
251 
252 	if( !bIsReadOnlyDir )
253 	    aUserURL = aCurURL;
254 
255 	if( bMultiPath )
256 	{
257 		aRelURL = INetURLObject( rMultiPath.GetToken( 0, ';' ) );
258 
259 		for( sal_uInt16 i = 0UL; i < nTokenCount; i++ )
260 		{
261 		    aCurURL = INetURLObject(rMultiPath.GetToken( i, ';' ));
262 
263 			ImplLoadSubDirs( aCurURL, bIsReadOnlyDir );
264 
265 			if( !bIsReadOnlyDir )
266 			    aUserURL = aCurURL;
267 	    }
268 	}
269 	else
270 		aRelURL = INetURLObject( rMultiPath );
271 
272 	DBG_ASSERT( aUserURL.GetProtocol() != INET_PROT_NOT_VALID, "no writable Gallery user directory available" );
273 	DBG_ASSERT( aRelURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
274 
275 	ImplLoadImports();
276 }
277 
278 // ------------------------------------------------------------------------
279 
280 void Gallery::ImplLoadSubDirs( const INetURLObject& rBaseURL, sal_Bool& rbDirIsReadOnly )
281 {
282     rbDirIsReadOnly = sal_False;
283 
284 	try
285 	{
286 		uno::Reference< ucb::XCommandEnvironment > xEnv;
287 		::ucbhelper::Content					   aCnt( rBaseURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv );
288 
289 		uno::Sequence< OUString > aProps( 1 );
290 		aProps.getArray()[ 0 ] = OUString::createFromAscii( "Url" );
291 
292 		uno::Reference< sdbc::XResultSet > xResultSet( aCnt.createCursor( aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ) );
293 
294 		try
295 		{
296 		    // check readonlyness the very hard way
297         	INetURLObject   aTestURL( rBaseURL );
298 	        String          aTestFile( RTL_CONSTASCII_USTRINGPARAM( "cdefghij.klm" ) );
299 
300     	    aTestURL.Append( aTestFile );
301 	        SvStream* pTestStm = ::utl::UcbStreamHelper::CreateStream( aTestURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE );
302 
303 	        if( pTestStm )
304 	        {
305 	            *pTestStm << 1;
306 
307 	            if( pTestStm->GetError() )
308 	                rbDirIsReadOnly = sal_True;
309 
310 	            delete pTestStm;
311 	            KillFile( aTestURL );
312 	        }
313 	        else
314 	            rbDirIsReadOnly = sal_True;
315 	    }
316 	    catch( const ucb::ContentCreationException& )
317 	    {
318 	    }
319 	    catch( const uno::RuntimeException& )
320 	    {
321 	    }
322 	    catch( const uno::Exception& )
323 	    {
324 	    }
325 
326 		if( xResultSet.is() )
327 		{
328 			uno::Reference< ucb::XContentAccess > xContentAccess( xResultSet, uno::UNO_QUERY );
329 
330 			if( xContentAccess.is() )
331 			{
332                 static const ::rtl::OUString s_sTitle(RTL_CONSTASCII_USTRINGPARAM("Title"));
333                 static const ::rtl::OUString s_sIsReadOnly(RTL_CONSTASCII_USTRINGPARAM("IsReadOnly"));
334                 static const ::rtl::OUString s_sSDG_EXT(RTL_CONSTASCII_USTRINGPARAM("sdg"));
335                 static const ::rtl::OUString s_sSDV_EXT(RTL_CONSTASCII_USTRINGPARAM("sdv"));
336 
337 				while( xResultSet->next() )
338 				{
339 					INetURLObject aThmURL( xContentAccess->queryContentIdentifierString() );
340 
341 					if(aThmURL.GetExtension().equalsIgnoreAsciiCaseAscii("thm"))
342 					{
343 						INetURLObject	aSdgURL( aThmURL); aSdgURL.SetExtension( s_sSDG_EXT );
344 						INetURLObject	aSdvURL( aThmURL ); aSdvURL.SetExtension( s_sSDV_EXT );
345 
346 						OUString		aTitle;
347 						sal_Bool		bReadOnly = sal_False;
348 
349 						try
350 						{
351 						    ::ucbhelper::Content aThmCnt( aThmURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv );
352 						    ::ucbhelper::Content aSdgCnt( aSdgURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv );
353 						    ::ucbhelper::Content aSdvCnt( aSdvURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv );
354 
355 						    try
356 						    {
357 						        aThmCnt.getPropertyValue( s_sTitle ) >>= aTitle;
358 						    }
359 	                        catch( const uno::RuntimeException& )
360 	                        {
361 	                        }
362 	                        catch( const uno::Exception& )
363 	                        {
364 	                        }
365 
366 						    if( aTitle.getLength() )
367 						    {
368 						        try
369 						        {
370 							        aThmCnt.getPropertyValue( s_sIsReadOnly ) >>= bReadOnly;
371 						        }
372 	                            catch( const uno::RuntimeException& )
373 	                            {
374 	                            }
375 	                            catch( const uno::Exception& )
376 	                            {
377 	                            }
378 
379 							    if( !bReadOnly )
380 							    {
381 							        try
382 							        {
383 								        aSdgCnt.getPropertyValue( s_sTitle ) >>= aTitle;
384 						            }
385 	                                catch( const ::com::sun::star::uno::RuntimeException& )
386 	                                {
387 	                                }
388 	                                catch( const ::com::sun::star::uno::Exception& )
389 	                                {
390 	                                }
391 
392 								    if( aTitle.getLength() )
393 								    {
394 								        try
395 								        {
396 	    								    aSdgCnt.getPropertyValue( s_sIsReadOnly ) >>= bReadOnly;
397     					                }
398 	                                    catch( const uno::RuntimeException& )
399 	                                    {
400 	                                    }
401 	                                    catch( const uno::Exception& )
402 	                                    {
403 	                                    }
404 							        }
405 							    }
406 
407 							    if( !bReadOnly )
408 							    {
409 							        try
410 							        {
411 								        aSdvCnt.getPropertyValue( s_sTitle ) >>= aTitle;
412     					            }
413 	                                catch( const ::com::sun::star::uno::RuntimeException& )
414 	                                {
415 	                                }
416 	                                catch( const ::com::sun::star::uno::Exception& )
417 	                                {
418 	                                }
419 
420 								    if( aTitle.getLength() )
421 								    {
422 								        try
423 								        {
424     									    aSdvCnt.getPropertyValue( s_sIsReadOnly ) >>= bReadOnly;
425     					                }
426 	                                    catch( const uno::RuntimeException& )
427 	                                    {
428 	                                    }
429 	                                    catch( const uno::Exception& )
430 	                                    {
431 	                                    }
432 								    }
433 							    }
434 
435 							    GalleryThemeEntry* pEntry = GalleryTheme::CreateThemeEntry( aThmURL, rbDirIsReadOnly || bReadOnly );
436 
437 							    if( pEntry )
438 							    {
439 								    const sal_uIntPtr nFileNumber = (sal_uIntPtr) String(aThmURL.GetBase()).Erase( 0, 2 ).Erase( 6 ).ToInt32();
440 
441 								    aThemeList.Insert( pEntry, LIST_APPEND );
442 
443 								    if( nFileNumber > nLastFileNumber )
444 									    nLastFileNumber = nFileNumber;
445 							    }
446 						    }
447 						}
448 	                    catch( const ucb::ContentCreationException& )
449 	                    {
450 	                    }
451 	                    catch( const uno::RuntimeException& )
452 	                    {
453 	                    }
454 	                    catch( const uno::Exception& )
455 	                    {
456 	                    }
457 					}
458 				}
459 			}
460 		}
461 	}
462 	catch( const ucb::ContentCreationException& )
463 	{
464 	}
465 	catch( const uno::RuntimeException& )
466 	{
467 	}
468 	catch( const uno::Exception& )
469 	{
470 	}
471 }
472 
473 // ------------------------------------------------------------------------
474 
475 void Gallery::ImplLoadImports()
476 {
477 	INetURLObject aURL( GetUserURL() );
478 
479 	aURL.Append( String( RTL_CONSTASCII_USTRINGPARAM( "gallery.sdi" ) ) );
480 
481 	if( FileExists( aURL ) )
482 	{
483 		SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
484 
485 		if( pIStm )
486 		{
487 			GalleryThemeEntry*			pThemeEntry;
488 			GalleryImportThemeEntry*	pImportEntry;
489 			INetURLObject               aFile;
490 			sal_uInt32                      nInventor;
491 			sal_uInt32                      nCount;
492 			sal_uInt16                      nId;
493 			sal_uInt16                      i;
494 			sal_uInt16                      nTempCharSet;
495 
496 			for( pImportEntry = aImportList.First(); pImportEntry; pImportEntry = aImportList.Next() )
497 				delete pImportEntry;
498 
499 			aImportList.Clear();
500 			*pIStm >> nInventor;
501 
502 			if( nInventor == COMPAT_FORMAT( 'S', 'G', 'A', '3' ) )
503 			{
504 				*pIStm >> nId >> nCount >> nTempCharSet;
505 
506 				for( i = 0; i < nCount; i++ )
507 				{
508 					pImportEntry = new GalleryImportThemeEntry;
509 
510 					*pIStm >> *pImportEntry;
511 					aImportList.Insert( pImportEntry, LIST_APPEND );
512 					aFile = INetURLObject( pImportEntry->aURL );
513 					pThemeEntry = new GalleryThemeEntry( aFile,
514 														 pImportEntry->aUIName,
515 														 String(aFile.GetBase()).Erase( 0, 2 ).Erase( 6 ).ToInt32(),
516 														 sal_True, sal_True, sal_False, 0, sal_False );
517 
518 					aThemeList.Insert( pThemeEntry, LIST_APPEND );
519 				}
520 			}
521 
522 			delete pIStm;
523 		}
524 	}
525 }
526 
527 // ------------------------------------------------------------------------
528 
529 void Gallery::ImplWriteImportList()
530 {
531 	INetURLObject aURL( GetUserURL() );
532 	aURL.Append( ( String( "gallery.sdi", RTL_TEXTENCODING_UTF8 ) ) );
533 	SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_TRUNC );
534 
535 	if( pOStm )
536 	{
537 		const sal_uInt32 nInventor = (sal_uInt32) COMPAT_FORMAT( 'S', 'G', 'A', '3' );
538 		const sal_uInt16 nId = 0x0004;
539 
540 		*pOStm << nInventor << nId << (sal_uInt32) aImportList.Count() << (sal_uInt16) gsl_getSystemTextEncoding();
541 
542 		for( GalleryImportThemeEntry* pImportEntry = aImportList.First(); pImportEntry; pImportEntry = aImportList.Next() )
543 			*pOStm << *pImportEntry;
544 
545 		if( pOStm->GetError() )
546 			ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
547 
548 		delete pOStm;
549 	}
550 }
551 
552 // ------------------------------------------------------------------------
553 
554 GalleryThemeEntry* Gallery::ImplGetThemeEntry( const String& rThemeName )
555 {
556 	GalleryThemeEntry* pFound = NULL;
557 
558 	if( rThemeName.Len() )
559 		for( GalleryThemeEntry* pEntry = aThemeList.First(); pEntry && !pFound; pEntry = aThemeList.Next() )
560 			if( rThemeName == pEntry->GetThemeName() )
561 				pFound = pEntry;
562 
563 	return pFound;
564 }
565 
566 // ------------------------------------------------------------------------
567 
568 GalleryImportThemeEntry* Gallery::ImplGetImportThemeEntry( const String& rImportName )
569 {
570 	GalleryImportThemeEntry* pFound = NULL;
571 
572 	for( GalleryImportThemeEntry* pImportEntry = aImportList.First(); pImportEntry && !pFound; pImportEntry = aImportList.Next() )
573 		if ( rImportName == pImportEntry->aUIName )
574 			pFound = pImportEntry;
575 
576 	return pFound;
577 }
578 
579 // ------------------------------------------------------------------------
580 
581 String Gallery::GetThemeName( sal_uIntPtr nThemeId ) const
582 {
583 	GalleryThemeEntry* pFound = NULL;
584 
585 	for( sal_uIntPtr n = 0, nCount = aThemeList.Count(); n < nCount; n++ )
586 	{
587 		GalleryThemeEntry* pEntry = aThemeList.GetObject( n );
588 
589 		if( nThemeId == pEntry->GetId() )
590 			pFound = pEntry;
591 	}
592 
593 	// try fallback, if no entry was found
594 	if( !pFound )
595 	{
596 		ByteString      aFallback;
597 
598 		switch( nThemeId )
599 		{
600 			case( GALLERY_THEME_3D ): aFallback = "3D"; break;
601 			case( GALLERY_THEME_BULLETS ): aFallback = "Bullets"; break;
602 			case( GALLERY_THEME_HOMEPAGE ): aFallback = "Homepage"; break;
603 			case( GALLERY_THEME_POWERPOINT ): aFallback = "private://gallery/hidden/imgppt"; break;
604 			case( GALLERY_THEME_FONTWORK ): aFallback = "private://gallery/hidden/fontwork"; break;
605 			case( GALLERY_THEME_FONTWORK_VERTICAL ): aFallback = "private://gallery/hidden/fontworkvertical"; break;
606 			case( GALLERY_THEME_RULERS ): aFallback = "Rulers"; break;
607 			case( GALLERY_THEME_SOUNDS ): aFallback = "Sounds"; break;
608 
609 			default:
610 			break;
611 		}
612 
613 		pFound = ( (Gallery*) this )->ImplGetThemeEntry( String::CreateFromAscii( aFallback.GetBuffer() ) );
614 	}
615 
616 	return( pFound ? pFound->GetThemeName() : String() );
617 }
618 
619 // ------------------------------------------------------------------------
620 
621 sal_Bool Gallery::HasTheme( const String& rThemeName )
622 {
623 	return( ImplGetThemeEntry( rThemeName ) != NULL );
624 }
625 
626 // ------------------------------------------------------------------------
627 
628 sal_Bool Gallery::CreateTheme( const String& rThemeName, sal_uInt32 nNumFrom )
629 {
630 	sal_Bool bRet = sal_False;
631 
632 	if( !HasTheme( rThemeName ) && ( GetUserURL().GetProtocol() != INET_PROT_NOT_VALID ) )
633 	{
634 		nLastFileNumber = nNumFrom > nLastFileNumber ? nNumFrom : nLastFileNumber + 1;
635 		GalleryThemeEntry* pNewEntry = new GalleryThemeEntry( GetUserURL(), rThemeName,
636 															  nLastFileNumber,
637 															  sal_False, sal_False, sal_True, 0, sal_False );
638 
639 		aThemeList.Insert( pNewEntry, LIST_APPEND );
640 		delete( new GalleryTheme( this, pNewEntry ) );
641 		Broadcast( GalleryHint( GALLERY_HINT_THEME_CREATED, rThemeName ) );
642 		bRet = sal_True;
643 	}
644 
645 	return bRet;
646 }
647 
648 // ------------------------------------------------------------------------
649 
650 sal_Bool Gallery::CreateImportTheme( const INetURLObject& rURL, const String& rImportName )
651 {
652 	INetURLObject	aURL( rURL );
653 	sal_Bool			bRet = sal_False;
654 
655 	DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
656 
657 	if( FileExists( aURL ) )
658 	{
659 		SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
660 
661 		if( pIStm )
662 		{
663 			sal_uIntPtr   nStmErr;
664 			sal_uInt16  nId;
665 
666 			*pIStm >> nId;
667 
668 			if( nId > 0x0004 )
669 				ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
670 			else
671 			{
672 				ByteString				aTmpStr;
673 				String                  aThemeName; *pIStm >> aTmpStr; aThemeName = String( aTmpStr, RTL_TEXTENCODING_UTF8 );
674 				GalleryThemeEntry*      pThemeEntry = new GalleryThemeEntry( aURL, rImportName,
675 																			 String(aURL.GetBase()).Erase( 0, 2 ).Erase( 6 ).ToInt32(),
676 																			 sal_True, sal_True, sal_True, 0, sal_False );
677 				GalleryTheme*           pImportTheme = new GalleryTheme( this, pThemeEntry );
678 
679 				pIStm->Seek( STREAM_SEEK_TO_BEGIN );
680 				*pIStm >> *pImportTheme;
681 				nStmErr = pIStm->GetError();
682 
683 				if( nStmErr )
684 				{
685 					delete pThemeEntry;
686 					ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
687 				}
688 				else
689 				{
690 					String  aName( rImportName );
691 					String  aNewName( aName );
692 					sal_uIntPtr   nCount = 0;
693 
694 					aName += ' ';
695 
696 					while ( HasTheme( aNewName ) && ( nCount++ < 16000 ) )
697 					{
698 						aNewName = aName;
699 						aNewName += String::CreateFromInt32( nCount );
700 					}
701 
702 					pImportTheme->SetImportName( aNewName );
703 					aThemeList.Insert( pThemeEntry, LIST_APPEND );
704 
705 					// Thema in Import-Liste eintragen und Import-Liste     speichern
706 					GalleryImportThemeEntry* pImportEntry = new GalleryImportThemeEntry;
707 					pImportEntry->aThemeName = pImportEntry->aUIName = aNewName;
708 					pImportEntry->aURL = rURL;
709 					pImportEntry->aImportName = rImportName;
710 					aImportList.Insert( pImportEntry, LIST_APPEND );
711 					ImplWriteImportList();
712 					bRet = sal_True;
713 				}
714 
715 				delete pImportTheme;
716 			}
717 
718 			delete pIStm;
719 		}
720 	}
721 
722 	return bRet;
723 }
724 
725 // ------------------------------------------------------------------------
726 
727 sal_Bool Gallery::RenameTheme( const String& rOldName, const String& rNewName )
728 {
729 	GalleryThemeEntry*      pThemeEntry = ImplGetThemeEntry( rOldName );
730 	sal_Bool                            bRet = sal_False;
731 
732 	// Ueberpruefen, ob neuer Themenname schon vorhanden ist
733 	if( pThemeEntry && !HasTheme( rNewName ) && ( !pThemeEntry->IsReadOnly() || pThemeEntry->IsImported() ) )
734 	{
735 		SfxListener   aListener;
736 		GalleryTheme* pThm = AcquireTheme( rOldName, aListener );
737 
738 		if( pThm )
739 		{
740 			const String aOldName( rOldName );
741 
742 			pThemeEntry->SetName( rNewName );
743 			pThm->ImplWrite();
744 
745 			if( pThemeEntry->IsImported() )
746 			{
747 				pThm->SetImportName( rNewName );
748 
749 				GalleryImportThemeEntry* pImportEntry = ImplGetImportThemeEntry( rOldName );
750 
751 				if( pImportEntry )
752 				{
753 					pImportEntry->aUIName = rNewName;
754 					ImplWriteImportList();
755 				}
756 			}
757 
758 			Broadcast( GalleryHint( GALLERY_HINT_THEME_RENAMED, aOldName, pThm->GetName() ) );
759 			ReleaseTheme( pThm, aListener );
760 			bRet = sal_True;
761 		}
762 	}
763 
764 	return bRet;
765 }
766 
767 // ------------------------------------------------------------------------
768 
769 sal_Bool Gallery::RemoveTheme( const String& rThemeName )
770 {
771 	GalleryThemeEntry*	pThemeEntry = ImplGetThemeEntry( rThemeName );
772 	sal_Bool                bRet = sal_False;
773 
774 	if( pThemeEntry && ( !pThemeEntry->IsReadOnly() || pThemeEntry->IsImported() ) )
775 	{
776 		Broadcast( GalleryHint( GALLERY_HINT_CLOSE_THEME, rThemeName ) );
777 
778 		if( pThemeEntry->IsImported() )
779 		{
780 			GalleryImportThemeEntry* pImportEntry = ImplGetImportThemeEntry( rThemeName );
781 
782 			if( pImportEntry )
783 			{
784 				delete aImportList.Remove( pImportEntry );
785 				ImplWriteImportList();
786 			}
787 		}
788 		else
789 		{
790 			SfxListener		aListener;
791 			GalleryTheme*	pThm = AcquireTheme( rThemeName, aListener );
792 
793             if( pThm )
794             {
795                 INetURLObject	aThmURL( pThm->GetThmURL() );
796                 INetURLObject	aSdgURL( pThm->GetSdgURL() );
797                 INetURLObject	aSdvURL( pThm->GetSdvURL() );
798 
799                 ReleaseTheme( pThm, aListener );
800 
801                 KillFile( aThmURL );
802                 KillFile( aSdgURL );
803                 KillFile( aSdvURL );
804             }
805 		}
806 
807 		delete aThemeList.Remove( pThemeEntry );
808 		Broadcast( GalleryHint( GALLERY_HINT_THEME_REMOVED, rThemeName ) );
809 
810 		bRet = sal_True;
811 	}
812 
813 	return bRet;
814 }
815 
816 // ------------------------------------------------------------------------
817 
818 INetURLObject Gallery::GetImportURL( const String& rThemeName )
819 {
820 	INetURLObject				aURL;
821 	GalleryImportThemeEntry*	pImportEntry = ImplGetImportThemeEntry( rThemeName );
822 
823 	if( pImportEntry )
824 	{
825 		aURL = pImportEntry->aURL;
826 		DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
827 	}
828 
829 	return aURL;
830 }
831 
832 // ------------------------------------------------------------------------
833 
834 GalleryTheme* Gallery::ImplGetCachedTheme( const GalleryThemeEntry* pThemeEntry )
835 {
836 	GalleryTheme* pTheme = NULL;
837 
838 	if( pThemeEntry )
839 	{
840 		GalleryThemeCacheEntry* pEntry;
841 
842 		for( pEntry = (GalleryThemeCacheEntry*) aThemeCache.First(); pEntry && !pTheme; pEntry = (GalleryThemeCacheEntry*) aThemeCache.Next() )
843 			if( pThemeEntry == pEntry->GetThemeEntry() )
844 				pTheme = pEntry->GetTheme();
845 
846 		if( !pTheme )
847 		{
848 			INetURLObject aURL;
849 
850 			if( !pThemeEntry->IsImported() )
851 				aURL = pThemeEntry->GetThmURL();
852 			else
853 				aURL = GetImportURL( pThemeEntry->GetThemeName() );
854 
855 			DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
856 
857 			if( FileExists( aURL ) )
858 			{
859 				SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
860 
861 				if( pIStm )
862 				{
863 					pTheme = new GalleryTheme( this, (GalleryThemeEntry*) pThemeEntry );
864 					*pIStm >> *pTheme;
865 
866 					if( pIStm->GetError() )
867 						delete pTheme, pTheme = NULL;
868 					else if( pThemeEntry->IsImported() )
869 						pTheme->SetImportName( pThemeEntry->GetThemeName() );
870 
871 					delete pIStm;
872 				}
873 			}
874 
875 			if( pTheme )
876 				aThemeCache.Insert( new GalleryThemeCacheEntry( pThemeEntry, pTheme ), LIST_APPEND );
877 		}
878 	}
879 
880 	return pTheme;
881 }
882 
883 // ------------------------------------------------------------------------
884 
885 void Gallery::ImplDeleteCachedTheme( GalleryTheme* pTheme )
886 {
887 	GalleryThemeCacheEntry* pEntry;
888 	sal_Bool                                    bDone = sal_False;
889 
890 	for( pEntry = (GalleryThemeCacheEntry*) aThemeCache.First(); pEntry && !bDone; pEntry = (GalleryThemeCacheEntry*) aThemeCache.Next() )
891 	{
892 		if( pTheme == pEntry->GetTheme() )
893 		{
894 			delete (GalleryThemeCacheEntry*) aThemeCache.Remove( pEntry );
895 			bDone = sal_True;
896 		}
897 	}
898 }
899 
900 // ------------------------------------------------------------------------
901 
902 GalleryTheme* Gallery::AcquireTheme( const String& rThemeName, SfxListener& rListener )
903 {
904 	GalleryTheme*           pTheme = NULL;
905 	GalleryThemeEntry*      pThemeEntry = ImplGetThemeEntry( rThemeName );
906 
907 	if( pThemeEntry && ( ( pTheme = ImplGetCachedTheme( pThemeEntry ) ) != NULL ) )
908 		rListener.StartListening( *pTheme );
909 
910 	return pTheme;
911 }
912 
913 // ------------------------------------------------------------------------
914 
915 void Gallery::ReleaseTheme( GalleryTheme* pTheme, SfxListener& rListener )
916 {
917 	if( pTheme )
918 	{
919 		rListener.EndListening( *pTheme );
920 
921 		if( !pTheme->HasListeners() )
922 			ImplDeleteCachedTheme( pTheme );
923 	}
924 }
925 
926 sal_Bool GalleryThemeEntry::IsDefault() const
927 { return( ( nId > 0 ) && ( nId != ( RID_GALLERYSTR_THEME_MYTHEME - RID_GALLERYSTR_THEME_START ) ) ); }
928 
929