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