Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / doc / doctempl.cxx
blob130a7c656f57f1915c8c438851fe3814b7298ecc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <limits.h>
31 #include <com/sun/star/uno/Any.h>
32 #include <osl/mutex.hxx>
33 #include <osl/thread.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/settings.hxx>
37 #include <unotools/localedatawrapper.hxx>
38 #include <unotools/pathoptions.hxx>
39 #include <tools/resary.hxx>
40 #include <tools/string.hxx>
41 #include <tools/urlobj.hxx>
42 #include <svtools/ehdl.hxx>
43 #include <svtools/sfxecode.hxx>
44 #include <comphelper/processfactory.hxx>
45 #include <ucbhelper/content.hxx>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/beans/PropertyValue.hpp>
48 #include <com/sun/star/beans/XPropertyContainer.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/beans/XPropertySetInfo.hpp>
51 #include <com/sun/star/document/XTypeDetection.hpp>
52 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
53 #include <com/sun/star/frame/XComponentLoader.hpp>
54 #include <com/sun/star/frame/DocumentTemplates.hpp>
55 #include <com/sun/star/frame/XDocumentTemplates.hpp>
56 #include <com/sun/star/io/XInputStream.hpp>
57 #include <com/sun/star/io/XPersist.hpp>
58 #include <com/sun/star/lang/XLocalizable.hpp>
59 #include <com/sun/star/sdbc/XResultSet.hpp>
60 #include <com/sun/star/sdbc/XRow.hpp>
61 #include <com/sun/star/ucb/ContentInfo.hpp>
62 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
63 #include <com/sun/star/ucb/NameClash.hpp>
64 #include <com/sun/star/ucb/TransferInfo.hpp>
65 #include <com/sun/star/ucb/XCommandProcessor.hpp>
66 #include <com/sun/star/ucb/XContent.hpp>
67 #include <com/sun/star/ucb/XContentAccess.hpp>
68 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
69 #include <com/sun/star/ucb/XAnyCompare.hpp>
70 #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
71 #include <com/sun/star/embed/ElementModes.hpp>
72 #include <com/sun/star/embed/XTransactedObject.hpp>
74 #include "sfxurlrelocator.hxx"
76 using namespace ::com::sun::star;
77 using namespace ::com::sun::star::beans;
78 using namespace ::com::sun::star::frame;
79 using namespace ::com::sun::star::io;
80 using namespace ::com::sun::star::lang;
81 using namespace ::com::sun::star::sdbc;
82 using namespace ::com::sun::star::uno;
83 using namespace ::com::sun::star::ucb;
84 using namespace ::com::sun::star::document;
85 using namespace ::rtl;
86 using namespace ::ucbhelper;
89 #include <sfx2/doctempl.hxx>
90 #include <sfx2/docfac.hxx>
91 #include <sfx2/docfile.hxx>
92 #include <sfx2/objsh.hxx>
93 #include "sfxtypes.hxx"
94 #include <sfx2/app.hxx>
95 #include "sfx2/sfxresid.hxx"
96 #include <sfx2/templatelocnames.hrc>
97 #include "doc.hrc"
98 #include <sfx2/fcontnr.hxx>
99 #include <svtools/templatefoldercache.hxx>
101 #include <comphelper/storagehelper.hxx>
102 #include <unotools/ucbhelper.hxx>
104 #include <vector>
105 using ::std::vector;
106 using ::std::advance;
108 //========================================================================
110 #define TITLE "Title"
111 #define TARGET_URL "TargetURL"
113 #define TARGET_DIR_URL "TargetDirURL"
114 #define COMMAND_TRANSFER "transfer"
116 #define SERVICENAME_DOCINFO "com.sun.star.document.DocumentProperties"
117 #define SERVICENAME_DESKTOP "com.sun.star.frame.Desktop"
119 //========================================================================
121 class RegionData_Impl;
123 namespace DocTempl {
125 class DocTempl_EntryData_Impl
127 RegionData_Impl* mpParent;
129 // the following member must be SfxObjectShellLock since it controlls that SfxObjectShell lifetime by design
130 // and users of this class expect it to be so.
131 SfxObjectShellLock mxObjShell;
133 OUString maTitle;
134 OUString maOwnURL;
135 OUString maTargetURL;
136 sal_Bool mbIsOwner : 1;
137 sal_Bool mbDidConvert: 1;
139 private:
140 RegionData_Impl* GetParent() const { return mpParent; }
142 public:
143 DocTempl_EntryData_Impl( RegionData_Impl* pParent,
144 const OUString& rTitle );
146 const OUString& GetTitle() const { return maTitle; }
147 const OUString& GetTargetURL();
148 const OUString& GetHierarchyURL();
150 void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
151 void SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
152 void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
154 int Compare( const OUString& rTitle ) const;
156 SfxObjectShellRef CreateObjectShell();
157 sal_Bool DeleteObjectShell();
162 using namespace ::DocTempl;
164 // ------------------------------------------------------------------------
166 class RegionData_Impl
168 const SfxDocTemplate_Impl* mpParent;
169 vector< DocTempl_EntryData_Impl* > maEntries;
170 OUString maTitle;
171 OUString maOwnURL;
172 OUString maTargetURL;
174 private:
175 size_t GetEntryPos( const OUString& rTitle,
176 sal_Bool& rFound ) const;
177 const SfxDocTemplate_Impl* GetParent() const { return mpParent; }
179 public:
180 RegionData_Impl( const SfxDocTemplate_Impl* pParent,
181 const OUString& rTitle );
182 ~RegionData_Impl();
184 void SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
185 void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
187 DocTempl_EntryData_Impl* GetEntry( size_t nIndex ) const;
188 DocTempl_EntryData_Impl* GetEntry( const OUString& rName ) const;
190 const OUString& GetTitle() const { return maTitle; }
191 const OUString& GetTargetURL();
192 const OUString& GetHierarchyURL();
194 size_t GetCount() const;
196 void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
198 void AddEntry( const OUString& rTitle,
199 const OUString& rTargetURL,
200 size_t *pPos = NULL );
201 void DeleteEntry( size_t nIndex );
203 int Compare( const OUString& rTitle ) const
204 { return maTitle.compareTo( rTitle ); }
205 int Compare( RegionData_Impl* pCompareWith ) const;
208 typedef vector< RegionData_Impl* > RegionList_Impl;
210 // ------------------------------------------------------------------------
212 class SfxDocTemplate_Impl : public SvRefBase
214 uno::Reference< XPersist > mxInfo;
215 uno::Reference< XDocumentTemplates > mxTemplates;
217 ::osl::Mutex maMutex;
218 OUString maRootURL;
219 OUString maStandardGroup;
220 RegionList_Impl maRegions;
221 sal_Bool mbConstructed;
223 uno::Reference< XAnyCompareFactory > m_rCompareFactory;
225 // the following member is intended to prevent clearing of the global data when it is in use
226 // TODO/LATER: it still does not make the implementation complete thread-safe
227 sal_Int32 mnLockCounter;
229 private:
230 void Clear();
232 public:
233 SfxDocTemplate_Impl();
234 ~SfxDocTemplate_Impl();
236 void IncrementLock();
237 void DecrementLock();
239 sal_Bool Construct( );
240 void CreateFromHierarchy( Content &rTemplRoot );
241 void ReInitFromComponent();
242 void AddRegion( const OUString& rTitle,
243 Content& rContent );
245 void Rescan();
247 void DeleteRegion( size_t nIndex );
249 size_t GetRegionCount() const
250 { return maRegions.size(); }
251 RegionData_Impl* GetRegion( const OUString& rName ) const;
252 RegionData_Impl* GetRegion( size_t nIndex ) const;
254 sal_Bool GetTitleFromURL( const OUString& rURL, OUString& aTitle );
255 sal_Bool InsertRegion( RegionData_Impl *pData, size_t nPos = size_t(-1) );
256 OUString GetRootURL() const { return maRootURL; }
258 uno::Reference< XDocumentTemplates > getDocTemplates() { return mxTemplates; }
261 // ------------------------------------------------------------------------
263 class DocTemplLocker_Impl
265 SfxDocTemplate_Impl& m_aDocTempl;
266 public:
267 DocTemplLocker_Impl( SfxDocTemplate_Impl& aDocTempl )
268 : m_aDocTempl( aDocTempl )
270 m_aDocTempl.IncrementLock();
273 ~DocTemplLocker_Impl()
275 m_aDocTempl.DecrementLock();
279 // ------------------------------------------------------------------------
281 #ifndef SFX_DECL_DOCTEMPLATES_DEFINED
282 #define SFX_DECL_DOCTEMPLATES_DEFINED
283 SV_DECL_REF(SfxDocTemplate_Impl)
284 #endif
286 SV_IMPL_REF(SfxDocTemplate_Impl)
288 // ------------------------------------------------------------------------
290 SfxDocTemplate_Impl *gpTemplateData = 0;
292 // -----------------------------------------------------------------------
294 static sal_Bool getTextProperty_Impl( Content& rContent,
295 const OUString& rPropName,
296 OUString& rPropValue );
298 //========================================================================
300 String SfxDocumentTemplates::GetFullRegionName
302 sal_uInt16 nIdx // Region Index
303 ) const
305 /* [Description]
307 Returns the logical name of a region and its path
309 [Return value] Reference to the Region name
314 // First: find the RegionData for the index
315 String aName;
317 DocTemplLocker_Impl aLocker( *pImp );
319 if ( pImp->Construct() )
321 RegionData_Impl *pData1 = pImp->GetRegion( nIdx );
323 if ( pData1 )
324 aName = pData1->GetTitle();
326 // --**-- here was some code which appended the path to the
327 // group if there was more than one with the same name.
328 // this should not happen anymore
331 return aName;
334 //------------------------------------------------------------------------
336 const String& SfxDocumentTemplates::GetRegionName
338 sal_uInt16 nIdx // Region Index
339 ) const
341 /* [Description]
343 Returns the logical name of a region
345 [Return value]
347 const String& Reference to the Region name
351 static String maTmpString;
353 DocTemplLocker_Impl aLocker( *pImp );
355 if ( pImp->Construct() )
357 RegionData_Impl *pData = pImp->GetRegion( nIdx );
359 if ( pData )
360 maTmpString = pData->GetTitle();
361 else
362 maTmpString.Erase();
364 else
365 maTmpString.Erase();
367 return maTmpString;
370 //------------------------------------------------------------------------
372 sal_uInt16 SfxDocumentTemplates::GetRegionCount() const
374 /* [Description]
376 Returns the number of Regions
378 [Return value]
380 sal_uInt16 Number of Regions
383 DocTemplLocker_Impl aLocker( *pImp );
385 if ( !pImp->Construct() )
386 return 0;
388 sal_uIntPtr nCount = pImp->GetRegionCount();
390 return (sal_uInt16) nCount;
393 //------------------------------------------------------------------------
395 sal_Bool SfxDocumentTemplates::IsRegionLoaded( sal_uInt16 nIdx ) const
397 DocTemplLocker_Impl aLocker( *pImp );
399 if ( !pImp->Construct() )
400 return sal_False;
402 RegionData_Impl *pData = pImp->GetRegion( nIdx );
404 if ( pData )
405 return sal_True;
406 else
407 return sal_False;
410 //------------------------------------------------------------------------
412 sal_uInt16 SfxDocumentTemplates::GetCount
414 sal_uInt16 nRegion /* Region index whose number is
415 to be determined */
417 ) const
419 /* [Description]
421 Number of entries in Region
423 [Return value] Number of entries
427 DocTemplLocker_Impl aLocker( *pImp );
429 if ( !pImp->Construct() )
430 return 0;
432 RegionData_Impl *pData = pImp->GetRegion( nRegion );
433 sal_uIntPtr nCount = 0;
435 if ( pData )
436 nCount = pData->GetCount();
438 return (sal_uInt16) nCount;
441 //------------------------------------------------------------------------
443 const String& SfxDocumentTemplates::GetName
445 sal_uInt16 nRegion, // Region Index, in which the entry lies
446 sal_uInt16 nIdx // Index of the entry
447 ) const
449 /* [Description]
451 Returns the logical name of an entry in Region
453 [Return value]
455 const String& Entry Name
459 DocTemplLocker_Impl aLocker( *pImp );
461 static String maTmpString;
463 if ( pImp->Construct() )
465 DocTempl_EntryData_Impl *pEntry = NULL;
466 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
468 if ( pRegion )
469 pEntry = pRegion->GetEntry( nIdx );
471 if ( pEntry )
472 maTmpString = pEntry->GetTitle();
473 else
474 maTmpString.Erase();
476 else
477 maTmpString.Erase();
479 return maTmpString;
482 //------------------------------------------------------------------------
484 String SfxDocumentTemplates::GetFileName
486 sal_uInt16 nRegion, // Region Index, in which the entry lies
487 sal_uInt16 nIdx // Index of the entry
488 ) const
490 /* [Description]
492 Returns the file name of an entry in Region
494 [Return value] File name of the entry
497 DocTemplLocker_Impl aLocker( *pImp );
499 if ( !pImp->Construct() )
500 return String();
502 DocTempl_EntryData_Impl *pEntry = NULL;
503 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
505 if ( pRegion )
506 pEntry = pRegion->GetEntry( nIdx );
508 if ( pEntry )
510 INetURLObject aURLObj( pEntry->GetTargetURL() );
511 return aURLObj.getName( INetURLObject::LAST_SEGMENT, true,
512 INetURLObject::DECODE_WITH_CHARSET );
514 else
515 return String();
518 //------------------------------------------------------------------------
520 String SfxDocumentTemplates::GetPath
522 sal_uInt16 nRegion, // Region Index, in which the entry lies
523 sal_uInt16 nIdx // Index of the entry
524 ) const
526 /* [Description]
528 Returns the file name with full path to the file assigned to an entry
530 [Return value]
532 String File name with full path
535 DocTemplLocker_Impl aLocker( *pImp );
537 if ( !pImp->Construct() )
538 return String();
540 DocTempl_EntryData_Impl *pEntry = NULL;
541 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
543 if ( pRegion )
544 pEntry = pRegion->GetEntry( nIdx );
546 if ( pEntry )
547 return pEntry->GetTargetURL();
548 else
549 return String();
552 //------------------------------------------------------------------------
554 ::rtl::OUString SfxDocumentTemplates::GetTemplateTargetURLFromComponent( const ::rtl::OUString& aGroupName,
555 const ::rtl::OUString& aTitle )
557 DocTemplLocker_Impl aLocker( *pImp );
559 INetURLObject aTemplateObj( pImp->GetRootURL() );
561 aTemplateObj.insertName( aGroupName, false,
562 INetURLObject::LAST_SEGMENT, true,
563 INetURLObject::ENCODE_ALL );
565 aTemplateObj.insertName( aTitle, false,
566 INetURLObject::LAST_SEGMENT, true,
567 INetURLObject::ENCODE_ALL );
570 ::rtl::OUString aResult;
571 Content aTemplate;
572 uno::Reference< XCommandEnvironment > aCmdEnv;
573 if ( Content::create( aTemplateObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv, aTemplate ) )
575 OUString aPropName( TARGET_URL );
576 getTextProperty_Impl( aTemplate, aPropName, aResult );
577 aResult = SvtPathOptions().SubstituteVariable( aResult );
580 return aResult;
583 //------------------------------------------------------------------------
585 /** Convert a resource string - a template name - to its localised pair if it exists.
586 @param nSourceResIds
587 Resource ID where the list of original en-US template names begin.
588 @param nDestResIds
589 Resource ID where the list of localised template names begin.
590 @param nCount
591 The number of names that have been localised.
592 @param rString
593 Name to be translated.
594 @return
595 The localised pair of rString or rString if the former does not exist.
597 OUString SfxDocumentTemplates::ConvertResourceString (
598 int nSourceResIds, int nDestResIds, int nCount, const OUString& rString )
600 for( int i = 0; i < nCount; ++i )
602 if( rString == SFX2_RESSTR(nSourceResIds + i))
603 return SFX2_RESSTR(nDestResIds + i);
605 return rString;
608 //------------------------------------------------------------------------
610 sal_Bool SfxDocumentTemplates::CopyOrMove
612 sal_uInt16 nTargetRegion, // Target Region Index
613 sal_uInt16 nTargetIdx, // Target position Index
614 sal_uInt16 nSourceRegion, // Source Region Index
615 sal_uInt16 nSourceIdx, /* Index to be copied / to moved template */
616 sal_Bool bMove // Copy / Move
619 /* [Description]
621 Copy or move a document template
623 [Return value]
625 sal_Bool sal_True, Action could be performed
626 sal_False, Action could not be performed
628 [Cross-references]
630 <SfxDocumentTemplates::Move(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
631 <SfxDocumentTemplates::Copy(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
635 /* to perform a copy or move, we need to send a transfer command to
636 the destination folder with the URL of the source as parameter.
637 ( If the destination content doesn't support the transfer command,
638 we could try a copy ( and delete ) instead. )
639 We need two transfers ( one for the real template and one for its
640 representation in the hierarchy )
644 DocTemplLocker_Impl aLocker( *pImp );
646 if ( !pImp->Construct() )
647 return sal_False;
649 // Don't copy or move any folders
650 if( nSourceIdx == USHRT_MAX )
651 return sal_False ;
653 if ( nSourceRegion == nTargetRegion )
655 SAL_WARN( "sfx2.doc", "Don't know, what to do!" );
656 return sal_False;
659 RegionData_Impl *pSourceRgn = pImp->GetRegion( nSourceRegion );
660 if ( !pSourceRgn )
661 return sal_False;
663 DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nSourceIdx );
664 if ( !pSource )
665 return sal_False;
667 RegionData_Impl *pTargetRgn = pImp->GetRegion( nTargetRegion );
668 if ( !pTargetRgn )
669 return sal_False;
671 OUString aTitle = pSource->GetTitle();
673 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
675 if ( xTemplates->addTemplate( pTargetRgn->GetTitle(),
676 aTitle,
677 pSource->GetTargetURL() ) )
680 INetURLObject aSourceObj( pSource->GetTargetURL() );
682 ::rtl::OUString aNewTargetURL = GetTemplateTargetURLFromComponent( pTargetRgn->GetTitle(), aTitle );
683 if ( aNewTargetURL.isEmpty() )
684 return sal_False;
686 if ( bMove )
688 // --**-- delete the original file
689 sal_Bool bDeleted = xTemplates->removeTemplate( pSourceRgn->GetTitle(),
690 pSource->GetTitle() );
691 if ( bDeleted )
692 pSourceRgn->DeleteEntry( nSourceIdx );
693 else
695 if ( xTemplates->removeTemplate( pTargetRgn->GetTitle(), aTitle ) )
696 return sal_False; // will trigger tetry with copy instead of move
698 // if it is not possible to remove just created template ( must be possible! )
699 // it is better to report success here, since at least the copy has succeeded
700 // TODO/LATER: solve it more gracefully in future
704 // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
705 size_t temp_nTargetIdx = nTargetIdx;
706 pTargetRgn->AddEntry( aTitle, aNewTargetURL, &temp_nTargetIdx );
708 return sal_True;
711 // --**-- if the current file is opened,
712 // it must be re-opened afterwards.
714 return sal_False;
717 //------------------------------------------------------------------------
719 sal_Bool SfxDocumentTemplates::Move
721 sal_uInt16 nTargetRegion, // Target Region Index
722 sal_uInt16 nTargetIdx, // Target position Index
723 sal_uInt16 nSourceRegion, // Source Region Index
724 sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
727 /* [Description]
729 Moving a template
731 [Return value]
733 sal_Bool sal_True, Action could be performed
734 sal_False, Action could not be performed
736 [Cross-references]
738 <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
741 DocTemplLocker_Impl aLocker( *pImp );
743 return CopyOrMove( nTargetRegion, nTargetIdx,
744 nSourceRegion, nSourceIdx, sal_True );
747 //------------------------------------------------------------------------
749 sal_Bool SfxDocumentTemplates::Copy
751 sal_uInt16 nTargetRegion, // Target Region Index
752 sal_uInt16 nTargetIdx, // Target position Index
753 sal_uInt16 nSourceRegion, // Source Region Index
754 sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
757 /* [Description]
759 Copying a template
761 [Return value]
763 sal_Bool sal_True, Action could be performed
764 sal_False, Action could not be performed
766 [Cross-references]
768 <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
772 DocTemplLocker_Impl aLocker( *pImp );
774 return CopyOrMove( nTargetRegion, nTargetIdx,
775 nSourceRegion, nSourceIdx, sal_False );
778 //------------------------------------------------------------------------
780 sal_Bool SfxDocumentTemplates::CopyTo
782 sal_uInt16 nRegion, // Region of the template to be exported
783 sal_uInt16 nIdx, // Index of the template to be exported
784 const String& rName /* File name under which the template is to
785 be created */
786 ) const
788 /* [Description]
790 Exporting a template into the file system
792 [Return value]
794 sal_Bool sal_True, Action could be performed
795 sal_False, Action could not be performed
797 [Cross-references]
799 <SfxDocumentTemplates::CopyFrom(sal_uInt16,sal_uInt16,String&)>
803 DocTemplLocker_Impl aLocker( *pImp );
805 if ( ! pImp->Construct() )
806 return sal_False;
808 RegionData_Impl *pSourceRgn = pImp->GetRegion( nRegion );
809 if ( !pSourceRgn )
810 return sal_False;
812 DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nIdx );
813 if ( !pSource )
814 return sal_False;
816 INetURLObject aTargetURL( rName );
818 OUString aTitle( aTargetURL.getName( INetURLObject::LAST_SEGMENT, true,
819 INetURLObject::DECODE_WITH_CHARSET ) );
820 aTargetURL.removeSegment();
822 OUString aParentURL = aTargetURL.GetMainURL( INetURLObject::NO_DECODE );
824 uno::Reference< XCommandEnvironment > aCmdEnv;
825 Content aTarget;
829 aTarget = Content( aParentURL, aCmdEnv );
831 TransferInfo aTransferInfo;
832 aTransferInfo.MoveData = sal_False;
833 aTransferInfo.SourceURL = pSource->GetTargetURL();
834 aTransferInfo.NewTitle = aTitle;
835 aTransferInfo.NameClash = NameClash::OVERWRITE;
837 Any aArg = makeAny( aTransferInfo );
838 OUString aCmd( COMMAND_TRANSFER );
840 aTarget.executeCommand( aCmd, aArg );
842 catch ( ContentCreationException& )
843 { return sal_False; }
844 catch ( Exception& )
845 { return sal_False; }
847 return sal_True;
850 //------------------------------------------------------------------------
852 sal_Bool SfxDocumentTemplates::CopyFrom
854 sal_uInt16 nRegion, /* Region in which the template is to be
855 imported */
856 sal_uInt16 nIdx, // Index of the new template in this Region
857 String& rName /* File name of the template to be imported
858 as an out parameter of the (automatically
859 generated from the file name) logical name
860 of the template */
863 /* [Description]
865 Import a template from the file system
867 [Return value] Sucess (sal_True) or serfpTargetDirectory->GetContent());
869 sal_Bool sal_True, Action could be performed
870 sal_False, Action could not be performed
872 [Cross-references]
874 <SfxDocumentTemplates::CopyTo(sal_uInt16,sal_uInt16,const String&)>
878 DocTemplLocker_Impl aLocker( *pImp );
880 if ( ! pImp->Construct() )
881 return sal_False;
883 RegionData_Impl *pTargetRgn = pImp->GetRegion( nRegion );
885 if ( !pTargetRgn )
886 return sal_False;
888 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
889 if ( !xTemplates.is() )
890 return sal_False;
892 OUString aTitle;
893 sal_Bool bTemplateAdded = sal_False;
895 if( pImp->GetTitleFromURL( rName, aTitle ) )
897 bTemplateAdded = xTemplates->addTemplate( pTargetRgn->GetTitle(), aTitle, rName );
899 else
901 OUString aService( SERVICENAME_DESKTOP );
902 uno::Reference< XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( aService ),
903 UNO_QUERY );
905 Sequence< PropertyValue > aArgs( 1 );
906 aArgs[0].Name = ::rtl::OUString("Hidden");
907 aArgs[0].Value <<= sal_True;
909 INetURLObject aTemplURL( rName );
910 uno::Reference< XDocumentPropertiesSupplier > xDocPropsSupplier;
911 uno::Reference< XStorable > xStorable;
914 xStorable = uno::Reference< XStorable >(
915 xDesktop->loadComponentFromURL( aTemplURL.GetMainURL(INetURLObject::NO_DECODE),
916 OUString("_blank"),
918 aArgs ),
919 UNO_QUERY );
921 xDocPropsSupplier = uno::Reference< XDocumentPropertiesSupplier >(
922 xStorable, UNO_QUERY );
924 catch( Exception& )
928 if( xStorable.is() )
930 // get Title from XDocumentPropertiesSupplier
931 if( xDocPropsSupplier.is() )
933 uno::Reference< XDocumentProperties > xDocProps
934 = xDocPropsSupplier->getDocumentProperties();
935 if (xDocProps.is() ) {
936 aTitle = xDocProps->getTitle();
940 if( aTitle.isEmpty() )
942 INetURLObject aURL( aTemplURL );
943 aURL.CutExtension();
944 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
945 INetURLObject::DECODE_WITH_CHARSET );
948 // write a template using XStorable interface
949 bTemplateAdded = xTemplates->storeTemplate( pTargetRgn->GetTitle(), aTitle, xStorable );
954 if( bTemplateAdded )
956 INetURLObject aTemplObj( pTargetRgn->GetHierarchyURL() );
957 aTemplObj.insertName( aTitle, false,
958 INetURLObject::LAST_SEGMENT, true,
959 INetURLObject::ENCODE_ALL );
960 OUString aTemplURL = aTemplObj.GetMainURL( INetURLObject::NO_DECODE );
962 uno::Reference< XCommandEnvironment > aCmdEnv;
963 Content aTemplCont;
965 if( Content::create( aTemplURL, aCmdEnv, aTemplCont ) )
967 OUString aTemplName;
968 OUString aPropName( TARGET_URL );
970 if( getTextProperty_Impl( aTemplCont, aPropName, aTemplName ) )
972 if ( nIdx == USHRT_MAX )
973 nIdx = 0;
974 else
975 nIdx += 1;
977 // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
978 size_t temp_nIdx = nIdx;
979 pTargetRgn->AddEntry( aTitle, aTemplName, &temp_nIdx );
980 rName = aTitle;
981 return sal_True;
983 else
985 DBG_ASSERT( sal_False, "CopyFrom(): The content should contain target URL!" );
988 else
990 DBG_ASSERT( sal_False, "CopyFrom(): The content just was created!" );
994 return sal_False;
997 //------------------------------------------------------------------------
999 sal_Bool SfxDocumentTemplates::Delete
1001 sal_uInt16 nRegion, // Region Index
1002 sal_uInt16 nIdx /* Index of the entry or USHRT_MAX,
1003 if a directory is meant. */
1006 /* [Description]
1008 Deleting an entry or a directory
1010 [Return value]
1012 sal_Bool sal_True, Action could be performed
1013 sal_False, Action could not be performed
1015 [Cross-references]
1017 <SfxDocumentTemplates::InsertDir(const String&,sal_uInt16)>
1018 <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
1022 DocTemplLocker_Impl aLocker( *pImp );
1024 /* delete the template or folder in the hierarchy and in the
1025 template folder by sending a delete command to the content.
1026 Then remove the data from the lists
1028 if ( ! pImp->Construct() )
1029 return sal_False;
1031 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1033 if ( !pRegion )
1034 return sal_False;
1036 sal_Bool bRet;
1037 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1039 if ( nIdx == USHRT_MAX )
1041 bRet = xTemplates->removeGroup( pRegion->GetTitle() );
1042 if ( bRet )
1043 pImp->DeleteRegion( nRegion );
1045 else
1047 DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
1049 if ( !pEntry )
1050 return sal_False;
1052 bRet = xTemplates->removeTemplate( pRegion->GetTitle(),
1053 pEntry->GetTitle() );
1054 if( bRet )
1055 pRegion->DeleteEntry( nIdx );
1058 return bRet;
1061 //------------------------------------------------------------------------
1063 sal_Bool SfxDocumentTemplates::InsertDir
1065 const String& rText, // the logical name of the new Region
1066 sal_uInt16 nRegion // Region Index
1069 /* [Description]
1071 Insert an index
1073 [Return value]
1075 sal_Bool sal_True, Action could be performed
1076 sal_False, Action could not be performed
1078 [Cross-references]
1080 <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
1083 DocTemplLocker_Impl aLocker( *pImp );
1085 if ( ! pImp->Construct() )
1086 return sal_False;
1088 RegionData_Impl *pRegion = pImp->GetRegion( rText );
1090 if ( pRegion )
1091 return sal_False;
1093 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1095 if ( xTemplates->addGroup( rText ) )
1097 RegionData_Impl* pNewRegion = new RegionData_Impl( pImp, rText );
1099 if ( ! pImp->InsertRegion( pNewRegion, nRegion ) )
1101 delete pNewRegion;
1102 return sal_False;
1104 return sal_True;
1107 return sal_False;
1110 //------------------------------------------------------------------------
1112 sal_Bool SfxDocumentTemplates::SetName
1114 const String& rName, // Der zu setzende Name
1115 sal_uInt16 nRegion, // Region Index
1116 sal_uInt16 nIdx /* Index of the entry oder USHRT_MAX,
1117 if a directory is meant. */
1120 /* [Description]
1122 Change the name of an entry or a directory
1124 [Return value]
1126 sal_Bool sal_True, Action could be performed
1127 sal_False, Action could not be performed
1132 DocTemplLocker_Impl aLocker( *pImp );
1134 if ( ! pImp->Construct() )
1135 return sal_False;
1137 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1138 DocTempl_EntryData_Impl *pEntry = NULL;
1140 if ( !pRegion )
1141 return sal_False;
1143 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1144 OUString aEmpty;
1146 if ( nIdx == USHRT_MAX )
1148 if ( pRegion->GetTitle() == OUString( rName ) )
1149 return sal_True;
1151 // we have to rename a region
1152 if ( xTemplates->renameGroup( pRegion->GetTitle(), rName ) )
1154 pRegion->SetTitle( rName );
1155 pRegion->SetTargetURL( aEmpty );
1156 pRegion->SetHierarchyURL( aEmpty );
1157 return sal_True;
1160 else
1162 pEntry = pRegion->GetEntry( nIdx );
1164 if ( !pEntry )
1165 return sal_False;
1167 if ( pEntry->GetTitle() == OUString( rName ) )
1168 return sal_True;
1170 if ( xTemplates->renameTemplate( pRegion->GetTitle(),
1171 pEntry->GetTitle(),
1172 rName ) )
1174 pEntry->SetTitle( rName );
1175 pEntry->SetTargetURL( aEmpty );
1176 pEntry->SetHierarchyURL( aEmpty );
1177 return sal_True;
1181 return sal_False;
1184 //------------------------------------------------------------------------
1186 sal_Bool SfxDocumentTemplates::Rescan()
1188 /* [Description]
1190 Comparison of administrative data with the current state on disk.
1191 The logical name for which no file exists, will be removed from the
1192 administrative structure. Files for which no record exists will be included.
1194 [Return value]
1196 sal_Bool sal_True, Action could be performed
1197 sal_False, Action could not be performed
1199 [Cross-references]
1201 <SfxTemplateDir::Scan(sal_Bool bDirectory, sal_Bool bSave)>
1202 <SfxTemplateDir::Freshen(const SfxTemplateDir &rNew)>
1205 if ( !pImp->Construct() )
1206 return sal_False;
1208 pImp->Rescan();
1210 return sal_True;
1213 //------------------------------------------------------------------------
1215 SfxObjectShellRef SfxDocumentTemplates::CreateObjectShell
1217 sal_uInt16 nRegion, // Region Index
1218 sal_uInt16 nIdx // Index of the entry
1221 /* [Description]
1223 Access to the document shell of an entry
1225 [Return value]
1227 SfxObjectShellRef Referece to the ObjectShell
1229 [Cross-references]
1231 <SfxTemplateDirEntry::CreateObjectShell()>
1232 <SfxDocumentTemplates::DeleteObjectShell(sal_uInt16, sal_uInt16)>
1236 DocTemplLocker_Impl aLocker( *pImp );
1238 if ( !pImp->Construct() )
1239 return NULL;
1241 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1242 DocTempl_EntryData_Impl *pEntry = NULL;
1244 if ( pRegion )
1245 pEntry = pRegion->GetEntry( nIdx );
1247 if ( pEntry )
1248 return pEntry->CreateObjectShell();
1249 else
1250 return NULL;
1253 //------------------------------------------------------------------------
1255 sal_Bool SfxDocumentTemplates::DeleteObjectShell
1257 sal_uInt16 nRegion, // Region Index
1258 sal_uInt16 nIdx // Index of the entry
1261 /* [Description]
1263 Releasing the ObjectShell of an entry
1265 [Return value]
1267 sal_Bool sal_True, Action could be performed
1268 sal_False, Action could not be performed
1270 [Cross-references]
1272 <SfxTemplateDirEntry::DeleteObjectShell()>
1273 <SfxDocumentTemplates::CreateObjectShell(sal_uInt16, sal_uInt16)>
1277 DocTemplLocker_Impl aLocker( *pImp );
1279 if ( ! pImp->Construct() )
1280 return sal_True;
1282 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1283 DocTempl_EntryData_Impl *pEntry = NULL;
1285 if ( pRegion )
1286 pEntry = pRegion->GetEntry( nIdx );
1288 if ( pEntry )
1289 return pEntry->DeleteObjectShell();
1290 else
1291 return sal_True;
1294 //------------------------------------------------------------------------
1296 sal_Bool SfxDocumentTemplates::GetFull
1298 const String &rRegion, // Region Name
1299 const String &rName, // Template Name
1300 String &rPath // Out: Path + File name
1303 /* [Description]
1305 Returns Path + File name of the template specified by rRegion and rName.
1307 [Return value]
1309 sal_Bool sal_True, Action could be performed
1310 sal_False, Action could not be performed
1312 [Cross-references]
1314 <SfxDocumentTemplates::GetLogicNames(const String&,String&,String&)>
1318 DocTemplLocker_Impl aLocker( *pImp );
1320 // We don't search for empty names!
1321 if ( ! rName.Len() )
1322 return sal_False;
1324 if ( ! pImp->Construct() )
1325 return sal_False;
1327 DocTempl_EntryData_Impl* pEntry = NULL;
1328 const sal_uInt16 nCount = GetRegionCount();
1330 for ( sal_uInt16 i = 0; i < nCount; ++i )
1332 RegionData_Impl *pRegion = pImp->GetRegion( i );
1334 if( pRegion &&
1335 ( !rRegion.Len() || ( rRegion == String( pRegion->GetTitle() ) ) ) )
1337 pEntry = pRegion->GetEntry( rName );
1339 if ( pEntry )
1341 rPath = pEntry->GetTargetURL();
1342 break;
1347 return ( pEntry != NULL );
1350 //------------------------------------------------------------------------
1352 sal_Bool SfxDocumentTemplates::GetLogicNames
1354 const String &rPath, // Full Path to the template
1355 String &rRegion, // Out: Region name
1356 String &rName // Out: Template name
1357 ) const
1359 /* [Description]
1361 Returns and logical path name to the template specified by rPath
1363 [Return value]
1365 sal_Bool sal_True, Action could be performed
1366 sal_False, Action could not be performed
1368 [Cross-references]
1370 <SfxDocumentTemplates::GetFull(const String&,const String&,DirEntry&)>
1374 DocTemplLocker_Impl aLocker( *pImp );
1376 if ( ! pImp->Construct() )
1377 return sal_False;
1379 INetURLObject aFullPath;
1381 aFullPath.SetSmartProtocol( INET_PROT_FILE );
1382 aFullPath.SetURL( rPath );
1383 OUString aPath( aFullPath.GetMainURL( INetURLObject::NO_DECODE ) );
1385 RegionData_Impl *pData = NULL;
1386 DocTempl_EntryData_Impl *pEntry = NULL;
1387 sal_Bool bFound = sal_False;
1389 sal_uIntPtr nCount = GetRegionCount();
1391 for ( sal_uIntPtr i=0; !bFound && (i<nCount); i++ )
1393 pData = pImp->GetRegion( i );
1394 if ( pData )
1396 sal_uIntPtr nChildCount = pData->GetCount();
1398 for ( sal_uIntPtr j=0; !bFound && (j<nChildCount); j++ )
1400 pEntry = pData->GetEntry( j );
1401 if ( pEntry->GetTargetURL() == aPath )
1403 bFound = sal_True;
1409 if ( bFound )
1411 rRegion = pData->GetTitle();
1412 rName = pEntry->GetTitle();
1415 return bFound;
1418 //------------------------------------------------------------------------
1420 SfxDocumentTemplates::SfxDocumentTemplates()
1422 /* [Description]
1424 Constructor
1427 if ( !gpTemplateData )
1428 gpTemplateData = new SfxDocTemplate_Impl;
1430 pImp = gpTemplateData;
1433 //-------------------------------------------------------------------------
1435 void SfxDocumentTemplates::Construct()
1437 // Delayed build-up of administrative data
1442 //------------------------------------------------------------------------
1444 SfxDocumentTemplates::~SfxDocumentTemplates()
1446 /* [Description]
1448 Destructor
1449 Release of administrative data
1453 pImp = NULL;
1456 void SfxDocumentTemplates::Update( sal_Bool _bSmart )
1458 if ( !_bSmart // don't be smart
1459 || ::svt::TemplateFolderCache( sal_True ).needsUpdate() // update is really necessary
1462 if ( pImp->Construct() )
1463 pImp->Rescan();
1467 void SfxDocumentTemplates::ReInitFromComponent()
1469 pImp->ReInitFromComponent();
1473 sal_Bool SfxDocumentTemplates::HasUserContents( sal_uInt16 nRegion, sal_uInt16 nIdx ) const
1475 DocTemplLocker_Impl aLocker( *pImp );
1477 sal_Bool bResult = sal_False;
1479 RegionData_Impl* pRegion = pImp->GetRegion( nRegion );
1481 if ( pRegion )
1483 ::rtl::OUString aRegionTargetURL = pRegion->GetTargetURL();
1484 if ( !aRegionTargetURL.isEmpty() )
1486 sal_uInt16 nLen = 0;
1487 sal_uInt16 nStartInd = 0;
1489 if( nIdx == USHRT_MAX )
1491 // this is a folder
1492 // check whether there is at least one editable template
1493 nLen = ( sal_uInt16 )pRegion->GetCount();
1494 nStartInd = 0;
1495 if ( nLen == 0 )
1496 bResult = sal_True; // the writing part of empty folder with writing URL can be removed
1498 else
1500 // this is a template
1501 // check whether the template is inserted by user
1502 nLen = 1;
1503 nStartInd = nIdx;
1506 for ( sal_uInt16 nInd = nStartInd; nInd < nStartInd + nLen; nInd++ )
1508 DocTempl_EntryData_Impl* pEntryData = pRegion->GetEntry( nInd );
1509 if ( pEntryData )
1511 ::rtl::OUString aEntryTargetURL = pEntryData->GetTargetURL();
1512 if ( !aEntryTargetURL.isEmpty()
1513 && ::utl::UCBContentHelper::IsSubPath( aRegionTargetURL, aEntryTargetURL ) )
1515 bResult = sal_True;
1516 break;
1523 return bResult;
1526 // -----------------------------------------------------------------------
1527 DocTempl_EntryData_Impl::DocTempl_EntryData_Impl( RegionData_Impl* pParent,
1528 const OUString& rTitle )
1530 mpParent = pParent;
1531 maTitle = SfxDocumentTemplates::ConvertResourceString(
1532 STR_TEMPLATE_NAME1_DEF, STR_TEMPLATE_NAME1, NUM_TEMPLATE_NAMES, rTitle );
1533 mbIsOwner = sal_False;
1534 mbDidConvert= sal_False;
1537 // -----------------------------------------------------------------------
1538 int DocTempl_EntryData_Impl::Compare( const OUString& rTitle ) const
1540 return maTitle.compareTo( rTitle );
1543 // -----------------------------------------------------------------------
1544 SfxObjectShellRef DocTempl_EntryData_Impl::CreateObjectShell()
1546 if( ! mxObjShell.Is() )
1548 mbIsOwner = sal_False;
1549 sal_Bool bDum = sal_False;
1550 SfxApplication *pSfxApp = SFX_APP();
1551 String aTargetURL = GetTargetURL();
1553 mxObjShell = pSfxApp->DocAlreadyLoaded( aTargetURL, sal_True, bDum );
1555 if( ! mxObjShell.Is() )
1557 mbIsOwner = sal_True;
1558 SfxMedium *pMed=new SfxMedium(
1559 aTargetURL,(STREAM_STD_READWRITE | STREAM_SHARE_DENYALL), sal_False, 0 );
1560 const SfxFilter* pFilter = NULL;
1561 pMed->UseInteractionHandler(sal_True);
1562 if( pSfxApp->GetFilterMatcher().GuessFilter(
1563 *pMed, &pFilter, SFX_FILTER_TEMPLATE, 0 ) ||
1564 (pFilter && !pFilter->IsOwnFormat()) ||
1565 (pFilter && !pFilter->UsesStorage()) )
1567 SfxErrorContext aEc( ERRCTX_SFX_LOADTEMPLATE,
1568 aTargetURL );
1569 delete pMed;
1570 mbDidConvert=sal_True;
1571 sal_uIntPtr lErr;
1572 if ( mxObjShell.Is() ) {
1573 lErr = pSfxApp->LoadTemplate( mxObjShell,aTargetURL);
1574 if( lErr != ERRCODE_NONE )
1575 ErrorHandler::HandleError(lErr);
1579 else if (pFilter)
1581 mbDidConvert=sal_False;
1582 mxObjShell = SfxObjectShell::CreateObject( pFilter->GetServiceName(), SFX_CREATE_MODE_ORGANIZER );
1583 if ( mxObjShell.Is() )
1585 mxObjShell->DoInitNew(0);
1586 // TODO/LATER: make sure that we don't use binary templates!
1587 if( mxObjShell->LoadFrom( *pMed ) )
1589 mxObjShell->DoSaveCompleted( pMed );
1591 else
1592 mxObjShell.Clear();
1598 return (SfxObjectShellRef)(SfxObjectShell*) mxObjShell;
1601 //------------------------------------------------------------------------
1602 sal_Bool DocTempl_EntryData_Impl::DeleteObjectShell()
1604 sal_Bool bRet = sal_True;
1606 if ( mxObjShell.Is() )
1608 if( mxObjShell->IsModified() )
1610 // Here we also save, if the Template is being processed ...
1611 bRet = sal_False;
1613 if ( mbIsOwner )
1615 if( mbDidConvert )
1617 bRet=mxObjShell->PreDoSaveAs_Impl(
1618 GetTargetURL(),
1619 mxObjShell->GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_EXPORT | SFX_FILTER_IMPORT, SFX_FILTER_INTERNAL )->GetFilterName(), 0 );
1621 else
1623 if( mxObjShell->Save() )
1625 uno::Reference< embed::XTransactedObject > xTransacted( mxObjShell->GetStorage(), uno::UNO_QUERY );
1626 DBG_ASSERT( xTransacted.is(), "Storage must implement XTransactedObject!\n" );
1627 if ( xTransacted.is() )
1631 xTransacted->commit();
1632 bRet = sal_True;
1634 catch( uno::Exception& )
1643 if( bRet )
1645 mxObjShell.Clear();
1648 return bRet;
1651 // -----------------------------------------------------------------------
1652 const OUString& DocTempl_EntryData_Impl::GetHierarchyURL()
1654 if ( maOwnURL.isEmpty() )
1656 INetURLObject aTemplateObj( GetParent()->GetHierarchyURL() );
1658 aTemplateObj.insertName( GetTitle(), false,
1659 INetURLObject::LAST_SEGMENT, true,
1660 INetURLObject::ENCODE_ALL );
1662 maOwnURL = aTemplateObj.GetMainURL( INetURLObject::NO_DECODE );
1663 DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1666 return maOwnURL;
1669 // -----------------------------------------------------------------------
1670 const OUString& DocTempl_EntryData_Impl::GetTargetURL()
1672 if ( maTargetURL.isEmpty() )
1674 uno::Reference< XCommandEnvironment > aCmdEnv;
1675 Content aRegion;
1677 if ( Content::create( GetHierarchyURL(), aCmdEnv, aRegion ) )
1679 OUString aPropName( TARGET_URL );
1681 getTextProperty_Impl( aRegion, aPropName, maTargetURL );
1683 else
1685 SAL_WARN( "sfx2.doc", "GetTargetURL(): Could not create hierarchy content!" );
1689 return maTargetURL;
1692 // -----------------------------------------------------------------------
1693 RegionData_Impl::RegionData_Impl( const SfxDocTemplate_Impl* pParent,
1694 const OUString& rTitle )
1696 maTitle = rTitle;
1697 mpParent = pParent;
1700 // -----------------------------------------------------------------------
1701 RegionData_Impl::~RegionData_Impl()
1703 for ( size_t i = 0, n = maEntries.size(); i < n; ++i )
1704 delete maEntries[ i ];
1705 maEntries.clear();
1708 // -----------------------------------------------------------------------
1709 size_t RegionData_Impl::GetEntryPos( const OUString& rTitle, sal_Bool& rFound ) const
1711 #if 1 // Don't use binary search today
1712 size_t i;
1713 size_t nCount = maEntries.size();
1715 for ( i=0; i<nCount; i++ )
1717 DocTempl_EntryData_Impl *pData = maEntries[ i ];
1719 if ( pData->Compare( rTitle ) == 0 )
1721 rFound = sal_True;
1722 return i;
1726 rFound = sal_False;
1727 return i;
1729 #else
1730 // use binary search to find the correct position
1731 // in the maEntries list
1733 int nCompVal = 1;
1734 size_t nStart = 0;
1735 size_t nEnd = maEntries.size() - 1;
1736 size_t nMid;
1738 DocTempl_EntryData_Impl* pMid;
1740 rFound = sal_False;
1742 while ( nCompVal && ( nStart <= nEnd ) )
1744 nMid = ( nEnd - nStart ) / 2 + nStart;
1745 pMid = maEntries[ nMid ];
1747 nCompVal = pMid->Compare( rTitle );
1749 if ( nCompVal < 0 ) // pMid < pData
1750 nStart = nMid + 1;
1751 else
1752 nEnd = nMid - 1;
1755 if ( nCompVal == 0 )
1757 rFound = sal_True;
1759 else
1761 if ( nCompVal < 0 ) // pMid < pData
1762 nMid++;
1765 return nMid;
1766 #endif
1769 // -----------------------------------------------------------------------
1770 void RegionData_Impl::AddEntry( const OUString& rTitle,
1771 const OUString& rTargetURL,
1772 size_t *pPos )
1774 INetURLObject aLinkObj( GetHierarchyURL() );
1775 aLinkObj.insertName( rTitle, false,
1776 INetURLObject::LAST_SEGMENT, true,
1777 INetURLObject::ENCODE_ALL );
1778 OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE );
1780 DocTempl_EntryData_Impl* pEntry;
1781 sal_Bool bFound = sal_False;
1782 size_t nPos = GetEntryPos( rTitle, bFound );
1784 if ( bFound )
1786 pEntry = maEntries[ nPos ];
1788 else
1790 if ( pPos )
1791 nPos = *pPos;
1793 pEntry = new DocTempl_EntryData_Impl( this, rTitle );
1794 pEntry->SetTargetURL( rTargetURL );
1795 pEntry->SetHierarchyURL( aLinkURL );
1796 if ( nPos < maEntries.size() ) {
1797 vector< DocTempl_EntryData_Impl* >::iterator it = maEntries.begin();
1798 advance( it, nPos );
1799 maEntries.insert( it, pEntry );
1801 else
1802 maEntries.push_back( pEntry );
1806 // -----------------------------------------------------------------------
1807 size_t RegionData_Impl::GetCount() const
1809 return maEntries.size();
1812 // -----------------------------------------------------------------------
1813 const OUString& RegionData_Impl::GetHierarchyURL()
1815 if ( maOwnURL.isEmpty() )
1817 INetURLObject aRegionObj( GetParent()->GetRootURL() );
1819 aRegionObj.insertName( GetTitle(), false,
1820 INetURLObject::LAST_SEGMENT, true,
1821 INetURLObject::ENCODE_ALL );
1823 maOwnURL = aRegionObj.GetMainURL( INetURLObject::NO_DECODE );
1824 DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1827 return maOwnURL;
1830 // -----------------------------------------------------------------------
1831 const OUString& RegionData_Impl::GetTargetURL()
1833 if ( maTargetURL.isEmpty() )
1835 uno::Reference< XCommandEnvironment > aCmdEnv;
1836 Content aRegion;
1838 if ( Content::create( GetHierarchyURL(), aCmdEnv, aRegion ) )
1840 OUString aPropName( TARGET_DIR_URL );
1842 getTextProperty_Impl( aRegion, aPropName, maTargetURL );
1843 // The targeturl must be substituted: $(baseinsturl) (#i32656#)
1844 maTargetURL = SvtPathOptions().SubstituteVariable( maTargetURL );
1846 else
1848 SAL_WARN( "sfx2.doc", "GetTargetURL(): Could not create hierarchy content!" );
1852 return maTargetURL;
1855 // -----------------------------------------------------------------------
1856 DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( const OUString& rName ) const
1858 sal_Bool bFound = sal_False;
1859 long nPos = GetEntryPos( rName, bFound );
1861 if ( bFound )
1862 return maEntries[ nPos ];
1863 else
1864 return NULL;
1867 // -----------------------------------------------------------------------
1868 DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( size_t nIndex ) const
1870 if ( nIndex < maEntries.size() )
1871 return maEntries[ nIndex ];
1872 return NULL;
1875 // -----------------------------------------------------------------------
1876 void RegionData_Impl::DeleteEntry( size_t nIndex )
1878 if ( nIndex < maEntries.size() )
1880 delete maEntries[ nIndex ];
1881 vector< DocTempl_EntryData_Impl*>::iterator it = maEntries.begin();
1882 advance( it, nIndex );
1883 maEntries.erase( it );
1887 // -----------------------------------------------------------------------
1888 int RegionData_Impl::Compare( RegionData_Impl* pCompare ) const
1890 int nCompare = maTitle.compareTo( pCompare->maTitle );
1892 return nCompare;
1895 // -----------------------------------------------------------------------
1897 SfxDocTemplate_Impl::SfxDocTemplate_Impl()
1898 : mbConstructed( sal_False )
1899 , mnLockCounter( 0 )
1903 // -----------------------------------------------------------------------
1904 SfxDocTemplate_Impl::~SfxDocTemplate_Impl()
1906 Clear();
1908 gpTemplateData = NULL;
1911 // -----------------------------------------------------------------------
1912 void SfxDocTemplate_Impl::IncrementLock()
1914 ::osl::MutexGuard aGuard( maMutex );
1915 mnLockCounter++;
1918 // -----------------------------------------------------------------------
1919 void SfxDocTemplate_Impl::DecrementLock()
1921 ::osl::MutexGuard aGuard( maMutex );
1922 if ( mnLockCounter )
1923 mnLockCounter--;
1926 // -----------------------------------------------------------------------
1927 RegionData_Impl* SfxDocTemplate_Impl::GetRegion( size_t nIndex ) const
1929 if ( nIndex < maRegions.size() )
1930 return maRegions[ nIndex ];
1931 return NULL;
1934 // -----------------------------------------------------------------------
1935 RegionData_Impl* SfxDocTemplate_Impl::GetRegion( const OUString& rName )
1936 const
1938 for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
1940 RegionData_Impl* pData = maRegions[ i ];
1941 if( pData->GetTitle() == rName )
1942 return pData;
1944 return NULL;
1947 // -----------------------------------------------------------------------
1948 void SfxDocTemplate_Impl::DeleteRegion( size_t nIndex )
1950 if ( nIndex < maRegions.size() )
1952 delete maRegions[ nIndex ];
1953 RegionList_Impl::iterator it = maRegions.begin();
1954 advance( it, nIndex );
1955 maRegions.erase( it );
1959 // -----------------------------------------------------------------------
1960 /* AddRegion adds a Region to the RegionList
1962 void SfxDocTemplate_Impl::AddRegion( const OUString& rTitle,
1963 Content& rContent )
1965 RegionData_Impl* pRegion;
1966 pRegion = new RegionData_Impl( this, rTitle );
1968 if ( ! InsertRegion( pRegion ) )
1970 delete pRegion;
1971 return;
1974 // now get the content of the region
1975 uno::Reference< XResultSet > xResultSet;
1976 Sequence< OUString > aProps(2);
1977 aProps[0] = OUString(TITLE );
1978 aProps[1] = OUString(TARGET_URL );
1982 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1983 Sequence< NumberedSortingInfo > aSortingInfo(1);
1984 aSortingInfo.getArray()->ColumnIndex = 1;
1985 aSortingInfo.getArray()->Ascending = sal_True;
1986 xResultSet = rContent.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
1988 catch ( Exception& ) {}
1990 if ( xResultSet.is() )
1992 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
1993 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
1997 while ( xResultSet->next() )
1999 OUString aTitle( xRow->getString( 1 ) );
2000 OUString aTargetDir( xRow->getString( 2 ) );
2002 pRegion->AddEntry( aTitle, aTargetDir );
2005 catch ( Exception& ) {}
2009 // -----------------------------------------------------------------------
2010 void SfxDocTemplate_Impl::CreateFromHierarchy( Content &rTemplRoot )
2012 uno::Reference< XResultSet > xResultSet;
2013 Sequence< OUString > aProps(1);
2014 aProps[0] = OUString(TITLE );
2018 ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY;
2019 Sequence< NumberedSortingInfo > aSortingInfo(1);
2020 aSortingInfo.getArray()->ColumnIndex = 1;
2021 aSortingInfo.getArray()->Ascending = sal_True;
2022 xResultSet = rTemplRoot.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
2024 catch ( Exception& ) {}
2026 if ( xResultSet.is() )
2028 uno::Reference< XCommandEnvironment > aCmdEnv;
2029 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2030 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2034 while ( xResultSet->next() )
2036 OUString aTitle( xRow->getString( 1 ) );
2038 OUString aId = xContentAccess->queryContentIdentifierString();
2039 Content aContent = Content( aId, aCmdEnv );
2041 AddRegion( aTitle, aContent );
2044 catch ( Exception& ) {}
2048 // ------------------------------------------------------------------------
2049 sal_Bool SfxDocTemplate_Impl::Construct( )
2051 ::osl::MutexGuard aGuard( maMutex );
2053 if ( mbConstructed )
2054 return sal_True;
2056 uno::Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
2057 uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2059 OUString aService( SERVICENAME_DOCINFO );
2060 uno::Reference< XPersist > xInfo( xFactory->createInstance( aService ), UNO_QUERY );
2061 mxInfo = xInfo;
2063 mxTemplates = frame::DocumentTemplates::create(xContext);
2065 uno::Reference< XLocalizable > xLocalizable( mxTemplates, UNO_QUERY );
2067 Sequence< Any > aCompareArg(1);
2068 *(aCompareArg.getArray()) <<= xLocalizable->getLocale();
2069 m_rCompareFactory = uno::Reference< XAnyCompareFactory >(
2070 xFactory->createInstanceWithArguments( OUString("com.sun.star.ucb.AnyCompareFactory"),
2071 aCompareArg ),
2072 UNO_QUERY );
2074 uno::Reference < XContent > aRootContent = mxTemplates->getContent();
2075 uno::Reference < XCommandEnvironment > aCmdEnv;
2077 if ( ! aRootContent.is() )
2078 return sal_False;
2080 mbConstructed = sal_True;
2081 maRootURL = aRootContent->getIdentifier()->getContentIdentifier();
2083 ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) );
2085 if ( aLongNames.Count() )
2086 maStandardGroup = aLongNames.GetString( 0 );
2088 Content aTemplRoot( aRootContent, aCmdEnv );
2089 CreateFromHierarchy( aTemplRoot );
2091 return sal_True;
2094 // -----------------------------------------------------------------------
2095 void SfxDocTemplate_Impl::ReInitFromComponent()
2097 uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
2098 if ( xTemplates.is() )
2100 uno::Reference < XContent > aRootContent = xTemplates->getContent();
2101 uno::Reference < XCommandEnvironment > aCmdEnv;
2102 Content aTemplRoot( aRootContent, aCmdEnv );
2103 Clear();
2104 CreateFromHierarchy( aTemplRoot );
2108 // -----------------------------------------------------------------------
2109 sal_Bool SfxDocTemplate_Impl::InsertRegion( RegionData_Impl *pNew, size_t nPos )
2111 ::osl::MutexGuard aGuard( maMutex );
2113 // return false (not inserted) if the entry already exists
2114 for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
2115 if ( maRegions[ i ]->Compare( pNew ) == 0 )
2116 return sal_False;
2118 size_t newPos = nPos;
2119 if ( pNew->GetTitle() == maStandardGroup )
2120 newPos = 0;
2122 if ( newPos < maRegions.size() )
2124 RegionList_Impl::iterator it = maRegions.begin();
2125 advance( it, newPos );
2126 maRegions.insert( it, pNew );
2128 else
2129 maRegions.push_back( pNew );
2131 return sal_True;
2134 // -----------------------------------------------------------------------
2135 void SfxDocTemplate_Impl::Rescan()
2137 Clear();
2141 uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
2142 DBG_ASSERT( xTemplates.is(), "SfxDocTemplate_Impl::Rescan:invalid template instance!" );
2143 if ( xTemplates.is() )
2145 xTemplates->update();
2147 uno::Reference < XContent > aRootContent = xTemplates->getContent();
2148 uno::Reference < XCommandEnvironment > aCmdEnv;
2150 Content aTemplRoot( aRootContent, aCmdEnv );
2151 CreateFromHierarchy( aTemplRoot );
2154 catch( const Exception& )
2156 SAL_WARN( "sfx2.doc", "SfxDocTemplate_Impl::Rescan: caught an exception while doing the update!" );
2160 // -----------------------------------------------------------------------
2161 sal_Bool SfxDocTemplate_Impl::GetTitleFromURL( const OUString& rURL,
2162 OUString& aTitle )
2164 if ( mxInfo.is() )
2168 mxInfo->read( rURL );
2170 catch ( Exception& )
2172 // the document is not a StarOffice document
2173 return sal_False;
2179 uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
2180 if ( aPropSet.is() )
2182 OUString aPropName( TITLE );
2183 Any aValue = aPropSet->getPropertyValue( aPropName );
2184 aValue >>= aTitle;
2187 catch ( IOException& ) {}
2188 catch ( UnknownPropertyException& ) {}
2189 catch ( Exception& ) {}
2192 if ( aTitle.isEmpty() )
2194 INetURLObject aURL( rURL );
2195 aURL.CutExtension();
2196 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
2197 INetURLObject::DECODE_WITH_CHARSET );
2200 return sal_True;
2204 // -----------------------------------------------------------------------
2205 void SfxDocTemplate_Impl::Clear()
2207 ::osl::MutexGuard aGuard( maMutex );
2208 if ( mnLockCounter )
2209 return;
2211 for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
2212 delete maRegions[ i ];
2213 maRegions.clear();
2216 // -----------------------------------------------------------------------
2217 sal_Bool getTextProperty_Impl( Content& rContent,
2218 const OUString& rPropName,
2219 OUString& rPropValue )
2221 sal_Bool bGotProperty = sal_False;
2223 // Get the property
2226 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
2228 // check, whether or not the property exists
2229 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
2231 return sal_False;
2234 // now get the property
2235 Any aAnyValue;
2237 aAnyValue = rContent.getPropertyValue( rPropName );
2238 aAnyValue >>= rPropValue;
2240 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
2242 SfxURLRelocator_Impl aRelocImpl( ::comphelper::getProcessServiceFactory() );
2243 aRelocImpl.makeAbsoluteURL( rPropValue );
2246 bGotProperty = sal_True;
2248 catch ( RuntimeException& ) {}
2249 catch ( Exception& ) {}
2251 return bGotProperty;
2254 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */