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