xref: /trunk/main/svx/source/gallery2/gallery1.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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