1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include <comphelper/processfactory.hxx>
23 #include <comphelper/string.hxx>
24 #include <tools/vcompat.hxx>
25 #include <ucbhelper/content.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
27 #include <unotools/pathoptions.hxx>
28 #include <sfx2/docfile.hxx>
29 #include "svx/gallery.hxx"
30 #include "gallery.hrc"
31 #include "svx/galmisc.hxx"
32 #include "svx/galtheme.hxx"
33 #include "svx/gallery1.hxx"
34 #include <com/sun/star/sdbc/XResultSet.hpp>
35 #include <com/sun/star/ucb/XContentAccess.hpp>
41 using namespace ::rtl
;
42 using namespace ::com::sun::star
;
44 // ---------------------
45 // - GalleryThemeEntry -
46 // ---------------------
48 static bool FileExists( const INetURLObject
&rURL
, const rtl::OUString
&rExt
)
50 INetURLObject
aURL( rURL
);
51 aURL
.setExtension( rExt
);
52 return FileExists( aURL
);
55 GalleryThemeEntry::GalleryThemeEntry( bool bCreateUniqueURL
,
56 const INetURLObject
& rBaseURL
,
58 sal_Bool _bReadOnly
, sal_Bool _bNewFile
,
59 sal_uInt32 _nId
, sal_Bool _bThemeNameFromResource
) :
61 bReadOnly ( _bReadOnly
),
62 bThemeNameFromResource ( _bThemeNameFromResource
)
64 INetURLObject
aURL( rBaseURL
);
65 DBG_ASSERT( aURL
.GetProtocol() != INET_PROT_NOT_VALID
, "invalid URL" );
69 INetURLObject
aBaseNoCase( ImplGetURLIgnoreCase( rBaseURL
) );
71 static sal_Int32 nIdx
= 0;
72 while( FileExists( aURL
, "thm" ) )
76 aURL
.setName( aURL
.getName() + OUString::number(nIdx
));
80 aURL
.setExtension( "thm" );
81 aThmURL
= ImplGetURLIgnoreCase( aURL
);
83 aURL
.setExtension( "sdg" );
84 aSdgURL
= ImplGetURLIgnoreCase( aURL
);
86 aURL
.setExtension( "sdv" );
87 aSdvURL
= ImplGetURLIgnoreCase( aURL
);
89 aURL
.setExtension( "str" );
90 aStrURL
= ImplGetURLIgnoreCase( aURL
);
92 SetModified( _bNewFile
);
94 aName
= ReadStrFromIni( "name" );
96 // This is awful - we shouldn't use these resources if we
97 // possibly can avoid them
98 if( aName
.isEmpty() && nId
&& bThemeNameFromResource
)
99 aName
= GAL_RESSTR( RID_GALLERYSTR_THEME_START
+ (sal_uInt16
) nId
);
101 if( aName
.isEmpty() )
105 // -----------------------------------------------------------------------------
107 INetURLObject
GalleryThemeEntry::ImplGetURLIgnoreCase( const INetURLObject
& rURL
) const
109 INetURLObject
aURL( rURL
);
111 // check original file name
112 if( !FileExists( aURL
) )
114 // check upper case file name
115 aURL
.setName( aURL
.getName().toAsciiUpperCase() );
117 if(!FileExists( aURL
) )
119 // check lower case file name
120 aURL
.setName( aURL
.getName().toAsciiLowerCase() );
127 // -----------------------------------------------------------------------------
129 void GalleryThemeEntry::SetName( const OUString
& rNewName
)
131 if( aName
!= rNewName
)
134 SetModified( sal_True
);
135 bThemeNameFromResource
= sal_False
;
139 // -----------------------------------------------------------------------------
141 void GalleryThemeEntry::SetId( sal_uInt32 nNewId
, sal_Bool bResetThemeName
)
144 SetModified( sal_True
);
145 bThemeNameFromResource
= ( nId
&& bResetThemeName
);
148 // --------------------------
149 // - GalleryThemeCacheEntry -
150 // --------------------------
152 class GalleryThemeCacheEntry
156 const GalleryThemeEntry
* mpThemeEntry
;
157 GalleryTheme
* mpTheme
;
161 GalleryThemeCacheEntry( const GalleryThemeEntry
* pThemeEntry
, GalleryTheme
* pTheme
) :
162 mpThemeEntry( pThemeEntry
), mpTheme( pTheme
) {}
163 ~GalleryThemeCacheEntry() { delete mpTheme
; }
165 const GalleryThemeEntry
* GetThemeEntry() const { return mpThemeEntry
; }
166 GalleryTheme
* GetTheme() const { return mpTheme
; }
173 Gallery::Gallery( const OUString
& rMultiPath
)
174 : nReadTextEncoding ( osl_getThreadTextEncoding() )
175 , bMultiPath ( sal_False
)
177 ImplLoad( rMultiPath
);
180 // ------------------------------------------------------------------------
184 // Themen-Liste loeschen
185 for ( size_t i
= 0, n
= aThemeList
.size(); i
< n
; ++i
)
186 delete aThemeList
[ i
];
190 // ------------------------------------------------------------------------
192 Gallery
* Gallery::GetGalleryInstance()
194 static Gallery
* pGallery
= NULL
;
198 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
201 pGallery
= new Gallery( SvtPathOptions().GetGalleryPath() );
208 // ------------------------------------------------------------------------
210 void Gallery::ImplLoad( const OUString
& rMultiPath
)
212 const sal_Int32 nTokenCount
= comphelper::string::getTokenCount(rMultiPath
, ';');
213 sal_Bool bIsReadOnlyDir
;
215 bMultiPath
= ( nTokenCount
> 0 );
217 INetURLObject
aCurURL(SvtPathOptions().GetConfigPath());
218 ImplLoadSubDirs( aCurURL
, bIsReadOnlyDir
);
220 if( !bIsReadOnlyDir
)
225 aRelURL
= INetURLObject( comphelper::string::getToken(rMultiPath
, 0, ';') );
227 for( sal_Int32 i
= 0; i
< nTokenCount
; ++i
)
229 aCurURL
= INetURLObject(comphelper::string::getToken(rMultiPath
, i
, ';'));
231 ImplLoadSubDirs( aCurURL
, bIsReadOnlyDir
);
233 if( !bIsReadOnlyDir
)
238 aRelURL
= INetURLObject( rMultiPath
);
240 DBG_ASSERT( aUserURL
.GetProtocol() != INET_PROT_NOT_VALID
, "no writable Gallery user directory available" );
241 DBG_ASSERT( aRelURL
.GetProtocol() != INET_PROT_NOT_VALID
, "invalid URL" );
244 // ------------------------------------------------------------------------
246 void Gallery::ImplLoadSubDirs( const INetURLObject
& rBaseURL
, sal_Bool
& rbDirIsReadOnly
)
248 rbDirIsReadOnly
= sal_False
;
252 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
253 ::ucbhelper::Content
aCnt( rBaseURL
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext() );
255 uno::Sequence
< OUString
> aProps( 1 );
256 aProps
.getArray()[ 0 ] = OUString("Url");
258 uno::Reference
< sdbc::XResultSet
> xResultSet( aCnt
.createCursor( aProps
, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY
) );
262 // check readonlyness the very hard way
263 INetURLObject
aTestURL( rBaseURL
);
264 String
aTestFile( RTL_CONSTASCII_USTRINGPARAM( "cdefghij.klm" ) );
266 aTestURL
.Append( aTestFile
);
267 SvStream
* pTestStm
= ::utl::UcbStreamHelper::CreateStream( aTestURL
.GetMainURL( INetURLObject::NO_DECODE
), STREAM_WRITE
);
271 *pTestStm
<< sal_Int32(1);
273 if( pTestStm
->GetError() )
274 rbDirIsReadOnly
= sal_True
;
277 KillFile( aTestURL
);
280 rbDirIsReadOnly
= sal_True
;
282 catch( const ucb::ContentCreationException
& )
285 catch( const uno::RuntimeException
& )
288 catch( const uno::Exception
& )
292 if( xResultSet
.is() )
294 uno::Reference
< ucb::XContentAccess
> xContentAccess( xResultSet
, uno::UNO_QUERY
);
296 if( xContentAccess
.is() )
298 static const OUString
s_sTitle("Title");
299 static const OUString
s_sIsReadOnly("IsReadOnly");
300 static const OUString
s_sSDG_EXT("sdg");
301 static const OUString
s_sSDV_EXT("sdv");
303 while( xResultSet
->next() )
305 INetURLObject
aThmURL( xContentAccess
->queryContentIdentifierString() );
307 if(aThmURL
.GetExtension().equalsIgnoreAsciiCase("thm"))
309 INetURLObject
aSdgURL( aThmURL
); aSdgURL
.SetExtension( s_sSDG_EXT
);
310 INetURLObject
aSdvURL( aThmURL
); aSdvURL
.SetExtension( s_sSDV_EXT
);
312 sal_Bool bReadOnly
= sal_False
;
316 ::ucbhelper::Content
aThmCnt( aThmURL
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext() );
317 ::ucbhelper::Content
aSdgCnt( aSdgURL
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext() );
318 ::ucbhelper::Content
aSdvCnt( aSdvURL
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext() );
322 aThmCnt
.getPropertyValue( s_sTitle
) >>= aTitle
;
324 catch( const uno::RuntimeException
& )
327 catch( const uno::Exception
& )
331 if( !aTitle
.isEmpty() )
335 aThmCnt
.getPropertyValue( s_sIsReadOnly
) >>= bReadOnly
;
337 catch( const uno::RuntimeException
& )
340 catch( const uno::Exception
& )
348 aSdgCnt
.getPropertyValue( s_sTitle
) >>= aTitle
;
350 catch( const ::com::sun::star::uno::RuntimeException
& )
353 catch( const ::com::sun::star::uno::Exception
& )
357 if( !aTitle
.isEmpty() )
361 aSdgCnt
.getPropertyValue( s_sIsReadOnly
) >>= bReadOnly
;
363 catch( const uno::RuntimeException
& )
366 catch( const uno::Exception
& )
376 aSdvCnt
.getPropertyValue( s_sTitle
) >>= aTitle
;
378 catch( const ::com::sun::star::uno::RuntimeException
& )
381 catch( const ::com::sun::star::uno::Exception
& )
385 if( !aTitle
.isEmpty() )
389 aSdvCnt
.getPropertyValue( s_sIsReadOnly
) >>= bReadOnly
;
391 catch( const uno::RuntimeException
& )
394 catch( const uno::Exception
& )
400 GalleryThemeEntry
* pEntry
= GalleryTheme::CreateThemeEntry( aThmURL
, rbDirIsReadOnly
|| bReadOnly
);
403 aThemeList
.push_back( pEntry
);
406 catch( const ucb::ContentCreationException
& )
409 catch( const uno::RuntimeException
& )
412 catch( const uno::Exception
& )
420 catch( const ucb::ContentCreationException
& )
423 catch( const uno::RuntimeException
& )
426 catch( const uno::Exception
& )
431 // ------------------------------------------------------------------------
433 GalleryThemeEntry
* Gallery::ImplGetThemeEntry( const OUString
& rThemeName
)
435 GalleryThemeEntry
* pFound
= NULL
;
437 if( !rThemeName
.isEmpty() )
439 for ( size_t i
= 0, n
= aThemeList
.size(); i
< n
&& !pFound
; ++i
)
440 if( rThemeName
== aThemeList
[ i
]->GetThemeName() )
441 pFound
= aThemeList
[ i
];
447 // ------------------------------------------------------------------------
449 OUString
Gallery::GetThemeName( sal_uIntPtr nThemeId
) const
451 GalleryThemeEntry
* pFound
= NULL
;
453 for ( size_t i
= 0, n
= aThemeList
.size(); i
< n
&& !pFound
; ++i
)
455 GalleryThemeEntry
* pEntry
= aThemeList
[ i
];
456 if( nThemeId
== pEntry
->GetId() )
460 // try fallback, if no entry was found
467 case( GALLERY_THEME_3D
):
470 case( GALLERY_THEME_BULLETS
):
471 aFallback
= "Bullets";
473 case( GALLERY_THEME_HOMEPAGE
):
474 aFallback
= "Homepage";
476 case( GALLERY_THEME_POWERPOINT
):
477 aFallback
= "private://gallery/hidden/imgppt";
479 case( GALLERY_THEME_FONTWORK
):
480 aFallback
= "private://gallery/hidden/fontwork";
482 case( GALLERY_THEME_FONTWORK_VERTICAL
):
483 aFallback
= "private://gallery/hidden/fontworkvertical";
485 case( GALLERY_THEME_SOUNDS
):
486 aFallback
= "Sounds";
488 case( RID_GALLERYSTR_THEME_ARROWS
):
489 aFallback
= "Arrows";
491 case( RID_GALLERYSTR_THEME_COMPUTERS
):
492 aFallback
= "Computers";
494 case( RID_GALLERYSTR_THEME_DIAGRAMS
):
495 aFallback
= "Diagrams";
497 case( RID_GALLERYSTR_THEME_EDUCATION
):
498 aFallback
= "Education";
500 case( RID_GALLERYSTR_THEME_ENVIRONMENT
):
501 aFallback
= "Environment";
503 case( RID_GALLERYSTR_THEME_FINANCE
):
504 aFallback
= "Finance";
506 case( RID_GALLERYSTR_THEME_PEOPLE
):
507 aFallback
= "People";
509 case( RID_GALLERYSTR_THEME_SYMBOLS
):
510 aFallback
= "Symbols";
512 case( RID_GALLERYSTR_THEME_TRANSPORT
):
513 aFallback
= "Transport";
515 case( RID_GALLERYSTR_THEME_TXTSHAPES
):
516 aFallback
= "Textshapes";
522 pFound
= const_cast<Gallery
*>(this)->ImplGetThemeEntry(OStringToOUString(aFallback
, RTL_TEXTENCODING_ASCII_US
));
525 return( pFound
? pFound
->GetThemeName() : OUString() );
528 // ------------------------------------------------------------------------
530 sal_Bool
Gallery::HasTheme( const String
& rThemeName
)
532 return( ImplGetThemeEntry( rThemeName
) != NULL
);
535 // ------------------------------------------------------------------------
537 sal_Bool
Gallery::CreateTheme( const String
& rThemeName
)
539 sal_Bool bRet
= sal_False
;
541 if( !HasTheme( rThemeName
) && ( GetUserURL().GetProtocol() != INET_PROT_NOT_VALID
) )
543 INetURLObject
aURL( GetUserURL() );
544 aURL
.Append( rThemeName
);
545 GalleryThemeEntry
* pNewEntry
= new GalleryThemeEntry(
546 true, aURL
, rThemeName
,
547 sal_False
, sal_True
, 0, sal_False
);
549 aThemeList
.push_back( pNewEntry
);
550 delete( new GalleryTheme( this, pNewEntry
) );
551 Broadcast( GalleryHint( GALLERY_HINT_THEME_CREATED
, rThemeName
) );
558 // ------------------------------------------------------------------------
560 sal_Bool
Gallery::RenameTheme( const String
& rOldName
, const String
& rNewName
)
562 GalleryThemeEntry
* pThemeEntry
= ImplGetThemeEntry( rOldName
);
563 sal_Bool bRet
= sal_False
;
565 // Ueberpruefen, ob neuer Themenname schon vorhanden ist
566 if( pThemeEntry
&& !HasTheme( rNewName
) && !pThemeEntry
->IsReadOnly() )
568 SfxListener aListener
;
569 GalleryTheme
* pThm
= AcquireTheme( rOldName
, aListener
);
573 const String
aOldName( rOldName
);
575 pThemeEntry
->SetName( rNewName
);
578 Broadcast( GalleryHint( GALLERY_HINT_THEME_RENAMED
, aOldName
, pThm
->GetName() ) );
579 ReleaseTheme( pThm
, aListener
);
587 // ------------------------------------------------------------------------
589 sal_Bool
Gallery::RemoveTheme( const String
& rThemeName
)
591 GalleryThemeEntry
* pThemeEntry
= ImplGetThemeEntry( rThemeName
);
592 sal_Bool bRet
= sal_False
;
594 if( pThemeEntry
&& !pThemeEntry
->IsReadOnly() )
596 Broadcast( GalleryHint( GALLERY_HINT_CLOSE_THEME
, rThemeName
) );
598 SfxListener aListener
;
599 GalleryTheme
* pThm
= AcquireTheme( rThemeName
, aListener
);
603 INetURLObject
aThmURL( pThm
->GetThmURL() );
604 INetURLObject
aSdgURL( pThm
->GetSdgURL() );
605 INetURLObject
aSdvURL( pThm
->GetSdvURL() );
606 INetURLObject
aStrURL( pThm
->GetSdvURL() );
608 ReleaseTheme( pThm
, aListener
);
616 for ( GalleryThemeList::iterator it
= aThemeList
.begin(); it
!= aThemeList
.end(); ++it
)
618 if ( pThemeEntry
== *it
) {
620 aThemeList
.erase( it
);
625 Broadcast( GalleryHint( GALLERY_HINT_THEME_REMOVED
, rThemeName
) );
633 // ------------------------------------------------------------------------
635 GalleryTheme
* Gallery::ImplGetCachedTheme( const GalleryThemeEntry
* pThemeEntry
)
637 GalleryTheme
* pTheme
= NULL
;
641 for (GalleryCacheThemeList::const_iterator it
= aThemeCache
.begin(); it
!= aThemeCache
.end(); ++it
)
643 if (pThemeEntry
== (*it
)->GetThemeEntry())
645 pTheme
= (*it
)->GetTheme();
652 INetURLObject aURL
= pThemeEntry
->GetThmURL();
654 DBG_ASSERT( aURL
.GetProtocol() != INET_PROT_NOT_VALID
, "invalid URL" );
656 if( FileExists( aURL
) )
658 SvStream
* pIStm
= ::utl::UcbStreamHelper::CreateStream( aURL
.GetMainURL( INetURLObject::NO_DECODE
), STREAM_READ
);
662 pTheme
= new GalleryTheme( this, (GalleryThemeEntry
*) pThemeEntry
);
665 if( pIStm
->GetError() )
667 delete pTheme
, pTheme
= NULL
;
675 aThemeCache
.push_back( new GalleryThemeCacheEntry( pThemeEntry
, pTheme
));
682 // ------------------------------------------------------------------------
684 void Gallery::ImplDeleteCachedTheme( GalleryTheme
* pTheme
)
686 for (GalleryCacheThemeList::iterator it
= aThemeCache
.begin(); it
!= aThemeCache
.end(); ++it
)
688 if (pTheme
== (*it
)->GetTheme())
691 aThemeCache
.erase(it
);
697 // ------------------------------------------------------------------------
699 GalleryTheme
* Gallery::AcquireTheme( const String
& rThemeName
, SfxListener
& rListener
)
701 GalleryTheme
* pTheme
= NULL
;
702 GalleryThemeEntry
* pThemeEntry
= ImplGetThemeEntry( rThemeName
);
704 if( pThemeEntry
&& ( ( pTheme
= ImplGetCachedTheme( pThemeEntry
) ) != NULL
) )
705 rListener
.StartListening( *pTheme
);
710 // ------------------------------------------------------------------------
712 void Gallery::ReleaseTheme( GalleryTheme
* pTheme
, SfxListener
& rListener
)
716 rListener
.EndListening( *pTheme
);
718 if( !pTheme
->HasListeners() )
719 ImplDeleteCachedTheme( pTheme
);
723 sal_Bool
GalleryThemeEntry::IsDefault() const
724 { return( ( nId
> 0 ) && ( nId
!= ( RID_GALLERYSTR_THEME_MYTHEME
- RID_GALLERYSTR_THEME_START
) ) ); }
726 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */