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 .
21 #include "doctemplates.hxx"
22 #include <osl/mutex.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/diagnose_ex.h>
25 #include <tools/urlobj.hxx>
26 #include <rtl/ustring.hxx>
27 #include <rtl/ustrbuf.hxx>
28 #include <tools/resary.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/wrkwin.hxx>
31 #include <unotools/pathoptions.hxx>
32 #include <comphelper/componentcontext.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/sequenceashashmap.hxx>
35 #include <comphelper/storagehelper.hxx>
36 #include <comphelper/string.hxx>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/XPropertySetInfo.hpp>
40 #include <com/sun/star/beans/XPropertyContainer.hpp>
41 #include <com/sun/star/beans/StringPair.hpp>
42 #include <com/sun/star/util/theMacroExpander.hpp>
43 #include <com/sun/star/util/theOfficeInstallationDirectories.hpp>
44 #include <com/sun/star/configuration/theDefaultProvider.hpp>
45 #include <com/sun/star/container/XContainerQuery.hpp>
46 #include <com/sun/star/document/XTypeDetection.hpp>
47 #include <com/sun/star/document/DocumentProperties.hpp>
48 #include <com/sun/star/io/TempFile.hpp>
49 #include <com/sun/star/sdbc/XResultSet.hpp>
50 #include <com/sun/star/sdbc/XRow.hpp>
51 #include <com/sun/star/ucb/NameClash.hpp>
52 #include <com/sun/star/ucb/NameClashException.hpp>
53 #include <com/sun/star/ucb/TransferInfo.hpp>
54 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
55 #include <com/sun/star/ucb/XContentAccess.hpp>
56 #include <com/sun/star/frame/ModuleManager.hpp>
57 #include <com/sun/star/uno/Exception.hpp>
59 #include <svtools/templatefoldercache.hxx>
60 #include <unotools/configmgr.hxx>
61 #include <unotools/ucbhelper.hxx>
63 #include "sfx2/sfxresid.hxx"
64 #include "sfxurlrelocator.hxx"
65 #include "doctemplateslocal.hxx"
66 #include <sfx2/docfac.hxx>
67 #include <sfx2/docfile.hxx>
72 //-----------------------------------------------------------------------------
74 //=============================================================================
76 #define TEMPLATE_SERVICE_NAME "com.sun.star.frame.DocumentTemplates"
77 #define TEMPLATE_IMPLEMENTATION_NAME "com.sun.star.comp.sfx2.DocumentTemplates"
79 #define SERVICENAME_TYPEDETECTION "com.sun.star.document.TypeDetection"
81 #define TEMPLATE_ROOT_URL "vnd.sun.star.hier:/templates"
83 #define IS_FOLDER "IsFolder"
84 #define IS_DOCUMENT "IsDocument"
85 #define TARGET_URL "TargetURL"
86 #define TEMPLATE_VERSION "TemplateComponentVersion"
87 #define TEMPLATE_VERSION_VALUE "2"
88 #define TYPE_FOLDER "application/vnd.sun.star.hier-folder"
89 #define TYPE_LINK "application/vnd.sun.star.hier-link"
90 #define TYPE_FSYS_FOLDER "application/vnd.sun.staroffice.fsys-folder"
91 #define TYPE_FSYS_FILE "application/vnd.sun.staroffice.fsys-file"
93 #define PROPERTY_DIRLIST "DirectoryList"
94 #define PROPERTY_NEEDSUPDATE "NeedsUpdate"
95 #define PROPERTY_TYPE "TypeDescription"
97 #define TARGET_DIR_URL "TargetDirURL"
98 #define COMMAND_DELETE "delete"
100 #define STANDARD_FOLDER "standard"
104 //=============================================================================
106 using namespace ::com::sun::star
;
107 using namespace ::com::sun::star::beans
;
108 using namespace ::com::sun::star::document
;
109 using namespace ::com::sun::star::io
;
110 using namespace ::com::sun::star::lang
;
111 using namespace ::com::sun::star::sdbc
;
112 using namespace ::com::sun::star::ucb
;
113 using namespace ::com::sun::star::uno
;
114 using namespace ::com::sun::star::container
;
115 using namespace ::com::sun::star::util
;
117 using namespace ::ucbhelper
;
118 using namespace ::comphelper
;
122 //=============================================================================
124 class WaitWindow_Impl
: public WorkWindow
127 sal_uInt16 _nTextStyle
;
133 virtual void Paint( const Rectangle
& rRect
);
139 //=============================================================================
143 OUString maShortName
;
148 class DocTemplates_EntryData_Impl
;
149 class GroupData_Impl
;
151 typedef vector
< NamePair_Impl
* > NameList_Impl
;
152 typedef vector
< GroupData_Impl
* > GroupList_Impl
;
154 //=============================================================================
155 #include <com/sun/star/task/InteractionHandler.hpp>
156 #include <com/sun/star/ucb/XProgressHandler.hpp>
158 class TplTaskEnvironment
: public ::cppu::WeakImplHelper1
< ucb::XCommandEnvironment
>
160 uno::Reference
< task::XInteractionHandler
> m_xInteractionHandler
;
161 uno::Reference
< ucb::XProgressHandler
> m_xProgressHandler
;
164 TplTaskEnvironment( const uno::Reference
< task::XInteractionHandler
>& rxInteractionHandler
)
165 : m_xInteractionHandler( rxInteractionHandler
)
168 virtual uno::Reference
<task::XInteractionHandler
> SAL_CALL
getInteractionHandler() throw (uno::RuntimeException
)
169 { return m_xInteractionHandler
; }
171 virtual uno::Reference
<ucb::XProgressHandler
> SAL_CALL
getProgressHandler() throw (uno::RuntimeException
)
172 { return m_xProgressHandler
; }
175 class SfxDocTplService_Impl
177 uno::Reference
< XComponentContext
> mxContext
;
178 uno::Reference
< XCommandEnvironment
> maCmdEnv
;
179 uno::Reference
< XDocumentProperties
> m_xDocProps
;
180 uno::Reference
< XTypeDetection
> mxType
;
182 ::osl::Mutex maMutex
;
183 Sequence
< OUString
> maTemplateDirs
;
185 NameList_Impl maNames
;
187 Content maRootContent
;
188 Updater_Impl
* mpUpdater
;
189 sal_Bool mbIsInitialized
: 1;
190 sal_Bool mbLocaleSet
: 1;
192 SfxURLRelocator_Impl maRelocator
;
195 void getDefaultLocale();
197 void readFolderList();
198 sal_Bool
needsUpdate();
199 OUString
getLongName( const OUString
& rShortName
);
200 sal_Bool
setTitleForURL( const OUString
& rURL
, const OUString
& aTitle
);
201 sal_Bool
getTitleFromURL( const OUString
& rURL
, OUString
& aTitle
, OUString
& aType
, sal_Bool
& bDocHasTitle
);
203 sal_Bool
addEntry( Content
& rParentFolder
,
204 const OUString
& rTitle
,
205 const OUString
& rTargetURL
,
206 const OUString
& rType
);
208 sal_Bool
createFolder( const OUString
& rNewFolderURL
,
209 sal_Bool bCreateParent
,
210 sal_Bool bFsysFolder
,
211 Content
&rNewFolder
);
213 sal_Bool
CreateNewUniqueFolderWithPrefix( const OUString
& aPath
,
214 const OUString
& aPrefix
,
215 OUString
& aNewFolderName
,
216 OUString
& aNewFolderURL
,
217 Content
& aNewFolder
);
218 OUString
CreateNewUniqueFileWithPrefix( const OUString
& aPath
,
219 const OUString
& aPrefix
,
220 const OUString
& aExt
);
222 uno::Sequence
< beans::StringPair
> ReadUINamesForTemplateDir_Impl( const OUString
& aUserPath
);
223 sal_Bool
UpdateUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
224 const OUString
& aGroupName
,
225 const OUString
& aNewFolderName
);
226 sal_Bool
ReplaceUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
227 const OUString
& aFsysGroupName
,
228 const OUString
& aOldGroupName
,
229 const OUString
& aNewGroupName
);
230 sal_Bool
RemoveUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
231 const OUString
& aGroupName
);
232 sal_Bool
WriteUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
233 const uno::Sequence
< beans::StringPair
>& aUINames
);
235 OUString
CreateNewGroupFsys( const OUString
& rGroupName
, Content
& aGroup
);
237 sal_Bool
removeContent( Content
& rContent
);
238 sal_Bool
removeContent( const OUString
& rContentURL
);
240 sal_Bool
setProperty( Content
& rContent
,
241 const OUString
& rPropName
,
242 const Any
& rPropValue
);
243 sal_Bool
getProperty( Content
& rContent
,
244 const OUString
& rPropName
,
247 void createFromContent( GroupList_Impl
& rList
,
250 sal_Bool bWriteableContent
= sal_False
);
251 void addHierGroup( GroupList_Impl
& rList
,
252 const OUString
& rTitle
,
253 const OUString
& rOwnURL
);
254 void addFsysGroup( GroupList_Impl
& rList
,
255 const OUString
& rTitle
,
256 const OUString
& rUITitle
,
257 const OUString
& rOwnURL
,
258 sal_Bool bWriteableGroup
= sal_False
);
259 void removeFromHierarchy( DocTemplates_EntryData_Impl
*pData
);
260 void addToHierarchy( GroupData_Impl
*pGroup
,
261 DocTemplates_EntryData_Impl
*pData
);
263 void removeFromHierarchy( GroupData_Impl
*pGroup
);
264 void addGroupToHierarchy( GroupData_Impl
*pGroup
);
266 void updateData( DocTemplates_EntryData_Impl
*pData
);
269 SfxDocTplService_Impl( const uno::Reference
< XComponentContext
> & xContext
);
270 ~SfxDocTplService_Impl();
272 sal_Bool
init() { if ( !mbIsInitialized
) init_Impl(); return mbIsInitialized
; }
273 Content
getContent() const { return maRootContent
; }
275 void setLocale( const Locale
& rLocale
);
278 sal_Bool
storeTemplate( const OUString
& rGroupName
,
279 const OUString
& rTemplateName
,
280 const uno::Reference
< frame::XStorable
>& rStorable
);
282 sal_Bool
addTemplate( const OUString
& rGroupName
,
283 const OUString
& rTemplateName
,
284 const OUString
& rSourceURL
);
285 sal_Bool
removeTemplate( const OUString
& rGroupName
,
286 const OUString
& rTemplateName
);
287 sal_Bool
renameTemplate( const OUString
& rGroupName
,
288 const OUString
& rOldName
,
289 const OUString
& rNewName
);
291 sal_Bool
addGroup( const OUString
& rGroupName
);
292 sal_Bool
removeGroup( const OUString
& rGroupName
);
293 sal_Bool
renameGroup( const OUString
& rOldName
,
294 const OUString
& rNewName
);
296 void update( sal_Bool bUpdateNow
);
298 void finished() { mpUpdater
= NULL
; }
301 //=============================================================================
303 class Updater_Impl
: public ::osl::Thread
306 SfxDocTplService_Impl
*mpDocTemplates
;
309 Updater_Impl( SfxDocTplService_Impl
* pTemplates
);
312 virtual void SAL_CALL
run();
313 virtual void SAL_CALL
onTerminated();
316 //=============================================================================
318 class DocTemplates_EntryData_Impl
322 OUString maTargetURL
;
323 OUString maHierarchyURL
;
325 sal_Bool mbInHierarchy
: 1;
326 sal_Bool mbInUse
: 1;
327 sal_Bool mbUpdateType
: 1;
328 sal_Bool mbUpdateLink
: 1;
331 DocTemplates_EntryData_Impl( const OUString
& rTitle
);
333 void setInUse() { mbInUse
= sal_True
; }
334 void setHierarchy( sal_Bool bInHierarchy
) { mbInHierarchy
= bInHierarchy
; }
335 void setUpdateLink( sal_Bool bUpdateLink
) { mbUpdateLink
= bUpdateLink
; }
336 void setUpdateType( sal_Bool bUpdateType
) { mbUpdateType
= bUpdateType
; }
338 sal_Bool
getInUse() const { return mbInUse
; }
339 sal_Bool
getInHierarchy() const { return mbInHierarchy
; }
340 sal_Bool
getUpdateLink() const { return mbUpdateLink
; }
341 sal_Bool
getUpdateType() const { return mbUpdateType
; }
343 const OUString
& getHierarchyURL() const { return maHierarchyURL
; }
344 const OUString
& getTargetURL() const { return maTargetURL
; }
345 const OUString
& getTitle() const { return maTitle
; }
346 const OUString
& getType() const { return maType
; }
348 void setHierarchyURL( const OUString
& rURL
) { maHierarchyURL
= rURL
; }
349 void setTargetURL( const OUString
& rURL
) { maTargetURL
= rURL
; }
350 void setType( const OUString
& rType
) { maType
= rType
; }
353 //=============================================================================
357 vector
< DocTemplates_EntryData_Impl
* > maEntries
;
359 OUString maHierarchyURL
;
360 OUString maTargetURL
;
361 sal_Bool mbInUse
: 1;
362 sal_Bool mbInHierarchy
: 1;
365 GroupData_Impl( const OUString
& rTitle
);
368 void setInUse() { mbInUse
= sal_True
; }
369 void setHierarchy( sal_Bool bInHierarchy
) { mbInHierarchy
= bInHierarchy
; }
370 void setHierarchyURL( const OUString
& rURL
) { maHierarchyURL
= rURL
; }
371 void setTargetURL( const OUString
& rURL
) { maTargetURL
= rURL
; }
373 sal_Bool
getInUse() const { return mbInUse
; }
374 sal_Bool
getInHierarchy() const { return mbInHierarchy
; }
375 const OUString
& getHierarchyURL() const { return maHierarchyURL
; }
376 const OUString
& getTargetURL() const { return maTargetURL
; }
377 const OUString
& getTitle() const { return maTitle
; }
379 DocTemplates_EntryData_Impl
* addEntry( const OUString
& rTitle
,
380 const OUString
& rTargetURL
,
381 const OUString
& rType
,
382 const OUString
& rHierURL
);
383 size_t count() { return maEntries
.size(); }
384 DocTemplates_EntryData_Impl
* getEntry( size_t nPos
) { return maEntries
[ nPos
]; }
387 //-----------------------------------------------------------------------------
388 // private SfxDocTplService_Impl
389 //-----------------------------------------------------------------------------
390 void SfxDocTplService_Impl::init_Impl()
392 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
393 uno::Reference
< task::XInteractionHandler
> xInteractionHandler(
394 task::InteractionHandler::createWithParent(xContext
, 0), uno::UNO_QUERY_THROW
);
395 maCmdEnv
= new TplTaskEnvironment( xInteractionHandler
);
397 ::osl::ClearableMutexGuard
aGuard( maMutex
);
398 sal_Bool bIsInitialized
= sal_False
;
399 sal_Bool bNeedsUpdate
= sal_False
;
404 // convert locale to string
405 OUString aLang
= maLocale
.Language
;
406 aLang
+= OUString( '-' );
407 aLang
+= maLocale
.Country
;
409 // set maRootContent to the root of the templates hierarchy. Create the
410 // entry if necessary
412 maRootURL
= OUString( TEMPLATE_ROOT_URL
);
413 maRootURL
+= OUString( '/' );
416 OUString
aTemplVersPropName( TEMPLATE_VERSION
);
417 OUString
aTemplVers( TEMPLATE_VERSION_VALUE
);
418 if ( Content::create( maRootURL
, maCmdEnv
, comphelper::getProcessComponentContext(), maRootContent
) )
422 if ( getProperty( maRootContent
, aTemplVersPropName
, aValue
)
423 && ( aValue
>>= aPropValue
)
424 && aPropValue
.equals( aTemplVers
) )
426 bIsInitialized
= sal_True
;
429 removeContent( maRootContent
);
432 if ( !bIsInitialized
)
434 if ( createFolder( maRootURL
, sal_True
, sal_False
, maRootContent
)
435 && setProperty( maRootContent
, aTemplVersPropName
, uno::makeAny( aTemplVers
) ) )
436 bIsInitialized
= sal_True
;
438 bNeedsUpdate
= sal_True
;
441 if ( bIsInitialized
)
444 m_xDocProps
.set(document::DocumentProperties::create(
445 ::comphelper::getProcessComponentContext()));
446 } catch (uno::RuntimeException
const& e
) {
447 SAL_WARN("sfx2.doc", "SfxDocTplService_Impl::init_Impl: "
448 "cannot create DocumentProperties service:" << e
.Message
);
451 OUString
const aService
= OUString( SERVICENAME_TYPEDETECTION
);
452 mxType
= uno::Reference
< XTypeDetection
> ( mxContext
->getServiceManager()->createInstanceWithContext(aService
, mxContext
), UNO_QUERY
);
460 SolarMutexClearableGuard aSolarGuard
;
462 WaitWindow_Impl
* pWin
= new WaitWindow_Impl();
465 ::osl::ClearableMutexGuard
anotherGuard( maMutex
);
469 anotherGuard
.clear();
470 SolarMutexGuard aSecondSolarGuard
;
474 else if ( needsUpdate() )
475 // the UI should be shown only on the first update
480 SAL_WARN( "sfx2.doc", "init_Impl(): Could not create root" );
483 mbIsInitialized
= bIsInitialized
;
486 //-----------------------------------------------------------------------------
487 void SfxDocTplService_Impl::getDefaultLocale()
491 ::osl::MutexGuard
aGuard( maMutex
);
494 OUString
aLocale( utl::ConfigManager::getLocale() );
495 if ( !aLocale
.isEmpty() )
497 sal_Int32 nPos
= aLocale
.indexOf( sal_Unicode( '-' ) );
500 maLocale
.Language
= aLocale
.copy( 0, nPos
);
501 nPos
= aLocale
.indexOf( sal_Unicode( '_' ), nPos
+ 1 );
505 = aLocale
.copy( maLocale
.Language
.getLength() + 1,
506 nPos
- maLocale
.Language
.getLength() - 1 );
508 = aLocale
.copy( nPos
+ 1 );
513 = aLocale
.copy( maLocale
.Language
.getLength() + 1 );
519 mbLocaleSet
= sal_True
;
524 // -----------------------------------------------------------------------
525 void SfxDocTplService_Impl::readFolderList()
527 SolarMutexGuard aGuard
;
529 ResStringArray
aShortNames( SfxResId( TEMPLATE_SHORT_NAMES_ARY
) );
530 ResStringArray
aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY
) );
532 NamePair_Impl
* pPair
;
534 sal_uInt16 nCount
= (sal_uInt16
)( std::min( aShortNames
.Count(), aLongNames
.Count() ) );
536 for ( sal_uInt16 i
=0; i
<nCount
; i
++ )
538 pPair
= new NamePair_Impl
;
539 pPair
->maShortName
= aShortNames
.GetString( i
);
540 pPair
->maLongName
= aLongNames
.GetString( i
);
542 maNames
.push_back( pPair
);
546 // -----------------------------------------------------------------------
547 OUString
SfxDocTplService_Impl::getLongName( const OUString
& rShortName
)
551 for ( size_t i
= 0, n
= maNames
.size(); i
< n
; ++i
)
553 NamePair_Impl
* pPair
= maNames
[ i
];
554 if ( pPair
->maShortName
== rShortName
)
556 aRet
= pPair
->maLongName
;
561 if ( aRet
.isEmpty() )
567 //-----------------------------------------------------------------------------
568 void SfxDocTplService_Impl::getDirList()
570 OUString
aPropName( PROPERTY_DIRLIST
);
573 // Get the template dir list
574 // TODO/LATER: let use service, register listener
576 String aDirs
= SvtPathOptions().GetTemplatePath();
577 sal_uInt16 nCount
= comphelper::string::getTokenCount(aDirs
, C_DELIM
);
579 maTemplateDirs
= Sequence
< OUString
>( nCount
);
581 uno::Reference
< util::XMacroExpander
> xExpander
= util::theMacroExpander::get(mxContext
);
582 const OUString
aPrefix(
583 "vnd.sun.star.expand:" );
585 for ( sal_uInt16 i
=0; i
<nCount
; i
++ )
587 aURL
.SetSmartProtocol( INET_PROT_FILE
);
588 aURL
.SetURL( aDirs
.GetToken( i
, C_DELIM
) );
589 maTemplateDirs
[i
] = aURL
.GetMainURL( INetURLObject::NO_DECODE
);
591 sal_Int32 nIndex
= maTemplateDirs
[i
].indexOf( aPrefix
);
592 if ( nIndex
!= -1 && xExpander
.is() )
594 maTemplateDirs
[i
] = maTemplateDirs
[i
].replaceAt(nIndex
,
597 maTemplateDirs
[i
] = xExpander
->expandMacros( maTemplateDirs
[i
] );
601 aValue
<<= maTemplateDirs
;
603 // Store the template dir list
604 setProperty( maRootContent
, aPropName
, aValue
);
607 //-----------------------------------------------------------------------------
608 sal_Bool
SfxDocTplService_Impl::needsUpdate()
610 OUString
aPropName( PROPERTY_NEEDSUPDATE
);
611 sal_Bool bNeedsUpdate
= sal_True
;
614 // Get the template dir list
615 sal_Bool bHasProperty
= getProperty( maRootContent
, aPropName
, aValue
);
618 aValue
>>= bNeedsUpdate
;
620 // the old template component also checks this state, but it is initialized from this component
621 // so if this componend was already updated the old component does not need such an update
622 ::svt::TemplateFolderCache aTempCache
;
624 bNeedsUpdate
= aTempCache
.needsUpdate();
627 aTempCache
.storeState();
632 // -----------------------------------------------------------------------
633 sal_Bool
SfxDocTplService_Impl::setTitleForURL( const OUString
& rURL
, const OUString
& aTitle
)
635 if (m_xDocProps
.is())
639 m_xDocProps
->loadFromMedium(rURL
, Sequence
<PropertyValue
>());
640 m_xDocProps
->setTitle(aTitle
);
642 uno::Reference
< embed::XStorage
> xStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
643 rURL
, embed::ElementModes::READWRITE
);
645 uno::Sequence
<beans::PropertyValue
> medium(2);
646 medium
[0].Name
= OUString("DocumentBaseURL");
647 medium
[0].Value
<<= rURL
;
648 medium
[1].Name
= OUString("URL");
649 medium
[1].Value
<<= rURL
;
651 m_xDocProps
->storeToStorage(xStorage
, medium
);
661 // -----------------------------------------------------------------------
662 sal_Bool
SfxDocTplService_Impl::getTitleFromURL( const OUString
& rURL
, OUString
& aTitle
, OUString
& aType
, sal_Bool
& bDocHasTitle
)
664 bDocHasTitle
= sal_False
;
666 if (m_xDocProps
.is())
670 m_xDocProps
->loadFromMedium(rURL
, Sequence
<PropertyValue
>());
671 aTitle
= m_xDocProps
->getTitle();
678 if ( aType
.isEmpty() && mxType
.is() )
680 OUString aDocType
= mxType
->queryTypeByURL( rURL
);
681 if ( !aDocType
.isEmpty() )
684 uno::Reference
< container::XNameAccess
> xTypeDetection( mxType
, uno::UNO_QUERY_THROW
);
685 SequenceAsHashMap
aTypeProps( xTypeDetection
->getByName( aDocType
) );
686 aType
= aTypeProps
.getUnpackedValueOrDefault(
687 OUString("MediaType"),
690 catch( uno::Exception
& )
694 if ( aTitle
.isEmpty() )
696 INetURLObject
aURL( rURL
);
698 aTitle
= aURL
.getName( INetURLObject::LAST_SEGMENT
, true,
699 INetURLObject::DECODE_WITH_CHARSET
);
702 bDocHasTitle
= sal_True
;
707 // -----------------------------------------------------------------------
708 sal_Bool
SfxDocTplService_Impl::addEntry( Content
& rParentFolder
,
709 const OUString
& rTitle
,
710 const OUString
& rTargetURL
,
711 const OUString
& rType
)
713 sal_Bool bAddedEntry
= sal_False
;
715 INetURLObject
aLinkObj( rParentFolder
.getURL() );
716 aLinkObj
.insertName( rTitle
, false,
717 INetURLObject::LAST_SEGMENT
, true,
718 INetURLObject::ENCODE_ALL
);
719 OUString aLinkURL
= aLinkObj
.GetMainURL( INetURLObject::NO_DECODE
);
723 if ( ! Content::create( aLinkURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aLink
) )
725 Sequence
< OUString
> aNames(3);
726 aNames
[0] = OUString( TITLE
);
727 aNames
[1] = OUString( IS_FOLDER
);
728 aNames
[2] = OUString( TARGET_URL
);
730 Sequence
< Any
> aValues(3);
731 aValues
[0] = makeAny( rTitle
);
732 aValues
[1] = makeAny( sal_Bool( sal_False
) );
733 aValues
[2] = makeAny( rTargetURL
);
735 OUString
aType( TYPE_LINK
);
736 OUString
aAdditionalProp( PROPERTY_TYPE
);
740 rParentFolder
.insertNewContent( aType
, aNames
, aValues
, aLink
);
741 setProperty( aLink
, aAdditionalProp
, makeAny( rType
) );
742 bAddedEntry
= sal_True
;
750 // -----------------------------------------------------------------------
751 sal_Bool
SfxDocTplService_Impl::createFolder( const OUString
& rNewFolderURL
,
752 sal_Bool bCreateParent
,
753 sal_Bool bFsysFolder
,
754 Content
&rNewFolder
)
757 sal_Bool bCreatedFolder
= sal_False
;
758 INetURLObject
aParentURL( rNewFolderURL
);
759 OUString aFolderName
= aParentURL
.getName( INetURLObject::LAST_SEGMENT
, true,
760 INetURLObject::DECODE_WITH_CHARSET
);
762 // compute the parent folder url from the new folder url
763 // and remove the final slash, because Content::create doesn't
765 aParentURL
.removeSegment();
766 if ( aParentURL
.getSegmentCount() >= 1 )
767 aParentURL
.removeFinalSlash();
769 // if the parent exists, we can continue with the creation of the
770 // new folder, we have to create the parent otherwise ( as long as
771 // bCreateParent is set to true )
772 if ( Content::create( aParentURL
.GetMainURL( INetURLObject::NO_DECODE
), maCmdEnv
, comphelper::getProcessComponentContext(), aParent
) )
776 Sequence
< OUString
> aNames(2);
777 aNames
[0] = OUString( TITLE
);
778 aNames
[1] = OUString( IS_FOLDER
);
780 Sequence
< Any
> aValues(2);
781 aValues
[0] = makeAny( aFolderName
);
782 aValues
[1] = makeAny( sal_Bool( sal_True
) );
787 aType
= OUString( TYPE_FSYS_FOLDER
);
789 aType
= OUString( TYPE_FOLDER
);
791 aParent
.insertNewContent( aType
, aNames
, aValues
, rNewFolder
);
792 bCreatedFolder
= sal_True
;
794 catch( RuntimeException
& )
796 SAL_WARN( "sfx2.doc", "createFolder(): got runtime exception" );
800 SAL_WARN( "sfx2.doc", "createFolder(): Could not create new folder" );
803 else if ( bCreateParent
)
805 // if the parent doesn't exists and bCreateParent is set to true,
806 // we try to create the parent and if this was successful, we
807 // try to create the new folder again ( but this time, we set
808 // bCreateParent to false to avoid endless recusions )
809 if ( ( aParentURL
.getSegmentCount() >= 1 ) &&
810 createFolder( aParentURL
.GetMainURL( INetURLObject::NO_DECODE
), bCreateParent
, bFsysFolder
, aParent
) )
812 bCreatedFolder
= createFolder( rNewFolderURL
, sal_False
, bFsysFolder
, rNewFolder
);
816 return bCreatedFolder
;
819 // -----------------------------------------------------------------------
820 sal_Bool
SfxDocTplService_Impl::CreateNewUniqueFolderWithPrefix( const OUString
& aPath
,
821 const OUString
& aPrefix
,
822 OUString
& aNewFolderName
,
823 OUString
& aNewFolderURL
,
824 Content
& aNewFolder
)
826 sal_Bool bCreated
= sal_False
;
827 INetURLObject
aDirPath( aPath
);
830 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
831 if ( Content::create( aDirPath
.GetMainURL( INetURLObject::NO_DECODE
), aQuietEnv
, comphelper::getProcessComponentContext(), aParent
) )
833 for ( sal_Int32 nInd
= 0; nInd
< 32000; nInd
++ )
835 OUString aTryName
= aPrefix
;
837 aTryName
+= OUString::valueOf( nInd
);
841 Sequence
< OUString
> aNames(2);
842 aNames
[0] = OUString( TITLE
);
843 aNames
[1] = OUString( IS_FOLDER
);
845 Sequence
< Any
> aValues(2);
846 aValues
[0] = makeAny( aTryName
);
847 aValues
[1] = makeAny( sal_Bool( sal_True
) );
849 OUString
aType( TYPE_FSYS_FOLDER
);
851 bCreated
= aParent
.insertNewContent( aType
, aNames
, aValues
, aNewFolder
);
853 catch( ucb::NameClashException
& )
855 // if there is already an element, retry
859 INetURLObject
aObjPath( aDirPath
);
860 aObjPath
.insertName( aTryName
, false,
861 INetURLObject::LAST_SEGMENT
, true,
862 INetURLObject::ENCODE_ALL
);
863 // if there is already an element, retry
864 // if there was another error, do not try any more
865 if ( !::utl::UCBContentHelper::Exists( aObjPath
.GetMainURL( INetURLObject::NO_DECODE
) ) )
871 aNewFolderName
= aTryName
;
872 aNewFolderURL
= aNewFolder
.get()->getIdentifier()->getContentIdentifier();
881 // -----------------------------------------------------------------------
882 OUString
SfxDocTplService_Impl::CreateNewUniqueFileWithPrefix( const OUString
& aPath
,
883 const OUString
& aPrefix
,
884 const OUString
& aExt
)
886 OUString aNewFileURL
;
887 INetURLObject
aDirPath( aPath
);
891 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
892 if ( Content::create( aDirPath
.GetMainURL( INetURLObject::NO_DECODE
), aQuietEnv
, comphelper::getProcessComponentContext(), aParent
) )
894 for ( sal_Int32 nInd
= 0; nInd
< 32000; nInd
++ )
897 sal_Bool bCreated
= sal_False
;
898 OUString aTryName
= aPrefix
;
900 aTryName
+= OUString::valueOf( nInd
);
901 if ( aExt
.toChar() != '.' )
902 aTryName
+= OUString( "." );
907 Sequence
< OUString
> aNames(2);
908 aNames
[0] = OUString( TITLE
);
909 aNames
[1] = OUString( IS_DOCUMENT
);
911 Sequence
< Any
> aValues(2);
912 aValues
[0] = makeAny( aTryName
);
913 aValues
[1] = makeAny( sal_Bool( sal_True
) );
915 OUString
aType( TYPE_FSYS_FILE
);
917 bCreated
= aParent
.insertNewContent( aType
, aNames
, aValues
, aNewFile
);
919 catch( ucb::NameClashException
& )
921 // if there is already an element, retry
925 INetURLObject
aObjPath( aPath
);
926 aObjPath
.insertName( aTryName
, false,
927 INetURLObject::LAST_SEGMENT
, true,
928 INetURLObject::ENCODE_ALL
);
929 // if there is already an element, retry
930 // if there was another error, do not try any more
931 if ( !::utl::UCBContentHelper::Exists( aObjPath
.GetMainURL( INetURLObject::NO_DECODE
) ) )
937 aNewFileURL
= aNewFile
.get()->getIdentifier()->getContentIdentifier();
946 // -----------------------------------------------------------------------
947 sal_Bool
SfxDocTplService_Impl::removeContent( Content
& rContent
)
949 sal_Bool bRemoved
= sal_False
;
952 OUString
aCmd( COMMAND_DELETE
);
953 Any aArg
= makeAny( sal_Bool( sal_True
) );
955 rContent
.executeCommand( aCmd
, aArg
);
958 catch ( RuntimeException
& ) {}
959 catch ( Exception
& ) {}
964 // -----------------------------------------------------------------------
965 sal_Bool
SfxDocTplService_Impl::removeContent( const OUString
& rContentURL
)
969 if ( Content::create( rContentURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aContent
) )
970 return removeContent( aContent
);
975 // -----------------------------------------------------------------------
976 sal_Bool
SfxDocTplService_Impl::setProperty( Content
& rContent
,
977 const OUString
& rPropName
,
978 const Any
& rPropValue
)
980 sal_Bool bPropertySet
= sal_False
;
982 // Store the property
985 Any
aPropValue( rPropValue
);
986 uno::Reference
< XPropertySetInfo
> aPropInfo
= rContent
.getProperties();
988 // check, whether or not the property exists, create it, when not
989 if ( !aPropInfo
.is() || !aPropInfo
->hasPropertyByName( rPropName
) )
991 uno::Reference
< XPropertyContainer
> xProperties( rContent
.get(), UNO_QUERY
);
992 if ( xProperties
.is() )
996 xProperties
->addProperty( rPropName
, PropertyAttribute::MAYBEVOID
, rPropValue
);
998 catch( PropertyExistException
& ) {}
999 catch( IllegalTypeException
& ) {
1000 SAL_WARN( "sfx2.doc", "IllegalTypeException" );
1002 catch( IllegalArgumentException
& ) {
1003 SAL_WARN( "sfx2.doc", "IllegalArgumentException" );
1008 // To ensure a reloctable office installation, the path to the
1009 // office installtion directory must never be stored directly.
1010 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName
) )
1013 if ( rPropValue
>>= aValue
)
1015 maRelocator
.makeRelocatableURL( aValue
);
1016 aPropValue
= makeAny( aValue
);
1020 Sequence
< OUString
> aValues
;
1021 if ( rPropValue
>>= aValues
)
1023 for ( sal_Int32 n
= 0; n
< aValues
.getLength(); n
++ )
1025 maRelocator
.makeRelocatableURL( aValues
[ n
] );
1027 aPropValue
= makeAny( aValues
);
1031 OSL_FAIL( "Unsupported property value type" );
1036 // now set the property
1038 rContent
.setPropertyValue( rPropName
, aPropValue
);
1039 bPropertySet
= sal_True
;
1041 catch ( RuntimeException
& ) {}
1042 catch ( Exception
& ) {}
1044 return bPropertySet
;
1047 // -----------------------------------------------------------------------
1048 sal_Bool
SfxDocTplService_Impl::getProperty( Content
& rContent
,
1049 const OUString
& rPropName
,
1052 sal_Bool bGotProperty
= sal_False
;
1057 uno::Reference
< XPropertySetInfo
> aPropInfo
= rContent
.getProperties();
1059 // check, whether or not the property exists
1060 if ( !aPropInfo
.is() || !aPropInfo
->hasPropertyByName( rPropName
) )
1065 // now get the property
1067 rPropValue
= rContent
.getPropertyValue( rPropName
);
1069 // To ensure a reloctable office installation, the path to the
1070 // office installtion directory must never be stored directly.
1071 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName
) )
1074 if ( rPropValue
>>= aValue
)
1076 maRelocator
.makeAbsoluteURL( aValue
);
1077 rPropValue
= makeAny( aValue
);
1081 Sequence
< OUString
> aValues
;
1082 if ( rPropValue
>>= aValues
)
1084 for ( sal_Int32 n
= 0; n
< aValues
.getLength(); n
++ )
1086 maRelocator
.makeAbsoluteURL( aValues
[ n
] );
1088 rPropValue
= makeAny( aValues
);
1092 OSL_FAIL( "Unsupported property value type" );
1097 bGotProperty
= sal_True
;
1099 catch ( RuntimeException
& ) {}
1100 catch ( Exception
& ) {}
1102 return bGotProperty
;
1105 // -----------------------------------------------------------------------
1107 bool SfxURLRelocator_Impl::propertyCanContainOfficeDir(
1108 const OUString
& rPropName
)
1110 // Note: TargetURL is handled by UCB itself (because it is a property
1111 // with a predefined semantic). Additional Core properties introduced
1112 // be a client app must be handled by the client app itself, because
1113 // the UCB does not know the semantics of those properties.
1114 return ( rPropName
== TARGET_DIR_URL
|| rPropName
== PROPERTY_DIRLIST
);
1117 //-----------------------------------------------------------------------------
1118 // public SfxDocTplService_Impl
1119 //-----------------------------------------------------------------------------
1121 SfxDocTplService_Impl::SfxDocTplService_Impl( const uno::Reference
< XComponentContext
> & xContext
)
1122 : maRelocator( xContext
)
1124 mxContext
= xContext
;
1126 mbIsInitialized
= sal_False
;
1127 mbLocaleSet
= sal_False
;
1130 //-----------------------------------------------------------------------------
1131 SfxDocTplService_Impl::~SfxDocTplService_Impl()
1133 ::osl::MutexGuard
aGuard( maMutex
);
1137 mpUpdater
->terminate();
1142 for ( size_t i
= 0, n
= maNames
.size(); i
< n
; ++i
)
1143 delete maNames
[ i
];
1147 //-----------------------------------------------------------------------------
1148 Locale
SfxDocTplService_Impl::getLocale()
1150 ::osl::MutexGuard
aGuard( maMutex
);
1158 //-----------------------------------------------------------------------------
1159 void SfxDocTplService_Impl::setLocale( const Locale
&rLocale
)
1161 ::osl::MutexGuard
aGuard( maMutex
);
1164 ( maLocale
.Language
!= rLocale
.Language
) &&
1165 ( maLocale
.Country
!= rLocale
.Country
) )
1166 mbIsInitialized
= sal_False
;
1169 mbLocaleSet
= sal_True
;
1172 //-----------------------------------------------------------------------------
1173 void SfxDocTplService_Impl::update( sal_Bool bUpdateNow
)
1175 ::osl::MutexGuard
aGuard( maMutex
);
1181 mpUpdater
= new Updater_Impl( this );
1182 mpUpdater
->create();
1186 //-----------------------------------------------------------------------------
1187 void SfxDocTplService_Impl::doUpdate()
1189 ::osl::MutexGuard
aGuard( maMutex
);
1191 OUString
aPropName( PROPERTY_NEEDSUPDATE
);
1194 aValue
<<= sal_True
;
1195 setProperty( maRootContent
, aPropName
, aValue
);
1197 GroupList_Impl aGroupList
;
1199 // get the entries from the hierarchy
1200 createFromContent( aGroupList
, maRootContent
, sal_True
);
1202 // get the entries from the template directories
1203 sal_Int32 nCountDir
= maTemplateDirs
.getLength();
1204 OUString
* pDirs
= maTemplateDirs
.getArray();
1205 Content aDirContent
;
1207 // the last directory in the list must be writable
1208 sal_Bool bWriteableDirectory
= sal_True
;
1210 // the target folder might not exist, for this reason no interaction handler should be used
1211 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
1216 if ( Content::create( pDirs
[ nCountDir
], aQuietEnv
, comphelper::getProcessComponentContext(), aDirContent
) )
1218 createFromContent( aGroupList
, aDirContent
, sal_False
, bWriteableDirectory
);
1221 bWriteableDirectory
= sal_False
;
1224 // now check the list
1225 for( size_t j
= 0, n
= aGroupList
.size(); j
< n
; ++j
)
1227 GroupData_Impl
*pGroup
= aGroupList
[ j
];
1228 if ( pGroup
->getInUse() )
1230 if ( pGroup
->getInHierarchy() )
1233 if ( Content::create( pGroup
->getHierarchyURL(), maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
1234 setProperty( aGroup
,
1235 OUString( TARGET_DIR_URL
),
1236 makeAny( pGroup
->getTargetURL() ) );
1238 size_t nCount
= pGroup
->count();
1239 for ( size_t i
=0; i
<nCount
; i
++ )
1241 DocTemplates_EntryData_Impl
*pData
= pGroup
->getEntry( i
);
1242 if ( ! pData
->getInUse() )
1244 if ( pData
->getInHierarchy() )
1245 removeFromHierarchy( pData
); // delete entry in hierarchy
1247 addToHierarchy( pGroup
, pData
); // add entry to hierarchy
1249 else if ( pData
->getUpdateType() ||
1250 pData
->getUpdateLink() )
1252 updateData( pData
);
1258 addGroupToHierarchy( pGroup
); // add group to hierarchy
1262 removeFromHierarchy( pGroup
); // delete group from hierarchy
1268 aValue
<<= sal_False
;
1269 setProperty( maRootContent
, aPropName
, aValue
);
1272 //-----------------------------------------------------------------------------
1273 uno::Sequence
< beans::StringPair
> SfxDocTplService_Impl::ReadUINamesForTemplateDir_Impl( const OUString
& aUserPath
)
1275 INetURLObject
aLocObj( aUserPath
);
1276 aLocObj
.insertName( OUString( "groupuinames.xml" ), false,
1277 INetURLObject::LAST_SEGMENT
, true,
1278 INetURLObject::ENCODE_ALL
);
1279 Content aLocContent
;
1281 // TODO/LATER: Use hashmap in future
1282 uno::Sequence
< beans::StringPair
> aUINames
;
1283 if ( Content::create( aLocObj
.GetMainURL( INetURLObject::NO_DECODE
), uno::Reference
< ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext(), aLocContent
) )
1287 uno::Reference
< io::XInputStream
> xLocStream
= aLocContent
.openStream();
1288 if ( xLocStream
.is() )
1289 aUINames
= DocTemplLocaleHelper::ReadGroupLocalizationSequence( xLocStream
, mxContext
);
1291 catch( uno::Exception
& )
1298 //-----------------------------------------------------------------------------
1299 sal_Bool
SfxDocTplService_Impl::UpdateUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
1300 const OUString
& aGroupName
,
1301 const OUString
& aNewFolderName
)
1303 uno::Sequence
< beans::StringPair
> aUINames
= ReadUINamesForTemplateDir_Impl( aUserPath
);
1304 sal_Int32 nLen
= aUINames
.getLength();
1306 // it is possible that the name is used already, but it should be checked before
1307 for ( sal_Int32 nInd
= 0; nInd
< nLen
; nInd
++ )
1308 if ( aUINames
[nInd
].First
.equals( aNewFolderName
) )
1311 aUINames
.realloc( ++nLen
);
1312 aUINames
[nLen
-1].First
= aNewFolderName
;
1313 aUINames
[nLen
-1].Second
= aGroupName
;
1315 return WriteUINamesForTemplateDir_Impl( aUserPath
, aUINames
);
1318 //-----------------------------------------------------------------------------
1319 sal_Bool
SfxDocTplService_Impl::ReplaceUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
1320 const OUString
& aDefaultFsysGroupName
,
1321 const OUString
& aOldGroupName
,
1322 const OUString
& aNewGroupName
)
1324 uno::Sequence
< beans::StringPair
> aUINames
= ReadUINamesForTemplateDir_Impl( aUserPath
);
1325 sal_Int32 nLen
= aUINames
.getLength();
1327 sal_Bool bChanged
= sal_False
;
1328 for ( sal_Int32 nInd
= 0; nInd
< nLen
; nInd
++ )
1329 if ( aUINames
[nInd
].Second
.equals( aOldGroupName
) )
1331 aUINames
[nInd
].Second
= aNewGroupName
;
1332 bChanged
= sal_True
;
1337 aUINames
.realloc( ++nLen
);
1338 aUINames
[nLen
-1].First
= aDefaultFsysGroupName
;
1339 aUINames
[nLen
-1].Second
= aNewGroupName
;
1341 return WriteUINamesForTemplateDir_Impl( aUserPath
, aUINames
);
1344 //-----------------------------------------------------------------------------
1345 sal_Bool
SfxDocTplService_Impl::RemoveUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
1346 const OUString
& aGroupName
)
1348 uno::Sequence
< beans::StringPair
> aUINames
= ReadUINamesForTemplateDir_Impl( aUserPath
);
1349 sal_Int32 nLen
= aUINames
.getLength();
1350 uno::Sequence
< beans::StringPair
> aNewUINames( nLen
);
1351 sal_Int32 nNewLen
= 0;
1353 sal_Bool bChanged
= sal_False
;
1354 for ( sal_Int32 nInd
= 0; nInd
< nLen
; nInd
++ )
1355 if ( aUINames
[nInd
].Second
.equals( aGroupName
) )
1356 bChanged
= sal_True
;
1360 aNewUINames
[nNewLen
-1].First
= aUINames
[nInd
].First
;
1361 aNewUINames
[nNewLen
-1].Second
= aUINames
[nInd
].Second
;
1364 aNewUINames
.realloc( nNewLen
);
1366 return bChanged
? WriteUINamesForTemplateDir_Impl( aUserPath
, aNewUINames
) : sal_True
;
1370 //-----------------------------------------------------------------------------
1371 sal_Bool
SfxDocTplService_Impl::WriteUINamesForTemplateDir_Impl( const OUString
& aUserPath
,
1372 const uno::Sequence
< beans::StringPair
>& aUINames
)
1374 sal_Bool bResult
= sal_False
;
1376 uno::Reference
< beans::XPropertySet
> xTempFile(
1377 io::TempFile::create(mxContext
),
1378 uno::UNO_QUERY_THROW
);
1381 uno::Any aUrl
= xTempFile
->getPropertyValue( OUString("Uri") );
1384 uno::Reference
< io::XStream
> xStream( xTempFile
, uno::UNO_QUERY_THROW
);
1385 uno::Reference
< io::XOutputStream
> xOutStream
= xStream
->getOutputStream();
1386 if ( !xOutStream
.is() )
1387 throw uno::RuntimeException();
1389 DocTemplLocaleHelper::WriteGroupLocalizationSequence( xOutStream
, aUINames
, mxContext
);
1391 // the SAX writer might close the stream
1392 xOutStream
->closeOutput();
1393 } catch( uno::Exception
& )
1396 Content
aTargetContent( aUserPath
, maCmdEnv
, comphelper::getProcessComponentContext() );
1397 Content
aSourceContent( aTempURL
, maCmdEnv
, comphelper::getProcessComponentContext() );
1398 aTargetContent
.transferContent( aSourceContent
,
1399 InsertOperation_COPY
,
1400 OUString( "groupuinames.xml" ),
1401 ucb::NameClash::OVERWRITE
,
1402 OUString( "text/xml" ) );
1405 catch ( uno::Exception
& )
1412 //-----------------------------------------------------------------------------
1413 OUString
SfxDocTplService_Impl::CreateNewGroupFsys( const OUString
& rGroupName
, Content
& aGroup
)
1415 OUString aResultURL
;
1417 if ( maTemplateDirs
.getLength() )
1419 OUString aTargetPath
= maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ];
1421 // create a new folder with the given name
1423 OUString aNewFolderName
;
1425 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1426 if ( !CreateNewUniqueFolderWithPrefix( aTargetPath
,
1431 && !CreateNewUniqueFolderWithPrefix( aTargetPath
,
1432 OUString( "UserGroup" ),
1439 if ( !UpdateUINamesForTemplateDir_Impl( aTargetPath
, rGroupName
, aNewFolderName
) )
1441 // we could not create the groupuinames for the folder, so we delete the group in the
1442 // the folder and return
1443 removeContent( aNewFolder
);
1447 // Now set the target url for this group and we are done
1448 OUString
aPropName( TARGET_DIR_URL
);
1449 Any aValue
= makeAny( aResultURL
);
1451 if ( ! setProperty( aGroup
, aPropName
, aValue
) )
1453 removeContent( aNewFolder
);
1461 //-----------------------------------------------------------------------------
1462 sal_Bool
SfxDocTplService_Impl::addGroup( const OUString
& rGroupName
)
1464 ::osl::MutexGuard
aGuard( maMutex
);
1466 // Check, whether or not there is a group with this name
1468 OUString aNewGroupURL
;
1469 INetURLObject
aNewGroupObj( maRootURL
);
1471 aNewGroupObj
.insertName( rGroupName
, false,
1472 INetURLObject::LAST_SEGMENT
, true,
1473 INetURLObject::ENCODE_ALL
);
1475 aNewGroupURL
= aNewGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1477 if ( Content::create( aNewGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aNewGroup
) ||
1478 ! createFolder( aNewGroupURL
, sal_False
, sal_False
, aNewGroup
) )
1480 // if there already was a group with this name or the new group
1481 // could not be created, we return here
1485 // Get the user template path entry ( new group will always
1486 // be added in the user template path )
1490 nIndex
= maTemplateDirs
.getLength();
1494 return sal_False
; // We don't know where to add the group
1496 aUserPath
= maTemplateDirs
[ nIndex
];
1498 // create a new folder with the given name
1500 OUString aNewFolderName
;
1501 OUString aNewFolderURL
;
1503 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1504 if ( !CreateNewUniqueFolderWithPrefix( aUserPath
,
1509 && !CreateNewUniqueFolderWithPrefix( aUserPath
,
1510 OUString( "UserGroup" ),
1515 // we could not create the folder, so we delete the group in the
1516 // hierarchy and return
1517 removeContent( aNewGroup
);
1521 if ( !UpdateUINamesForTemplateDir_Impl( aUserPath
, rGroupName
, aNewFolderName
) )
1523 // we could not create the groupuinames for the folder, so we delete the group in the
1524 // hierarchy, the folder and return
1525 removeContent( aNewGroup
);
1526 removeContent( aNewFolder
);
1530 // Now set the target url for this group and we are done
1531 OUString
aPropName( TARGET_DIR_URL
);
1532 Any aValue
= makeAny( aNewFolderURL
);
1534 if ( ! setProperty( aNewGroup
, aPropName
, aValue
) )
1536 removeContent( aNewGroup
);
1537 removeContent( aNewFolder
);
1544 //-----------------------------------------------------------------------------
1545 sal_Bool
SfxDocTplService_Impl::removeGroup( const OUString
& rGroupName
)
1547 // remove all the elements that have the prefix aTargetURL
1548 // if the group does not have other elements remove it
1550 ::osl::MutexGuard
aGuard( maMutex
);
1552 sal_Bool bResult
= sal_False
;
1554 // create the group url
1555 INetURLObject
aGroupObj( maRootURL
);
1556 aGroupObj
.insertName( rGroupName
, false,
1557 INetURLObject::LAST_SEGMENT
, true,
1558 INetURLObject::ENCODE_ALL
);
1560 // Get the target url
1562 OUString aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1564 if ( Content::create( aGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
1566 OUString
aPropName( TARGET_DIR_URL
);
1569 OUString aGroupTargetURL
;
1570 if ( getProperty( aGroup
, aPropName
, aValue
) )
1571 aValue
>>= aGroupTargetURL
;
1573 if ( aGroupTargetURL
.isEmpty() )
1574 return sal_False
; // nothing is allowed to be removed
1576 if ( !maTemplateDirs
.getLength() )
1578 OUString aGeneralTempPath
= maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ];
1580 // check that the fs location is in writeble folder and this is not a "My templates" folder
1581 INetURLObject
aGroupParentFolder( aGroupTargetURL
);
1582 if ( !aGroupParentFolder
.removeSegment()
1583 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath
,
1584 aGroupParentFolder
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1587 // now get the content of the Group
1588 uno::Reference
< XResultSet
> xResultSet
;
1589 Sequence
< OUString
> aProps( 1 );
1591 aProps
[0] = OUString(TARGET_URL
);
1595 sal_Bool bHasNonRemovable
= sal_False
;
1596 sal_Bool bHasShared
= sal_False
;
1598 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
1599 xResultSet
= aGroup
.createCursor( aProps
, eInclude
);
1601 if ( xResultSet
.is() )
1603 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY_THROW
);
1604 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
1606 while ( xResultSet
->next() )
1608 OUString
aTemplTargetURL( xRow
->getString( 1 ) );
1609 OUString aHierURL
= xContentAccess
->queryContentIdentifierString();
1611 if ( ::utl::UCBContentHelper::IsSubPath( aGroupTargetURL
, aTemplTargetURL
) )
1613 // this is a user template, and it can be removed
1614 if ( removeContent( aTemplTargetURL
) )
1615 removeContent( aHierURL
);
1617 bHasNonRemovable
= sal_True
;
1620 bHasShared
= sal_True
;
1623 if ( !bHasNonRemovable
&& !bHasShared
)
1625 if ( removeContent( aGroupTargetURL
)
1626 || !::utl::UCBContentHelper::Exists( aGroupTargetURL
) )
1628 removeContent( aGroupURL
);
1629 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath
, rGroupName
);
1630 bResult
= sal_True
; // the operation is successful only if the whole group is removed
1633 else if ( !bHasNonRemovable
)
1635 if ( removeContent( aGroupTargetURL
)
1636 || !::utl::UCBContentHelper::Exists( aGroupTargetURL
) )
1638 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath
, rGroupName
);
1639 setProperty( aGroup
, aPropName
, uno::makeAny( OUString() ) );
1644 catch ( Exception
& ) {}
1650 //-----------------------------------------------------------------------------
1651 sal_Bool
SfxDocTplService_Impl::renameGroup( const OUString
& rOldName
,
1652 const OUString
& rNewName
)
1654 ::osl::MutexGuard
aGuard( maMutex
);
1656 // create the group url
1658 INetURLObject
aGroupObj( maRootURL
);
1659 aGroupObj
.insertName( rNewName
, false,
1660 INetURLObject::LAST_SEGMENT
, true,
1661 INetURLObject::ENCODE_ALL
);
1662 OUString aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1664 // Check, if there is a group with the new name, return false
1666 if ( Content::create( aGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
1669 aGroupObj
.removeSegment();
1670 aGroupObj
.insertName( rOldName
, false,
1671 INetURLObject::LAST_SEGMENT
, true,
1672 INetURLObject::ENCODE_ALL
);
1673 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1675 // When there is no group with the old name, we can't rename it
1676 if ( ! Content::create( aGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
1679 OUString aGroupTargetURL
;
1680 // there is no need to check whether target dir url is in target path, since if the target path is changed
1681 // the target dir url should be already generated new
1682 OUString
aPropName( TARGET_DIR_URL
);
1684 if ( getProperty( aGroup
, aPropName
, aValue
) )
1685 aValue
>>= aGroupTargetURL
;
1687 if ( aGroupTargetURL
.isEmpty() )
1690 if ( !maTemplateDirs
.getLength() )
1692 OUString aGeneralTempPath
= maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ];
1694 // check that the fs location is in writeble folder and this is not a "My templates" folder
1695 INetURLObject
aGroupParentFolder( aGroupTargetURL
);
1696 if ( !aGroupParentFolder
.removeSegment()
1697 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath
,
1698 aGroupParentFolder
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1701 // check that the group can be renamed ( all the contents must be in target location )
1702 sal_Bool bCanBeRenamed
= sal_False
;
1705 uno::Reference
< XResultSet
> xResultSet
;
1706 Sequence
< OUString
> aProps( 1 );
1708 aProps
[0] = OUString(TARGET_URL
);
1709 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
1710 xResultSet
= aGroup
.createCursor( aProps
, eInclude
);
1712 if ( xResultSet
.is() )
1714 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY_THROW
);
1715 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
1717 while ( xResultSet
->next() )
1719 OUString
aTemplTargetURL( xRow
->getString( 1 ) );
1721 if ( !::utl::UCBContentHelper::IsSubPath( aGroupTargetURL
, aTemplTargetURL
) )
1722 throw uno::Exception();
1725 bCanBeRenamed
= sal_True
;
1728 catch ( Exception
& ) {}
1730 if ( bCanBeRenamed
)
1732 INetURLObject
aGroupTargetObj( aGroupTargetURL
);
1733 OUString aFsysName
= aGroupTargetObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
1735 if ( aGroupTargetObj
.removeSegment()
1736 && ReplaceUINamesForTemplateDir_Impl( aGroupTargetObj
.GetMainURL( INetURLObject::NO_DECODE
),
1741 // rename the group in the hierarchy
1742 OUString
aTitleProp( TITLE
);
1744 aTitleValue
<<= rNewName
;
1746 return setProperty( aGroup
, aTitleProp
, aTitleValue
);
1753 //-----------------------------------------------------------------------------
1754 sal_Bool
SfxDocTplService_Impl::storeTemplate( const OUString
& rGroupName
,
1755 const OUString
& rTemplateName
,
1756 const uno::Reference
< frame::XStorable
>& rStorable
)
1758 ::osl::MutexGuard
aGuard( maMutex
);
1760 // Check, whether or not there is a group with this name
1761 // Return false, if there is no group with the given name
1762 Content aGroup
, aTemplate
, aTargetGroup
, aTemplateToRemove
;
1763 OUString aGroupURL
, aTemplateURL
, aTemplateToRemoveTargetURL
;
1764 INetURLObject
aGroupObj( maRootURL
);
1765 sal_Bool bRemoveOldTemplateContent
= sal_False
;
1766 OUString sDocServiceName
;
1768 aGroupObj
.insertName( rGroupName
, false,
1769 INetURLObject::LAST_SEGMENT
, true,
1770 INetURLObject::ENCODE_ALL
);
1771 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1773 if ( ! Content::create( aGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
1776 OUString aGroupTargetURL
;
1777 OUString
aPropName( TARGET_DIR_URL
);
1779 if ( getProperty( aGroup
, aPropName
, aValue
) )
1780 aValue
>>= aGroupTargetURL
;
1783 // Check, if there's a template with the given name in this group
1784 // the target template should be overwritten if it is imported by user
1785 // in case the template is installed by office installation of by an add-in
1786 // it can not be replaced
1787 aGroupObj
.insertName( rTemplateName
, false,
1788 INetURLObject::LAST_SEGMENT
, true,
1789 INetURLObject::ENCODE_ALL
);
1790 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1792 if ( Content::create( aTemplateURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aTemplateToRemove
) )
1794 OUString
aTargetTemplPropName( TARGET_URL
);
1796 bRemoveOldTemplateContent
= sal_True
;
1797 if ( getProperty( aTemplateToRemove
, aTargetTemplPropName
, aValue
) )
1798 aValue
>>= aTemplateToRemoveTargetURL
;
1800 if ( aGroupTargetURL
.isEmpty() || !maTemplateDirs
.getLength()
1801 || (!aTemplateToRemoveTargetURL
.isEmpty() && !::utl::UCBContentHelper::IsSubPath( maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ], aTemplateToRemoveTargetURL
)) )
1802 return sal_False
; // it is not allowed to remove the template
1807 uno::Reference
< lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory();
1808 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1810 // get document service name
1811 uno::Reference
< frame::XModuleManager2
> xModuleManager( frame::ModuleManager::create(xContext
) );
1812 sDocServiceName
= xModuleManager
->identify( uno::Reference
< uno::XInterface
>( rStorable
, uno::UNO_QUERY
) );
1813 if ( sDocServiceName
.isEmpty() )
1814 throw uno::RuntimeException();
1816 // get the actual filter name
1817 OUString aFilterName
;
1819 uno::Reference
< lang::XMultiServiceFactory
> xConfigProvider
=
1820 configuration::theDefaultProvider::get( xContext
);
1822 uno::Sequence
< uno::Any
> aArgs( 1 );
1823 beans::PropertyValue aPathProp
;
1824 aPathProp
.Name
= OUString("nodepath");
1825 aPathProp
.Value
<<= OUString( "/org.openoffice.Setup/Office/Factories/" );
1826 aArgs
[0] <<= aPathProp
;
1828 uno::Reference
< container::XNameAccess
> xSOFConfig(
1829 xConfigProvider
->createInstanceWithArguments(
1830 OUString("com.sun.star.configuration.ConfigurationAccess"),
1832 uno::UNO_QUERY_THROW
);
1834 uno::Reference
< container::XNameAccess
> xApplConfig
;
1835 xSOFConfig
->getByName( sDocServiceName
) >>= xApplConfig
;
1836 if ( !xApplConfig
.is() )
1837 throw uno::RuntimeException();
1839 xApplConfig
->getByName( OUString( "ooSetupFactoryActualTemplateFilter" ) ) >>= aFilterName
;
1840 if ( aFilterName
.isEmpty() )
1841 throw uno::RuntimeException();
1843 // find the related type name
1845 uno::Reference
< container::XNameAccess
> xFilterFactory(
1846 xFactory
->createInstance( OUString("com.sun.star.document.FilterFactory") ),
1847 uno::UNO_QUERY_THROW
);
1849 uno::Sequence
< beans::PropertyValue
> aFilterData
;
1850 xFilterFactory
->getByName( aFilterName
) >>= aFilterData
;
1851 for ( sal_Int32 nInd
= 0; nInd
< aFilterData
.getLength(); nInd
++ )
1852 if ( aFilterData
[nInd
].Name
== "Type" )
1853 aFilterData
[nInd
].Value
>>= aTypeName
;
1855 if ( aTypeName
.isEmpty() )
1856 throw uno::RuntimeException();
1858 // find the mediatype and extension
1859 uno::Reference
< container::XNameAccess
> xTypeDetection
;
1863 uno::Reference
< container::XNameAccess
>( mxType
, uno::UNO_QUERY_THROW
) :
1864 uno::Reference
< container::XNameAccess
>(
1865 xFactory
->createInstance( OUString("com.sun.star.document.TypeDetection") ),
1866 uno::UNO_QUERY_THROW
);
1868 SequenceAsHashMap
aTypeProps( xTypeDetection
->getByName( aTypeName
) );
1869 uno::Sequence
< OUString
> aAllExt
=
1870 aTypeProps
.getUnpackedValueOrDefault( OUString("Extensions"), Sequence
< OUString
>() );
1871 if ( !aAllExt
.getLength() )
1872 throw uno::RuntimeException();
1874 OUString aMediaType
= aTypeProps
.getUnpackedValueOrDefault( OUString("MediaType"), OUString() );
1875 OUString aExt
= aAllExt
[0];
1877 if ( aMediaType
.isEmpty() || aExt
.isEmpty() )
1878 throw uno::RuntimeException();
1880 // construct destination url
1881 if ( aGroupTargetURL
.isEmpty() )
1883 aGroupTargetURL
= CreateNewGroupFsys( rGroupName
, aGroup
);
1885 if ( aGroupTargetURL
.isEmpty() )
1886 throw uno::RuntimeException();
1889 OUString aNewTemplateTargetURL
= CreateNewUniqueFileWithPrefix( aGroupTargetURL
, rTemplateName
, aExt
);
1890 if ( aNewTemplateTargetURL
.isEmpty() )
1892 aNewTemplateTargetURL
= CreateNewUniqueFileWithPrefix( aGroupTargetURL
, OUString( "UserTemplate" ), aExt
);
1894 if ( aNewTemplateTargetURL
.isEmpty() )
1895 throw uno::RuntimeException();
1899 uno::Sequence
< PropertyValue
> aStoreArgs( 2 );
1900 aStoreArgs
[0].Name
= OUString("FilterName");
1901 aStoreArgs
[0].Value
<<= aFilterName
;
1902 aStoreArgs
[1].Name
= OUString("DocumentTitle");
1903 aStoreArgs
[1].Value
<<= rTemplateName
;
1905 if( !::utl::UCBContentHelper::EqualURLs( aNewTemplateTargetURL
, rStorable
->getLocation() ))
1906 rStorable
->storeToURL( aNewTemplateTargetURL
, aStoreArgs
);
1910 // the storing was successful, now the old template with the same name can be removed if it existed
1911 if ( !aTemplateToRemoveTargetURL
.isEmpty() )
1913 removeContent( aTemplateToRemoveTargetURL
);
1917 * if the old template was the standard template
1918 * it is necessary to change the standard template with the new file name
1920 String sStdTmplFile
= SfxObjectFactory::GetStandardTemplate( sDocServiceName
);
1921 if ( INetURLObject( sStdTmplFile
) == INetURLObject( aTemplateToRemoveTargetURL
) )
1923 SfxObjectFactory::SetStandardTemplate( sDocServiceName
, aNewTemplateTargetURL
);
1927 if ( bRemoveOldTemplateContent
)
1928 removeContent( aTemplateToRemove
);
1930 // add the template to hierarchy
1931 return addEntry( aGroup
, rTemplateName
, aNewTemplateTargetURL
, aMediaType
);
1935 // the template was not stored
1940 //-----------------------------------------------------------------------------
1941 sal_Bool
SfxDocTplService_Impl::addTemplate( const OUString
& rGroupName
,
1942 const OUString
& rTemplateName
,
1943 const OUString
& rSourceURL
)
1945 ::osl::MutexGuard
aGuard( maMutex
);
1947 // Check, whether or not there is a group with this name
1948 // Return false, if there is no group with the given name
1949 Content aGroup
, aTemplate
, aTargetGroup
;
1950 OUString aGroupURL
, aTemplateURL
;
1951 INetURLObject
aGroupObj( maRootURL
);
1953 aGroupObj
.insertName( rGroupName
, false,
1954 INetURLObject::LAST_SEGMENT
, true,
1955 INetURLObject::ENCODE_ALL
);
1956 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1958 if ( ! Content::create( aGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
1961 // Check, if there's a template with the given name in this group
1962 // Return false, if there already is a template
1963 aGroupObj
.insertName( rTemplateName
, false,
1964 INetURLObject::LAST_SEGMENT
, true,
1965 INetURLObject::ENCODE_ALL
);
1966 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1968 if ( Content::create( aTemplateURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aTemplate
) )
1971 // get the target url of the group
1972 OUString aTargetURL
;
1973 OUString
aPropName( TARGET_DIR_URL
);
1976 if ( getProperty( aGroup
, aPropName
, aValue
) )
1977 aValue
>>= aTargetURL
;
1979 if ( aTargetURL
.isEmpty() )
1981 aTargetURL
= CreateNewGroupFsys( rGroupName
, aGroup
);
1983 if ( aTargetURL
.isEmpty() )
1987 // Get the content type
1988 OUString aTitle
, aType
, aTargetURL2
;
1990 sal_Bool bDocHasTitle
= sal_False
;
1991 if( !getTitleFromURL( rSourceURL
, aTitle
, aType
, bDocHasTitle
) )
1994 INetURLObject
aSourceObj( rSourceURL
);
1995 if ( rTemplateName
.equals( aTitle
) )
1997 // addTemplate will sometimes be called just to add an entry in the
1998 // hierarchy; the target URL and the source URL will be the same in
2000 // TODO/LATER: get rid of this old hack
2002 INetURLObject
aTargetObj( aTargetURL
);
2004 aTargetObj
.insertName( rTemplateName
, false,
2005 INetURLObject::LAST_SEGMENT
, true,
2006 INetURLObject::ENCODE_ALL
);
2007 aTargetObj
.setExtension( aSourceObj
.getExtension() );
2009 aTargetURL2
= aTargetObj
.GetMainURL( INetURLObject::NO_DECODE
);
2011 if ( aTargetURL2
== rSourceURL
)
2012 return addEntry( aGroup
, rTemplateName
, aTargetURL2
, aType
);
2015 // copy the template into the new group (targeturl)
2017 INetURLObject
aTmpURL( aSourceObj
);
2018 aTmpURL
.CutExtension();
2019 OUString aPattern
= aTmpURL
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2021 OUString aNewTemplateTargetURL
= CreateNewUniqueFileWithPrefix( aTargetURL
, aPattern
, aSourceObj
.getExtension() );
2022 INetURLObject
aNewTemplateTargetObj( aNewTemplateTargetURL
);
2023 OUString aNewTemplateTargetName
= aNewTemplateTargetObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2024 if ( aNewTemplateTargetURL
.isEmpty() || aNewTemplateTargetName
.isEmpty() )
2027 // get access to source file
2028 Content aSourceContent
;
2029 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
2030 INetURLObject
aSourceURL( rSourceURL
);
2031 if( ! Content::create( aSourceURL
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext(), aSourceContent
) )
2034 if( ! Content::create( aTargetURL
, xEnv
, comphelper::getProcessComponentContext(), aTargetGroup
) )
2037 // transfer source file
2040 if( ! aTargetGroup
.transferContent( aSourceContent
,
2041 InsertOperation_COPY
,
2042 aNewTemplateTargetName
,
2043 NameClash::OVERWRITE
,
2047 // allow to edit the added template
2048 Content aResultContent
;
2049 if ( Content::create( aNewTemplateTargetURL
, xEnv
, comphelper::getProcessComponentContext(), aResultContent
) )
2051 OUString
aPropertyName( "IsReadOnly" );
2053 sal_Bool bReadOnly
= sal_False
;
2054 if ( getProperty( aResultContent
, aPropertyName
, aProperty
) && ( aProperty
>>= bReadOnly
) && bReadOnly
)
2055 setProperty( aResultContent
, aPropertyName
, uno::makeAny( (sal_Bool
)sal_False
) );
2058 catch ( ContentCreationException
& )
2059 { return sal_False
; }
2060 catch ( Exception
& )
2061 { return sal_False
; }
2064 // either the document has title and it is the same as requested, or we have to set it
2065 sal_Bool bCorrectTitle
= ( bDocHasTitle
&& aTitle
.equals( rTemplateName
) );
2066 if ( !bCorrectTitle
)
2068 if ( !bDocHasTitle
)
2070 INetURLObject
aNewTmpObj( aNewTemplateTargetObj
);
2071 aNewTmpObj
.CutExtension();
2072 bCorrectTitle
= ( aNewTmpObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
).equals( rTemplateName
) );
2075 if ( !bCorrectTitle
)
2076 bCorrectTitle
= setTitleForURL( aNewTemplateTargetURL
, rTemplateName
);
2079 if ( bCorrectTitle
)
2081 // create a new entry in the hierarchy
2082 return addEntry( aGroup
, rTemplateName
, aNewTemplateTargetURL
, aType
);
2085 // TODO/LATER: The user could be notified here that the renaming has failed
2086 // create a new entry in the hierarchy
2087 addEntry( aGroup
, aTitle
, aNewTemplateTargetURL
, aType
);
2091 //-----------------------------------------------------------------------------
2092 sal_Bool
SfxDocTplService_Impl::removeTemplate( const OUString
& rGroupName
,
2093 const OUString
& rTemplateName
)
2095 ::osl::MutexGuard
aGuard( maMutex
);
2097 // Check, whether or not there is a group with this name
2098 // Return false, if there is no group with the given name
2099 Content aGroup
, aTemplate
;
2100 OUString aGroupURL
, aTemplateURL
;
2101 INetURLObject
aGroupObj( maRootURL
);
2103 aGroupObj
.insertName( rGroupName
, false,
2104 INetURLObject::LAST_SEGMENT
, true,
2105 INetURLObject::ENCODE_ALL
);
2106 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2108 if ( ! Content::create( aGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
2111 // Check, if there's a template with the given name in this group
2112 // Return false, if there is no template
2113 aGroupObj
.insertName( rTemplateName
, false,
2114 INetURLObject::LAST_SEGMENT
, true,
2115 INetURLObject::ENCODE_ALL
);
2116 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2118 if ( !Content::create( aTemplateURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aTemplate
) )
2121 // get the target URL from the template
2122 OUString aTargetURL
;
2123 OUString
aPropName( TARGET_URL
);
2126 if ( getProperty( aTemplate
, aPropName
, aValue
) )
2127 aValue
>>= aTargetURL
;
2129 // delete the target template
2130 if ( !aTargetURL
.isEmpty() )
2132 if ( !maTemplateDirs
.getLength()
2133 || !::utl::UCBContentHelper::IsSubPath( maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ], aTargetURL
) )
2136 removeContent( aTargetURL
);
2139 // delete the template entry
2140 return removeContent( aTemplate
);
2143 //-----------------------------------------------------------------------------
2144 sal_Bool
SfxDocTplService_Impl::renameTemplate( const OUString
& rGroupName
,
2145 const OUString
& rOldName
,
2146 const OUString
& rNewName
)
2148 ::osl::MutexGuard
aGuard( maMutex
);
2150 // Check, whether or not there is a group with this name
2151 // Return false, if there is no group with the given name
2152 Content aGroup
, aTemplate
;
2153 OUString aGroupURL
, aTemplateURL
;
2154 INetURLObject
aGroupObj( maRootURL
);
2156 aGroupObj
.insertName( rGroupName
, false,
2157 INetURLObject::LAST_SEGMENT
, true,
2158 INetURLObject::ENCODE_ALL
);
2159 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2161 if ( ! Content::create( aGroupURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
2164 // Check, if there's a template with the new name in this group
2165 // Return false, if there is one
2166 aGroupObj
.insertName( rNewName
, false,
2167 INetURLObject::LAST_SEGMENT
, true,
2168 INetURLObject::ENCODE_ALL
);
2169 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2171 if ( Content::create( aTemplateURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aTemplate
) )
2174 // Check, if there's a template with the old name in this group
2175 // Return false, if there is no template
2176 aGroupObj
.removeSegment();
2177 aGroupObj
.insertName( rOldName
, false,
2178 INetURLObject::LAST_SEGMENT
, true,
2179 INetURLObject::ENCODE_ALL
);
2180 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2182 if ( !Content::create( aTemplateURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aTemplate
) )
2185 OUString aTemplateTargetURL
;
2186 OUString
aTargetProp( TARGET_URL
);
2189 if ( getProperty( aTemplate
, aTargetProp
, aTargetValue
) )
2190 aTargetValue
>>= aTemplateTargetURL
;
2192 if ( !setTitleForURL( aTemplateTargetURL
, rNewName
) )
2195 // rename the template entry in the cache
2196 OUString
aTitleProp( TITLE
);
2198 aTitleValue
<<= rNewName
;
2200 return setProperty( aTemplate
, aTitleProp
, aTitleValue
);
2203 //-----------------------------------------------------------------------------
2205 SFX_IMPL_XSERVICEINFO( SfxDocTplService
, TEMPLATE_SERVICE_NAME
, TEMPLATE_IMPLEMENTATION_NAME
)
2206 SFX_IMPL_SINGLEFACTORY( SfxDocTplService
)
2208 //-----------------------------------------------------------------------------
2209 SfxDocTplService::SfxDocTplService( const uno::Reference
< XMultiServiceFactory
>& xFactory
)
2211 pImp
= new SfxDocTplService_Impl( comphelper::getComponentContext(xFactory
) );
2214 //-----------------------------------------------------------------------------
2216 SfxDocTplService::~SfxDocTplService()
2221 //-----------------------------------------------------------------------------
2222 //--- XLocalizable ---
2223 //-----------------------------------------------------------------------------
2225 Locale SAL_CALL
SfxDocTplService::getLocale()
2226 throw( uno::RuntimeException
)
2228 return pImp
->getLocale();
2231 //-----------------------------------------------------------------------------
2233 void SAL_CALL
SfxDocTplService::setLocale( const Locale
& rLocale
)
2234 throw( uno::RuntimeException
)
2236 pImp
->setLocale( rLocale
);
2239 //-----------------------------------------------------------------------------
2240 //--- XDocumentTemplates ---
2241 //-----------------------------------------------------------------------------
2242 uno::Reference
< ucb::XContent
> SAL_CALL
SfxDocTplService::getContent()
2243 throw( uno::RuntimeException
)
2246 return pImp
->getContent().get();
2251 //-----------------------------------------------------------------------------
2252 sal_Bool SAL_CALL
SfxDocTplService::storeTemplate( const OUString
& GroupName
,
2253 const OUString
& TemplateName
,
2254 const uno::Reference
< frame::XStorable
>& Storable
)
2255 throw( uno::RuntimeException
)
2258 return pImp
->storeTemplate( GroupName
, TemplateName
, Storable
);
2263 //-----------------------------------------------------------------------------
2264 sal_Bool SAL_CALL
SfxDocTplService::addTemplate( const OUString
& rGroupName
,
2265 const OUString
& rTemplateName
,
2266 const OUString
& rSourceURL
)
2267 throw( uno::RuntimeException
)
2270 return pImp
->addTemplate( rGroupName
, rTemplateName
, rSourceURL
);
2275 //-----------------------------------------------------------------------------
2276 sal_Bool SAL_CALL
SfxDocTplService::removeTemplate( const OUString
& rGroupName
,
2277 const OUString
& rTemplateName
)
2278 throw( uno::RuntimeException
)
2281 return pImp
->removeTemplate( rGroupName
, rTemplateName
);
2286 //-----------------------------------------------------------------------------
2287 sal_Bool SAL_CALL
SfxDocTplService::renameTemplate( const OUString
& rGroupName
,
2288 const OUString
& rOldName
,
2289 const OUString
& rNewName
)
2290 throw( uno::RuntimeException
)
2292 if ( rOldName
== rNewName
)
2296 return pImp
->renameTemplate( rGroupName
, rOldName
, rNewName
);
2301 //-----------------------------------------------------------------------------
2302 sal_Bool SAL_CALL
SfxDocTplService::addGroup( const OUString
& rGroupName
)
2303 throw( uno::RuntimeException
)
2306 return pImp
->addGroup( rGroupName
);
2311 //-----------------------------------------------------------------------------
2312 sal_Bool SAL_CALL
SfxDocTplService::removeGroup( const OUString
& rGroupName
)
2313 throw( uno::RuntimeException
)
2316 return pImp
->removeGroup( rGroupName
);
2321 //-----------------------------------------------------------------------------
2322 sal_Bool SAL_CALL
SfxDocTplService::renameGroup( const OUString
& rOldName
,
2323 const OUString
& rNewName
)
2324 throw( uno::RuntimeException
)
2326 if ( rOldName
== rNewName
)
2330 return pImp
->renameGroup( rOldName
, rNewName
);
2335 //-----------------------------------------------------------------------------
2336 void SAL_CALL
SfxDocTplService::update()
2337 throw( uno::RuntimeException
)
2340 pImp
->update( sal_True
);
2343 //------------------------------------------------------------------------
2345 Updater_Impl::Updater_Impl( SfxDocTplService_Impl
* pTemplates
)
2347 mpDocTemplates
= pTemplates
;
2350 //------------------------------------------------------------------------
2351 Updater_Impl::~Updater_Impl()
2355 //------------------------------------------------------------------------
2356 void SAL_CALL
Updater_Impl::run()
2358 mpDocTemplates
->doUpdate();
2361 //------------------------------------------------------------------------
2362 void SAL_CALL
Updater_Impl::onTerminated()
2364 mpDocTemplates
->finished();
2368 //-----------------------------------------------------------------------------
2369 WaitWindow_Impl::WaitWindow_Impl()
2370 : WorkWindow( NULL
, WB_BORDER
| WB_3DLOOK
)
2372 Rectangle aRect
= Rectangle( 0, 0, 300, 30000 );
2373 _nTextStyle
= TEXT_DRAW_CENTER
| TEXT_DRAW_VCENTER
| TEXT_DRAW_WORDBREAK
| TEXT_DRAW_MULTILINE
;
2374 _aText
= SfxResId( RID_CNT_STR_WAITING
).toString();
2375 _aRect
= GetTextRect( aRect
, _aText
, _nTextStyle
);
2377 aRect
.Right() += 2*X_OFFSET
;
2378 aRect
.Bottom() += 2*Y_OFFSET
;
2379 _aRect
.SetPos( Point( X_OFFSET
, Y_OFFSET
) );
2380 SetOutputSizePixel( aRect
.GetSize() );
2386 //-----------------------------------------------------------------------------
2387 WaitWindow_Impl::~WaitWindow_Impl()
2392 //-----------------------------------------------------------------------------
2393 void WaitWindow_Impl::Paint( const Rectangle
& /*rRect*/ )
2395 DrawText( _aRect
, _aText
, _nTextStyle
);
2398 //-----------------------------------------------------------------------------
2399 void SfxDocTplService_Impl::addHierGroup( GroupList_Impl
& rList
,
2400 const OUString
& rTitle
,
2401 const OUString
& rOwnURL
)
2403 // now get the content of the Group
2405 uno::Reference
< XResultSet
> xResultSet
;
2406 Sequence
< OUString
> aProps(3);
2408 aProps
[0] = OUString(TITLE
);
2409 aProps
[1] = OUString(TARGET_URL
);
2410 aProps
[2] = OUString(PROPERTY_TYPE
);
2414 aContent
= Content( rOwnURL
, maCmdEnv
, comphelper::getProcessComponentContext() );
2415 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
2416 xResultSet
= aContent
.createCursor( aProps
, eInclude
);
2418 catch ( ContentCreationException
& )
2420 SAL_WARN( "sfx2.doc", "addHierGroup: ContentCreationException" );
2422 catch ( Exception
& ) {}
2424 if ( xResultSet
.is() )
2426 GroupData_Impl
*pGroup
= new GroupData_Impl( rTitle
);
2427 pGroup
->setHierarchy( sal_True
);
2428 pGroup
->setHierarchyURL( rOwnURL
);
2429 rList
.push_back( pGroup
);
2431 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY
);
2432 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY
);
2436 while ( xResultSet
->next() )
2438 sal_Bool bUpdateType
= sal_False
;
2439 DocTemplates_EntryData_Impl
*pData
;
2441 OUString
aTitle( xRow
->getString( 1 ) );
2442 OUString
aTargetDir( xRow
->getString( 2 ) );
2443 OUString
aType( xRow
->getString( 3 ) );
2444 OUString aHierURL
= xContentAccess
->queryContentIdentifierString();
2446 if ( aType
.isEmpty() )
2450 sal_Bool bDocHasTitle
= sal_False
;
2451 if( !getTitleFromURL( aTargetDir
, aTmpTitle
, aType
, bDocHasTitle
) )
2453 SAL_WARN( "sfx2.doc", "addHierGroup(): template of alien format" );
2457 if ( !aType
.isEmpty() )
2458 bUpdateType
= sal_True
;
2461 pData
= pGroup
->addEntry( aTitle
, aTargetDir
, aType
, aHierURL
);
2462 pData
->setUpdateType( bUpdateType
);
2465 catch ( Exception
& ) {}
2469 //-----------------------------------------------------------------------------
2470 void SfxDocTplService_Impl::addFsysGroup( GroupList_Impl
& rList
,
2471 const OUString
& rTitle
,
2472 const OUString
& rUITitle
,
2473 const OUString
& rOwnURL
,
2474 sal_Bool bWriteableGroup
)
2478 if ( rUITitle
.isEmpty() )
2480 // reserved FS names that should not be used
2481 if ( rTitle
.compareToAscii( "wizard" ) == 0 )
2483 else if ( rTitle
.compareToAscii( "internal" ) == 0 )
2486 aTitle
= getLongName( rTitle
);
2491 if ( aTitle
.isEmpty() )
2494 GroupData_Impl
* pGroup
= NULL
;
2495 for ( size_t i
= 0, n
= rList
.size(); i
< n
; ++i
)
2497 if ( rList
[ i
]->getTitle() == aTitle
)
2499 pGroup
= rList
[ i
];
2506 pGroup
= new GroupData_Impl( aTitle
);
2507 rList
.push_back( pGroup
);
2510 if ( bWriteableGroup
)
2511 pGroup
->setTargetURL( rOwnURL
);
2515 // now get the content of the Group
2517 uno::Reference
< XResultSet
> xResultSet
;
2518 Sequence
< OUString
> aProps(1);
2519 aProps
[0] = OUString(TITLE
);
2523 // this method is only used during checking of the available template-folders
2524 // that should happen quietly
2525 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
2526 aContent
= Content( rOwnURL
, aQuietEnv
, comphelper::getProcessComponentContext() );
2527 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
2528 xResultSet
= aContent
.createCursor( aProps
, eInclude
);
2530 catch ( Exception
& ) {}
2532 if ( xResultSet
.is() )
2534 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY
);
2535 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY
);
2539 while ( xResultSet
->next() )
2541 OUString
aChildTitle( xRow
->getString( 1 ) );
2542 OUString aTargetURL
= xContentAccess
->queryContentIdentifierString();
2546 if ( aChildTitle
.compareToAscii( "sfx.tlx" ) == 0 || aChildTitle
== "groupuinames.xml" )
2549 sal_Bool bDocHasTitle
= sal_False
;
2550 if( !getTitleFromURL( aTargetURL
, aChildTitle
, aType
, bDocHasTitle
) )
2553 pGroup
->addEntry( aChildTitle
, aTargetURL
, aType
, aHierURL
);
2556 catch ( Exception
& ) {}
2560 // -----------------------------------------------------------------------
2561 void SfxDocTplService_Impl::createFromContent( GroupList_Impl
& rList
,
2563 sal_Bool bHierarchy
,
2564 sal_Bool bWriteableContent
)
2566 OUString aTargetURL
= rContent
.get()->getIdentifier()->getContentIdentifier();
2568 // when scanning the file system, we have to add the 'standard' group, too
2571 OUString aUIStdTitle
= getLongName( OUString( STANDARD_FOLDER
) );
2572 addFsysGroup( rList
, OUString(), aUIStdTitle
, aTargetURL
, bWriteableContent
);
2575 // search for predefined UI names
2576 INetURLObject
aLayerObj( aTargetURL
);
2578 // TODO/LATER: Use hashmap in future
2579 uno::Sequence
< beans::StringPair
> aUINames
;
2581 aUINames
= ReadUINamesForTemplateDir_Impl( aLayerObj
.GetMainURL( INetURLObject::NO_DECODE
) );
2583 uno::Reference
< XResultSet
> xResultSet
;
2584 Sequence
< OUString
> aProps(1);
2585 aProps
[0] = OUString(TITLE
);
2589 ResultSetInclude eInclude
= INCLUDE_FOLDERS_ONLY
;
2590 xResultSet
= rContent
.createCursor( aProps
, eInclude
);
2592 catch ( Exception
& ) {}
2594 if ( xResultSet
.is() )
2596 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY
);
2597 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY
);
2601 while ( xResultSet
->next() )
2603 // TODO/LATER: clarify the encoding of the Title
2604 OUString
aTitle( xRow
->getString( 1 ) );
2605 OUString
aTargetSubfolderURL( xContentAccess
->queryContentIdentifierString() );
2608 addHierGroup( rList
, aTitle
, aTargetSubfolderURL
);
2612 for ( sal_Int32 nInd
= 0; nInd
< aUINames
.getLength(); nInd
++ )
2613 if ( aUINames
[nInd
].First
.equals( aTitle
) )
2615 aUITitle
= aUINames
[nInd
].Second
;
2619 addFsysGroup( rList
, aTitle
, aUITitle
, aTargetSubfolderURL
, bWriteableContent
);
2623 catch ( Exception
& ) {}
2627 //-----------------------------------------------------------------------------
2628 void SfxDocTplService_Impl::removeFromHierarchy( DocTemplates_EntryData_Impl
*pData
)
2632 if ( Content::create( pData
->getHierarchyURL(), maCmdEnv
, comphelper::getProcessComponentContext(), aTemplate
) )
2634 removeContent( aTemplate
);
2638 //-----------------------------------------------------------------------------
2639 void SfxDocTplService_Impl::addToHierarchy( GroupData_Impl
*pGroup
,
2640 DocTemplates_EntryData_Impl
*pData
)
2642 Content aGroup
, aTemplate
;
2644 if ( ! Content::create( pGroup
->getHierarchyURL(), maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
2647 // Check, if there's a template with the given name in this group
2648 // Return if there is already a template
2649 INetURLObject
aGroupObj( pGroup
->getHierarchyURL() );
2651 aGroupObj
.insertName( pData
->getTitle(), false,
2652 INetURLObject::LAST_SEGMENT
, true,
2653 INetURLObject::ENCODE_ALL
);
2655 OUString aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2657 if ( Content::create( aTemplateURL
, maCmdEnv
, comphelper::getProcessComponentContext(), aTemplate
) )
2660 addEntry( aGroup
, pData
->getTitle(),
2661 pData
->getTargetURL(),
2665 //-----------------------------------------------------------------------------
2666 void SfxDocTplService_Impl::updateData( DocTemplates_EntryData_Impl
*pData
)
2670 if ( ! Content::create( pData
->getHierarchyURL(), maCmdEnv
, comphelper::getProcessComponentContext(), aTemplate
) )
2675 if ( pData
->getUpdateType() )
2677 aPropName
= OUString( PROPERTY_TYPE
);
2678 setProperty( aTemplate
, aPropName
, makeAny( pData
->getType() ) );
2681 if ( pData
->getUpdateLink() )
2683 aPropName
= OUString( TARGET_URL
);
2684 setProperty( aTemplate
, aPropName
, makeAny( pData
->getTargetURL() ) );
2688 //-----------------------------------------------------------------------------
2689 void SfxDocTplService_Impl::addGroupToHierarchy( GroupData_Impl
*pGroup
)
2691 OUString
aAdditionalProp( TARGET_DIR_URL
);
2694 INetURLObject
aNewGroupObj( maRootURL
);
2695 aNewGroupObj
.insertName( pGroup
->getTitle(), false,
2696 INetURLObject::LAST_SEGMENT
, true,
2697 INetURLObject::ENCODE_ALL
);
2699 OUString aNewGroupURL
= aNewGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2701 if ( createFolder( aNewGroupURL
, sal_False
, sal_False
, aGroup
) )
2703 setProperty( aGroup
, aAdditionalProp
, makeAny( pGroup
->getTargetURL() ) );
2704 pGroup
->setHierarchyURL( aNewGroupURL
);
2706 sal_uIntPtr nCount
= pGroup
->count();
2707 for ( sal_uIntPtr i
=0; i
<nCount
; i
++ )
2709 DocTemplates_EntryData_Impl
*pData
= pGroup
->getEntry( i
);
2710 addToHierarchy( pGroup
, pData
); // add entry to hierarchy
2715 //-----------------------------------------------------------------------------
2716 void SfxDocTplService_Impl::removeFromHierarchy( GroupData_Impl
*pGroup
)
2720 if ( Content::create( pGroup
->getHierarchyURL(), maCmdEnv
, comphelper::getProcessComponentContext(), aGroup
) )
2722 removeContent( aGroup
);
2726 // -----------------------------------------------------------------------
2727 GroupData_Impl::GroupData_Impl( const OUString
& rTitle
)
2730 mbInUse
= sal_False
;
2731 mbInHierarchy
= sal_False
;
2734 // -----------------------------------------------------------------------
2735 GroupData_Impl::~GroupData_Impl()
2737 for ( size_t i
= 0, n
= maEntries
.size(); i
< n
; ++i
)
2738 delete maEntries
[ i
];
2742 // -----------------------------------------------------------------------
2743 DocTemplates_EntryData_Impl
* GroupData_Impl::addEntry( const OUString
& rTitle
,
2744 const OUString
& rTargetURL
,
2745 const OUString
& rType
,
2746 const OUString
& rHierURL
)
2748 DocTemplates_EntryData_Impl
* pData
= NULL
;
2749 bool EntryFound
= false;
2751 for ( size_t i
= 0, n
= maEntries
.size(); i
< n
; ++i
)
2753 pData
= maEntries
[ i
];
2754 if ( pData
->getTitle() == rTitle
)
2763 pData
= new DocTemplates_EntryData_Impl( rTitle
);
2764 pData
->setTargetURL( rTargetURL
);
2765 pData
->setType( rType
);
2766 if ( !rHierURL
.isEmpty() )
2768 pData
->setHierarchyURL( rHierURL
);
2769 pData
->setHierarchy( sal_True
);
2771 maEntries
.push_back( pData
);
2775 if ( !rHierURL
.isEmpty() )
2777 pData
->setHierarchyURL( rHierURL
);
2778 pData
->setHierarchy( sal_True
);
2781 if ( pData
->getInHierarchy() )
2784 if ( rTargetURL
!= pData
->getTargetURL() )
2786 pData
->setTargetURL( rTargetURL
);
2787 pData
->setUpdateLink( sal_True
);
2794 // -----------------------------------------------------------------------
2795 DocTemplates_EntryData_Impl::DocTemplates_EntryData_Impl( const OUString
& rTitle
)
2798 mbInUse
= sal_False
;
2799 mbInHierarchy
= sal_False
;
2800 mbUpdateType
= sal_False
;
2801 mbUpdateLink
= sal_False
;
2804 // -----------------------------------------------------------------------
2805 SfxURLRelocator_Impl::SfxURLRelocator_Impl( const uno::Reference
< XComponentContext
> & xContext
)
2806 : mxContext( xContext
)
2810 // -----------------------------------------------------------------------
2811 SfxURLRelocator_Impl::~SfxURLRelocator_Impl()
2815 // -----------------------------------------------------------------------
2816 void SfxURLRelocator_Impl::initOfficeInstDirs()
2818 if ( !mxOfficeInstDirs
.is() )
2820 osl::MutexGuard
aGuard( maMutex
);
2821 if ( !mxOfficeInstDirs
.is() )
2823 OSL_ENSURE( mxContext
.is(), "No service manager!" );
2825 mxOfficeInstDirs
= theOfficeInstallationDirectories::get(mxContext
);
2830 // -----------------------------------------------------------------------
2831 void SfxURLRelocator_Impl::implExpandURL( OUString
& io_url
)
2833 const INetURLObject
aParser( io_url
);
2834 if ( aParser
.GetProtocol() != INET_PROT_VND_SUN_STAR_EXPAND
)
2837 io_url
= aParser
.GetURLPath( INetURLObject::DECODE_WITH_CHARSET
);
2840 if ( !mxMacroExpander
.is() )
2842 mxMacroExpander
.set( theMacroExpander::get(mxContext
), UNO_QUERY_THROW
);
2844 io_url
= mxMacroExpander
->expandMacros( io_url
);
2846 catch( const Exception
& )
2848 DBG_UNHANDLED_EXCEPTION();
2852 // -----------------------------------------------------------------------
2853 void SfxURLRelocator_Impl::makeRelocatableURL( OUString
& rURL
)
2855 if ( !rURL
.isEmpty() )
2857 initOfficeInstDirs();
2858 implExpandURL( rURL
);
2859 rURL
= mxOfficeInstDirs
->makeRelocatableURL( rURL
);
2863 // -----------------------------------------------------------------------
2864 void SfxURLRelocator_Impl::makeAbsoluteURL( OUString
& rURL
)
2866 if ( !rURL
.isEmpty() )
2868 initOfficeInstDirs();
2869 implExpandURL( rURL
);
2870 rURL
= mxOfficeInstDirs
->makeAbsoluteURL( rURL
);
2875 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */