Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <limits.h>
22 : #include <com/sun/star/uno/Any.h>
23 : #include <osl/mutex.hxx>
24 : #include <osl/thread.hxx>
25 :
26 : #include <vcl/svapp.hxx>
27 : #include <vcl/settings.hxx>
28 : #include <unotools/localedatawrapper.hxx>
29 : #include <unotools/pathoptions.hxx>
30 : #include <tools/resary.hxx>
31 : #include <tools/urlobj.hxx>
32 : #include <svtools/ehdl.hxx>
33 : #include <svtools/sfxecode.hxx>
34 : #include <comphelper/processfactory.hxx>
35 : #include <ucbhelper/content.hxx>
36 : #include <com/sun/star/beans/PropertyAttribute.hpp>
37 : #include <com/sun/star/beans/PropertyValue.hpp>
38 : #include <com/sun/star/beans/XPropertyContainer.hpp>
39 : #include <com/sun/star/beans/XPropertySet.hpp>
40 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
41 : #include <com/sun/star/document/XTypeDetection.hpp>
42 : #include <com/sun/star/document/DocumentProperties.hpp>
43 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
44 : #include <com/sun/star/frame/Desktop.hpp>
45 : #include <com/sun/star/frame/XComponentLoader.hpp>
46 : #include <com/sun/star/frame/DocumentTemplates.hpp>
47 : #include <com/sun/star/frame/XDocumentTemplates.hpp>
48 : #include <com/sun/star/io/XInputStream.hpp>
49 : #include <com/sun/star/io/XPersist.hpp>
50 : #include <com/sun/star/lang/XLocalizable.hpp>
51 : #include <com/sun/star/sdbc/XResultSet.hpp>
52 : #include <com/sun/star/sdbc/XRow.hpp>
53 : #include <com/sun/star/ucb/ContentInfo.hpp>
54 : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
55 : #include <com/sun/star/ucb/NameClash.hpp>
56 : #include <com/sun/star/ucb/TransferInfo.hpp>
57 : #include <com/sun/star/ucb/XCommandProcessor.hpp>
58 : #include <com/sun/star/ucb/XContent.hpp>
59 : #include <com/sun/star/ucb/XContentAccess.hpp>
60 : #include <com/sun/star/ucb/AnyCompareFactory.hpp>
61 : #include <com/sun/star/ucb/XAnyCompare.hpp>
62 : #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
63 : #include <com/sun/star/embed/ElementModes.hpp>
64 : #include <com/sun/star/embed/XTransactedObject.hpp>
65 :
66 : #include "sfxurlrelocator.hxx"
67 :
68 : using namespace ::com::sun::star;
69 : using namespace ::com::sun::star::beans;
70 : using namespace ::com::sun::star::frame;
71 : using namespace ::com::sun::star::io;
72 : using namespace ::com::sun::star::lang;
73 : using namespace ::com::sun::star::sdbc;
74 : using namespace ::com::sun::star::uno;
75 : using namespace ::com::sun::star::ucb;
76 : using namespace ::com::sun::star::document;
77 : using namespace ::rtl;
78 : using namespace ::ucbhelper;
79 :
80 :
81 : #include <sfx2/doctempl.hxx>
82 : #include <sfx2/docfac.hxx>
83 : #include <sfx2/docfile.hxx>
84 : #include <sfx2/objsh.hxx>
85 : #include "sfxtypes.hxx"
86 : #include <sfx2/app.hxx>
87 : #include <sfx2/sfxresid.hxx>
88 : #include <sfx2/templatelocnames.hrc>
89 : #include "doc.hrc"
90 : #include <sfx2/fcontnr.hxx>
91 : #include <svtools/templatefoldercache.hxx>
92 :
93 : #include <comphelper/storagehelper.hxx>
94 : #include <unotools/ucbhelper.hxx>
95 :
96 : #include <vector>
97 : using ::std::vector;
98 : using ::std::advance;
99 :
100 :
101 :
102 : #define TITLE "Title"
103 : #define TARGET_URL "TargetURL"
104 :
105 : #define COMMAND_TRANSFER "transfer"
106 :
107 :
108 :
109 : class RegionData_Impl;
110 :
111 : namespace DocTempl {
112 :
113 0 : class DocTempl_EntryData_Impl
114 : {
115 : RegionData_Impl* mpParent;
116 :
117 : // the following member must be SfxObjectShellLock since it controlls that SfxObjectShell lifetime by design
118 : // and users of this class expect it to be so.
119 : SfxObjectShellLock mxObjShell;
120 :
121 : OUString maTitle;
122 : OUString maOwnURL;
123 : OUString maTargetURL;
124 : bool mbIsOwner : 1;
125 : bool mbDidConvert: 1;
126 :
127 : private:
128 0 : RegionData_Impl* GetParent() const { return mpParent; }
129 :
130 : public:
131 : DocTempl_EntryData_Impl( RegionData_Impl* pParent,
132 : const OUString& rTitle );
133 :
134 0 : const OUString& GetTitle() const { return maTitle; }
135 : const OUString& GetTargetURL();
136 : const OUString& GetHierarchyURL();
137 :
138 0 : void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
139 0 : void SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
140 0 : void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
141 :
142 : int Compare( const OUString& rTitle ) const;
143 : };
144 :
145 : }
146 :
147 : using namespace ::DocTempl;
148 :
149 :
150 :
151 : class RegionData_Impl
152 : {
153 : const SfxDocTemplate_Impl* mpParent;
154 : vector< DocTempl_EntryData_Impl* > maEntries;
155 : OUString maTitle;
156 : OUString maOwnURL;
157 : OUString maTargetURL;
158 :
159 : private:
160 : size_t GetEntryPos( const OUString& rTitle,
161 : bool& rFound ) const;
162 0 : const SfxDocTemplate_Impl* GetParent() const { return mpParent; }
163 :
164 : public:
165 : RegionData_Impl( const SfxDocTemplate_Impl* pParent,
166 : const OUString& rTitle );
167 : ~RegionData_Impl();
168 :
169 0 : void SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
170 0 : void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
171 :
172 : DocTempl_EntryData_Impl* GetEntry( size_t nIndex ) const;
173 : DocTempl_EntryData_Impl* GetEntry( const OUString& rName ) const;
174 :
175 0 : const OUString& GetTitle() const { return maTitle; }
176 : const OUString& GetHierarchyURL();
177 :
178 : size_t GetCount() const;
179 :
180 0 : void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
181 :
182 : void AddEntry( const OUString& rTitle,
183 : const OUString& rTargetURL,
184 : size_t *pPos = NULL );
185 : void DeleteEntry( size_t nIndex );
186 :
187 : int Compare( RegionData_Impl* pCompareWith ) const;
188 : };
189 :
190 : typedef vector< RegionData_Impl* > RegionList_Impl;
191 :
192 :
193 :
194 : class SfxDocTemplate_Impl : public SvRefBase
195 : {
196 : uno::Reference< XPersist > mxInfo;
197 : uno::Reference< XDocumentTemplates > mxTemplates;
198 :
199 : ::osl::Mutex maMutex;
200 : OUString maRootURL;
201 : OUString maStandardGroup;
202 : RegionList_Impl maRegions;
203 : bool mbConstructed;
204 :
205 : uno::Reference< XAnyCompareFactory > m_rCompareFactory;
206 :
207 : // the following member is intended to prevent clearing of the global data when it is in use
208 : // TODO/LATER: it still does not make the implementation complete thread-safe
209 : sal_Int32 mnLockCounter;
210 :
211 : private:
212 : void Clear();
213 :
214 : public:
215 : SfxDocTemplate_Impl();
216 : virtual ~SfxDocTemplate_Impl();
217 :
218 : void IncrementLock();
219 : void DecrementLock();
220 :
221 : bool Construct( );
222 : void CreateFromHierarchy( Content &rTemplRoot );
223 : void ReInitFromComponent();
224 : void AddRegion( const OUString& rTitle,
225 : Content& rContent );
226 :
227 : void Rescan();
228 :
229 : void DeleteRegion( size_t nIndex );
230 :
231 0 : size_t GetRegionCount() const
232 0 : { return maRegions.size(); }
233 : RegionData_Impl* GetRegion( const OUString& rName ) const;
234 : RegionData_Impl* GetRegion( size_t nIndex ) const;
235 :
236 : bool GetTitleFromURL( const OUString& rURL, OUString& aTitle );
237 : bool InsertRegion( RegionData_Impl *pData, size_t nPos = size_t(-1) );
238 0 : OUString GetRootURL() const { return maRootURL; }
239 :
240 0 : uno::Reference< XDocumentTemplates > getDocTemplates() { return mxTemplates; }
241 : };
242 :
243 :
244 :
245 : class DocTemplLocker_Impl
246 : {
247 : SfxDocTemplate_Impl& m_aDocTempl;
248 : public:
249 0 : DocTemplLocker_Impl( SfxDocTemplate_Impl& aDocTempl )
250 0 : : m_aDocTempl( aDocTempl )
251 : {
252 0 : m_aDocTempl.IncrementLock();
253 0 : }
254 :
255 0 : ~DocTemplLocker_Impl()
256 : {
257 0 : m_aDocTempl.DecrementLock();
258 0 : }
259 : };
260 :
261 :
262 :
263 : #ifndef SFX_DECL_DOCTEMPLATES_DEFINED
264 : #define SFX_DECL_DOCTEMPLATES_DEFINED
265 : typedef tools::SvRef<SfxDocTemplate_Impl> SfxDocTemplate_ImplRef;
266 : #endif
267 :
268 : SfxDocTemplate_Impl *gpTemplateData = 0;
269 :
270 :
271 :
272 : static bool getTextProperty_Impl( Content& rContent,
273 : const OUString& rPropName,
274 : OUString& rPropValue );
275 :
276 :
277 :
278 0 : OUString SfxDocumentTemplates::GetFullRegionName
279 : (
280 : sal_uInt16 nIdx // Region Index
281 : ) const
282 :
283 : /* [Description]
284 :
285 : Returns the logical name of a region and its path
286 :
287 : [Return value] Reference to the Region name
288 :
289 : */
290 :
291 : {
292 : // First: find the RegionData for the index
293 0 : OUString aName;
294 :
295 0 : DocTemplLocker_Impl aLocker( *pImp );
296 :
297 0 : if ( pImp->Construct() )
298 : {
299 0 : RegionData_Impl *pData1 = pImp->GetRegion( nIdx );
300 :
301 0 : if ( pData1 )
302 0 : aName = pData1->GetTitle();
303 :
304 : // --**-- here was some code which appended the path to the
305 : // group if there was more than one with the same name.
306 : // this should not happen anymore
307 : }
308 :
309 0 : return aName;
310 : }
311 :
312 :
313 :
314 0 : const OUString& SfxDocumentTemplates::GetRegionName
315 : (
316 : sal_uInt16 nIdx // Region Index
317 : ) const
318 :
319 : /* [Description]
320 :
321 : Returns the logical name of a region
322 :
323 : [Return value]
324 :
325 : const String& Reference to the Region name
326 :
327 : */
328 : {
329 0 : static OUString maTmpString;
330 :
331 0 : DocTemplLocker_Impl aLocker( *pImp );
332 :
333 0 : if ( pImp->Construct() )
334 : {
335 0 : RegionData_Impl *pData = pImp->GetRegion( nIdx );
336 :
337 0 : if ( pData )
338 0 : maTmpString = pData->GetTitle();
339 : else
340 0 : maTmpString = "";
341 : }
342 : else
343 0 : maTmpString = "";
344 :
345 0 : return maTmpString;
346 : }
347 :
348 :
349 :
350 0 : sal_uInt16 SfxDocumentTemplates::GetRegionCount() const
351 :
352 : /* [Description]
353 :
354 : Returns the number of Regions
355 :
356 : [Return value]
357 :
358 : sal_uInt16 Number of Regions
359 : */
360 : {
361 0 : DocTemplLocker_Impl aLocker( *pImp );
362 :
363 0 : if ( !pImp->Construct() )
364 0 : return 0;
365 :
366 0 : sal_uIntPtr nCount = pImp->GetRegionCount();
367 :
368 0 : return (sal_uInt16) nCount;
369 : }
370 :
371 :
372 :
373 0 : sal_uInt16 SfxDocumentTemplates::GetCount
374 : (
375 : sal_uInt16 nRegion /* Region index whose number is
376 : to be determined */
377 :
378 : ) const
379 :
380 : /* [Description]
381 :
382 : Number of entries in Region
383 :
384 : [Return value] Number of entries
385 : */
386 :
387 : {
388 0 : DocTemplLocker_Impl aLocker( *pImp );
389 :
390 0 : if ( !pImp->Construct() )
391 0 : return 0;
392 :
393 0 : RegionData_Impl *pData = pImp->GetRegion( nRegion );
394 0 : sal_uIntPtr nCount = 0;
395 :
396 0 : if ( pData )
397 0 : nCount = pData->GetCount();
398 :
399 0 : return (sal_uInt16) nCount;
400 : }
401 :
402 :
403 :
404 0 : const OUString& SfxDocumentTemplates::GetName
405 : (
406 : sal_uInt16 nRegion, // Region Index, in which the entry lies
407 : sal_uInt16 nIdx // Index of the entry
408 : ) const
409 :
410 : /* [Description]
411 :
412 : Returns the logical name of an entry in Region
413 :
414 : [Return value]
415 :
416 : const String& Entry Name
417 : */
418 :
419 : {
420 0 : DocTemplLocker_Impl aLocker( *pImp );
421 :
422 0 : static OUString maTmpString;
423 :
424 0 : if ( pImp->Construct() )
425 : {
426 0 : DocTempl_EntryData_Impl *pEntry = NULL;
427 0 : RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
428 :
429 0 : if ( pRegion )
430 0 : pEntry = pRegion->GetEntry( nIdx );
431 :
432 0 : if ( pEntry )
433 0 : maTmpString = pEntry->GetTitle();
434 : else
435 0 : maTmpString = "";
436 : }
437 : else
438 0 : maTmpString = "";
439 :
440 0 : return maTmpString;
441 : }
442 :
443 :
444 :
445 0 : OUString SfxDocumentTemplates::GetPath
446 : (
447 : sal_uInt16 nRegion, // Region Index, in which the entry lies
448 : sal_uInt16 nIdx // Index of the entry
449 : ) const
450 :
451 : /* [Description]
452 :
453 : Returns the file name with full path to the file assigned to an entry
454 :
455 : [Return value]
456 :
457 : String File name with full path
458 : */
459 : {
460 0 : DocTemplLocker_Impl aLocker( *pImp );
461 :
462 0 : if ( !pImp->Construct() )
463 0 : return OUString();
464 :
465 0 : DocTempl_EntryData_Impl *pEntry = NULL;
466 0 : RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
467 :
468 0 : if ( pRegion )
469 0 : pEntry = pRegion->GetEntry( nIdx );
470 :
471 0 : if ( pEntry )
472 0 : return pEntry->GetTargetURL();
473 : else
474 0 : return OUString();
475 : }
476 :
477 :
478 :
479 0 : OUString SfxDocumentTemplates::GetTemplateTargetURLFromComponent( const OUString& aGroupName,
480 : const OUString& aTitle )
481 : {
482 0 : DocTemplLocker_Impl aLocker( *pImp );
483 :
484 0 : INetURLObject aTemplateObj( pImp->GetRootURL() );
485 :
486 : aTemplateObj.insertName( aGroupName, false,
487 : INetURLObject::LAST_SEGMENT, true,
488 0 : INetURLObject::ENCODE_ALL );
489 :
490 : aTemplateObj.insertName( aTitle, false,
491 : INetURLObject::LAST_SEGMENT, true,
492 0 : INetURLObject::ENCODE_ALL );
493 :
494 :
495 0 : OUString aResult;
496 0 : Content aTemplate;
497 0 : uno::Reference< XCommandEnvironment > aCmdEnv;
498 0 : if ( Content::create( aTemplateObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
499 : {
500 0 : OUString aPropName( TARGET_URL );
501 0 : getTextProperty_Impl( aTemplate, aPropName, aResult );
502 0 : aResult = SvtPathOptions().SubstituteVariable( aResult );
503 : }
504 :
505 0 : return aResult;
506 : }
507 :
508 :
509 :
510 : /** Convert a resource string - a template name - to its localised pair if it exists.
511 : @param nSourceResIds
512 : Resource ID where the list of original en-US template names begin.
513 : @param nDestResIds
514 : Resource ID where the list of localised template names begin.
515 : @param nCount
516 : The number of names that have been localised.
517 : @param rString
518 : Name to be translated.
519 : @return
520 : The localised pair of rString or rString if the former does not exist.
521 : */
522 0 : OUString SfxDocumentTemplates::ConvertResourceString (
523 : int nSourceResIds, int nDestResIds, int nCount, const OUString& rString )
524 : {
525 0 : for( int i = 0; i < nCount; ++i )
526 : {
527 0 : if( rString == SFX2_RESSTR(nSourceResIds + i))
528 0 : return SFX2_RESSTR(nDestResIds + i);
529 : }
530 0 : return rString;
531 : }
532 :
533 :
534 :
535 0 : bool SfxDocumentTemplates::CopyOrMove
536 : (
537 : sal_uInt16 nTargetRegion, // Target Region Index
538 : sal_uInt16 nTargetIdx, // Target position Index
539 : sal_uInt16 nSourceRegion, // Source Region Index
540 : sal_uInt16 nSourceIdx, /* Index to be copied / to moved template */
541 : bool bMove // Copy / Move
542 : )
543 :
544 : /* [Description]
545 :
546 : Copy or move a document template
547 :
548 : [Return value]
549 :
550 : sal_Bool sal_True, Action could be performed
551 : sal_False, Action could not be performed
552 :
553 : [Cross-references]
554 :
555 : <SfxDocumentTemplates::Move(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
556 : <SfxDocumentTemplates::Copy(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
557 : */
558 :
559 : {
560 : /* to perform a copy or move, we need to send a transfer command to
561 : the destination folder with the URL of the source as parameter.
562 : ( If the destination content doesn't support the transfer command,
563 : we could try a copy ( and delete ) instead. )
564 : We need two transfers ( one for the real template and one for its
565 : representation in the hierarchy )
566 : ...
567 : */
568 :
569 0 : DocTemplLocker_Impl aLocker( *pImp );
570 :
571 0 : if ( !pImp->Construct() )
572 0 : return false;
573 :
574 : // Don't copy or move any folders
575 0 : if( nSourceIdx == USHRT_MAX )
576 0 : return false ;
577 :
578 0 : if ( nSourceRegion == nTargetRegion )
579 : {
580 : SAL_WARN( "sfx.doc", "Don't know, what to do!" );
581 0 : return false;
582 : }
583 :
584 0 : RegionData_Impl *pSourceRgn = pImp->GetRegion( nSourceRegion );
585 0 : if ( !pSourceRgn )
586 0 : return false;
587 :
588 0 : DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nSourceIdx );
589 0 : if ( !pSource )
590 0 : return false;
591 :
592 0 : RegionData_Impl *pTargetRgn = pImp->GetRegion( nTargetRegion );
593 0 : if ( !pTargetRgn )
594 0 : return false;
595 :
596 0 : OUString aTitle = pSource->GetTitle();
597 :
598 0 : uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
599 :
600 0 : if ( xTemplates->addTemplate( pTargetRgn->GetTitle(),
601 : aTitle,
602 0 : pSource->GetTargetURL() ) )
603 : {
604 0 : OUString aNewTargetURL = GetTemplateTargetURLFromComponent( pTargetRgn->GetTitle(), aTitle );
605 0 : if ( aNewTargetURL.isEmpty() )
606 0 : return false;
607 :
608 0 : if ( bMove )
609 : {
610 : // --**-- delete the original file
611 0 : bool bDeleted = xTemplates->removeTemplate( pSourceRgn->GetTitle(),
612 0 : pSource->GetTitle() );
613 0 : if ( bDeleted )
614 0 : pSourceRgn->DeleteEntry( nSourceIdx );
615 : else
616 : {
617 0 : if ( xTemplates->removeTemplate( pTargetRgn->GetTitle(), aTitle ) )
618 0 : return false; // will trigger tetry with copy instead of move
619 :
620 : // if it is not possible to remove just created template ( must be possible! )
621 : // it is better to report success here, since at least the copy has succeeded
622 : // TODO/LATER: solve it more gracefully in future
623 : }
624 : }
625 :
626 : // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
627 0 : size_t temp_nTargetIdx = nTargetIdx;
628 0 : pTargetRgn->AddEntry( aTitle, aNewTargetURL, &temp_nTargetIdx );
629 :
630 0 : return true;
631 : }
632 :
633 : // --**-- if the current file is opened,
634 : // it must be re-opened afterwards.
635 :
636 0 : return false;
637 : }
638 :
639 :
640 :
641 0 : bool SfxDocumentTemplates::Move
642 : (
643 : sal_uInt16 nTargetRegion, // Target Region Index
644 : sal_uInt16 nTargetIdx, // Target position Index
645 : sal_uInt16 nSourceRegion, // Source Region Index
646 : sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
647 : )
648 :
649 : /* [Description]
650 :
651 : Moving a template
652 :
653 : [Return value]
654 :
655 : sal_Bool sal_True, Action could be performed
656 : sal_False, Action could not be performed
657 :
658 : [Cross-references]
659 :
660 : <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
661 : */
662 : {
663 0 : DocTemplLocker_Impl aLocker( *pImp );
664 :
665 : return CopyOrMove( nTargetRegion, nTargetIdx,
666 0 : nSourceRegion, nSourceIdx, true );
667 : }
668 :
669 :
670 :
671 0 : bool SfxDocumentTemplates::Copy
672 : (
673 : sal_uInt16 nTargetRegion, // Target Region Index
674 : sal_uInt16 nTargetIdx, // Target position Index
675 : sal_uInt16 nSourceRegion, // Source Region Index
676 : sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
677 : )
678 :
679 : /* [Description]
680 :
681 : Copying a template
682 :
683 : [Return value]
684 :
685 : sal_Bool sal_True, Action could be performed
686 : sal_False, Action could not be performed
687 :
688 : [Cross-references]
689 :
690 : <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
691 : */
692 :
693 : {
694 0 : DocTemplLocker_Impl aLocker( *pImp );
695 :
696 : return CopyOrMove( nTargetRegion, nTargetIdx,
697 0 : nSourceRegion, nSourceIdx, false );
698 : }
699 :
700 :
701 :
702 0 : bool SfxDocumentTemplates::CopyTo
703 : (
704 : sal_uInt16 nRegion, // Region of the template to be exported
705 : sal_uInt16 nIdx, // Index of the template to be exported
706 : const OUString& rName /* File name under which the template is to
707 : be created */
708 : ) const
709 :
710 : /* [Description]
711 :
712 : Exporting a template into the file system
713 :
714 : [Return value]
715 :
716 : sal_Bool sal_True, Action could be performed
717 : sal_False, Action could not be performed
718 :
719 : [Cross-references]
720 :
721 : <SfxDocumentTemplates::CopyFrom(sal_uInt16,sal_uInt16,String&)>
722 : */
723 :
724 : {
725 0 : DocTemplLocker_Impl aLocker( *pImp );
726 :
727 0 : if ( ! pImp->Construct() )
728 0 : return false;
729 :
730 0 : RegionData_Impl *pSourceRgn = pImp->GetRegion( nRegion );
731 0 : if ( !pSourceRgn )
732 0 : return false;
733 :
734 0 : DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nIdx );
735 0 : if ( !pSource )
736 0 : return false;
737 :
738 0 : INetURLObject aTargetURL( rName );
739 :
740 : OUString aTitle( aTargetURL.getName( INetURLObject::LAST_SEGMENT, true,
741 0 : INetURLObject::DECODE_WITH_CHARSET ) );
742 0 : aTargetURL.removeSegment();
743 :
744 0 : OUString aParentURL = aTargetURL.GetMainURL( INetURLObject::NO_DECODE );
745 :
746 0 : uno::Reference< XCommandEnvironment > aCmdEnv;
747 0 : Content aTarget;
748 :
749 : try
750 : {
751 0 : aTarget = Content( aParentURL, aCmdEnv, comphelper::getProcessComponentContext() );
752 :
753 0 : TransferInfo aTransferInfo;
754 0 : aTransferInfo.MoveData = sal_False;
755 0 : aTransferInfo.SourceURL = pSource->GetTargetURL();
756 0 : aTransferInfo.NewTitle = aTitle;
757 0 : aTransferInfo.NameClash = NameClash::OVERWRITE;
758 :
759 0 : Any aArg = makeAny( aTransferInfo );
760 0 : OUString aCmd( COMMAND_TRANSFER );
761 :
762 0 : aTarget.executeCommand( aCmd, aArg );
763 : }
764 0 : catch ( ContentCreationException& )
765 0 : { return false; }
766 0 : catch ( Exception& )
767 0 : { return false; }
768 :
769 0 : return true;
770 : }
771 :
772 :
773 :
774 0 : bool SfxDocumentTemplates::CopyFrom
775 : (
776 : sal_uInt16 nRegion, /* Region in which the template is to be
777 : imported */
778 : sal_uInt16 nIdx, // Index of the new template in this Region
779 : OUString& rName /* File name of the template to be imported
780 : as an out parameter of the (automatically
781 : generated from the file name) logical name
782 : of the template */
783 : )
784 :
785 : /* [Description]
786 :
787 : Import a template from the file system
788 :
789 : [Return value] Sucess (sal_True) or serfpTargetDirectory->GetContent());
790 :
791 : sal_Bool sal_True, Action could be performed
792 : sal_False, Action could not be performed
793 :
794 : [Cross-references]
795 :
796 : <SfxDocumentTemplates::CopyTo(sal_uInt16,sal_uInt16,const String&)>
797 : */
798 :
799 : {
800 0 : DocTemplLocker_Impl aLocker( *pImp );
801 :
802 0 : if ( ! pImp->Construct() )
803 0 : return false;
804 :
805 0 : RegionData_Impl *pTargetRgn = pImp->GetRegion( nRegion );
806 :
807 0 : if ( !pTargetRgn )
808 0 : return false;
809 :
810 0 : uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
811 0 : if ( !xTemplates.is() )
812 0 : return false;
813 :
814 0 : OUString aTitle;
815 0 : bool bTemplateAdded = false;
816 :
817 0 : if( pImp->GetTitleFromURL( rName, aTitle ) )
818 : {
819 0 : bTemplateAdded = xTemplates->addTemplate( pTargetRgn->GetTitle(), aTitle, rName );
820 : }
821 : else
822 : {
823 0 : uno::Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );;
824 :
825 0 : Sequence< PropertyValue > aArgs( 1 );
826 0 : aArgs[0].Name = "Hidden";
827 0 : aArgs[0].Value <<= sal_True;
828 :
829 0 : INetURLObject aTemplURL( rName );
830 0 : uno::Reference< XDocumentPropertiesSupplier > xDocPropsSupplier;
831 0 : uno::Reference< XStorable > xStorable;
832 : try
833 : {
834 0 : xStorable = uno::Reference< XStorable >(
835 0 : xDesktop->loadComponentFromURL( aTemplURL.GetMainURL(INetURLObject::NO_DECODE),
836 : OUString("_blank"),
837 : 0,
838 0 : aArgs ),
839 0 : UNO_QUERY );
840 :
841 0 : xDocPropsSupplier = uno::Reference< XDocumentPropertiesSupplier >(
842 0 : xStorable, UNO_QUERY );
843 : }
844 0 : catch( Exception& )
845 : {
846 : }
847 :
848 0 : if( xStorable.is() )
849 : {
850 : // get Title from XDocumentPropertiesSupplier
851 0 : if( xDocPropsSupplier.is() )
852 : {
853 : uno::Reference< XDocumentProperties > xDocProps
854 0 : = xDocPropsSupplier->getDocumentProperties();
855 0 : if (xDocProps.is() ) {
856 0 : aTitle = xDocProps->getTitle();
857 0 : }
858 : }
859 :
860 0 : if( aTitle.isEmpty() )
861 : {
862 0 : INetURLObject aURL( aTemplURL );
863 0 : aURL.CutExtension();
864 0 : aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
865 0 : INetURLObject::DECODE_WITH_CHARSET );
866 : }
867 :
868 : // write a template using XStorable interface
869 0 : bTemplateAdded = xTemplates->storeTemplate( pTargetRgn->GetTitle(), aTitle, xStorable );
870 0 : }
871 : }
872 :
873 :
874 0 : if( bTemplateAdded )
875 : {
876 0 : INetURLObject aTemplObj( pTargetRgn->GetHierarchyURL() );
877 : aTemplObj.insertName( aTitle, false,
878 : INetURLObject::LAST_SEGMENT, true,
879 0 : INetURLObject::ENCODE_ALL );
880 0 : OUString aTemplURL = aTemplObj.GetMainURL( INetURLObject::NO_DECODE );
881 :
882 0 : uno::Reference< XCommandEnvironment > aCmdEnv;
883 0 : Content aTemplCont;
884 :
885 0 : if( Content::create( aTemplURL, aCmdEnv, comphelper::getProcessComponentContext(), aTemplCont ) )
886 : {
887 0 : OUString aTemplName;
888 0 : OUString aPropName( TARGET_URL );
889 :
890 0 : if( getTextProperty_Impl( aTemplCont, aPropName, aTemplName ) )
891 : {
892 0 : if ( nIdx == USHRT_MAX )
893 0 : nIdx = 0;
894 : else
895 0 : nIdx += 1;
896 :
897 : // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
898 0 : size_t temp_nIdx = nIdx;
899 0 : pTargetRgn->AddEntry( aTitle, aTemplName, &temp_nIdx );
900 0 : rName = aTitle;
901 0 : return true;
902 : }
903 : else
904 : {
905 : DBG_ASSERT( false, "CopyFrom(): The content should contain target URL!" );
906 0 : }
907 : }
908 : else
909 : {
910 : DBG_ASSERT( false, "CopyFrom(): The content just was created!" );
911 0 : }
912 : }
913 :
914 0 : return false;
915 : }
916 :
917 :
918 :
919 0 : bool SfxDocumentTemplates::Delete
920 : (
921 : sal_uInt16 nRegion, // Region Index
922 : sal_uInt16 nIdx /* Index of the entry or USHRT_MAX,
923 : if a directory is meant. */
924 : )
925 :
926 : /* [Description]
927 :
928 : Deleting an entry or a directory
929 :
930 : [Return value]
931 :
932 : sal_Bool sal_True, Action could be performed
933 : sal_False, Action could not be performed
934 :
935 : [Cross-references]
936 :
937 : <SfxDocumentTemplates::InsertDir(const String&,sal_uInt16)>
938 : <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
939 : */
940 :
941 : {
942 0 : DocTemplLocker_Impl aLocker( *pImp );
943 :
944 : /* delete the template or folder in the hierarchy and in the
945 : template folder by sending a delete command to the content.
946 : Then remove the data from the lists
947 : */
948 0 : if ( ! pImp->Construct() )
949 0 : return false;
950 :
951 0 : RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
952 :
953 0 : if ( !pRegion )
954 0 : return false;
955 :
956 : bool bRet;
957 0 : uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
958 :
959 0 : if ( nIdx == USHRT_MAX )
960 : {
961 0 : bRet = xTemplates->removeGroup( pRegion->GetTitle() );
962 0 : if ( bRet )
963 0 : pImp->DeleteRegion( nRegion );
964 : }
965 : else
966 : {
967 0 : DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
968 :
969 0 : if ( !pEntry )
970 0 : return false;
971 :
972 0 : bRet = xTemplates->removeTemplate( pRegion->GetTitle(),
973 0 : pEntry->GetTitle() );
974 0 : if( bRet )
975 0 : pRegion->DeleteEntry( nIdx );
976 : }
977 :
978 0 : return bRet;
979 : }
980 :
981 :
982 :
983 0 : bool SfxDocumentTemplates::InsertDir
984 : (
985 : const OUString& rText, // the logical name of the new Region
986 : sal_uInt16 nRegion // Region Index
987 : )
988 :
989 : /* [Description]
990 :
991 : Insert an index
992 :
993 : [Return value]
994 :
995 : sal_Bool sal_True, Action could be performed
996 : sal_False, Action could not be performed
997 :
998 : [Cross-references]
999 :
1000 : <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
1001 : */
1002 : {
1003 0 : DocTemplLocker_Impl aLocker( *pImp );
1004 :
1005 0 : if ( ! pImp->Construct() )
1006 0 : return false;
1007 :
1008 0 : RegionData_Impl *pRegion = pImp->GetRegion( rText );
1009 :
1010 0 : if ( pRegion )
1011 0 : return false;
1012 :
1013 0 : uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1014 :
1015 0 : if ( xTemplates->addGroup( rText ) )
1016 : {
1017 0 : RegionData_Impl* pNewRegion = new RegionData_Impl( pImp, rText );
1018 :
1019 0 : if ( ! pImp->InsertRegion( pNewRegion, nRegion ) )
1020 : {
1021 0 : delete pNewRegion;
1022 0 : return false;
1023 : }
1024 0 : return true;
1025 : }
1026 :
1027 0 : return false;
1028 : }
1029 :
1030 0 : bool SfxDocumentTemplates::InsertTemplate(sal_uInt16 nSourceRegion, sal_uInt16 nIdx, const OUString &rName, const OUString &rPath)
1031 : {
1032 0 : DocTemplLocker_Impl aLocker( *pImp );
1033 :
1034 0 : if ( ! pImp->Construct() )
1035 0 : return false;
1036 :
1037 0 : RegionData_Impl *pRegion = pImp->GetRegion( nSourceRegion );
1038 :
1039 0 : if ( !pRegion )
1040 0 : return false;
1041 :
1042 0 : size_t pos = nIdx;
1043 0 : pRegion->AddEntry( rName, rPath, &pos );
1044 :
1045 0 : return true;
1046 : }
1047 :
1048 0 : bool SfxDocumentTemplates::SetName( const OUString& rName, sal_uInt16 nRegion, sal_uInt16 nIdx )
1049 :
1050 : {
1051 0 : DocTemplLocker_Impl aLocker( *pImp );
1052 :
1053 0 : if ( ! pImp->Construct() )
1054 0 : return false;
1055 :
1056 0 : RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1057 :
1058 0 : if ( !pRegion )
1059 0 : return false;
1060 :
1061 0 : uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1062 0 : OUString aEmpty;
1063 :
1064 0 : if ( nIdx == USHRT_MAX )
1065 : {
1066 0 : if ( pRegion->GetTitle() == rName )
1067 0 : return true;
1068 :
1069 : // we have to rename a region
1070 0 : if ( xTemplates->renameGroup( pRegion->GetTitle(), rName ) )
1071 : {
1072 0 : pRegion->SetTitle( rName );
1073 0 : pRegion->SetTargetURL( aEmpty );
1074 0 : pRegion->SetHierarchyURL( aEmpty );
1075 0 : return true;
1076 : }
1077 : }
1078 : else
1079 : {
1080 0 : DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
1081 :
1082 0 : if ( !pEntry )
1083 0 : return false;
1084 :
1085 0 : if ( pEntry->GetTitle() == rName )
1086 0 : return true;
1087 :
1088 0 : if ( xTemplates->renameTemplate( pRegion->GetTitle(),
1089 0 : pEntry->GetTitle(),
1090 0 : rName ) )
1091 : {
1092 0 : pEntry->SetTitle( rName );
1093 0 : pEntry->SetTargetURL( aEmpty );
1094 0 : pEntry->SetHierarchyURL( aEmpty );
1095 0 : return true;
1096 : }
1097 : }
1098 :
1099 0 : return false;
1100 : }
1101 :
1102 :
1103 :
1104 0 : bool SfxDocumentTemplates::GetFull
1105 : (
1106 : const OUString &rRegion, // Region Name
1107 : const OUString &rName, // Template Name
1108 : OUString &rPath // Out: Path + File name
1109 : )
1110 :
1111 : /* [Description]
1112 :
1113 : Returns Path + File name of the template specified by rRegion and rName.
1114 :
1115 : [Return value]
1116 :
1117 : sal_Bool sal_True, Action could be performed
1118 : sal_False, Action could not be performed
1119 :
1120 : [Cross-references]
1121 :
1122 : <SfxDocumentTemplates::GetLogicNames(const String&,String&,String&)>
1123 : */
1124 :
1125 : {
1126 0 : DocTemplLocker_Impl aLocker( *pImp );
1127 :
1128 : // We don't search for empty names!
1129 0 : if ( rName.isEmpty() )
1130 0 : return false;
1131 :
1132 0 : if ( ! pImp->Construct() )
1133 0 : return false;
1134 :
1135 0 : DocTempl_EntryData_Impl* pEntry = NULL;
1136 0 : const sal_uInt16 nCount = GetRegionCount();
1137 :
1138 0 : for ( sal_uInt16 i = 0; i < nCount; ++i )
1139 : {
1140 0 : RegionData_Impl *pRegion = pImp->GetRegion( i );
1141 :
1142 0 : if( pRegion &&
1143 0 : ( rRegion.isEmpty() || ( rRegion == pRegion->GetTitle() ) ) )
1144 : {
1145 0 : pEntry = pRegion->GetEntry( rName );
1146 :
1147 0 : if ( pEntry )
1148 : {
1149 0 : rPath = pEntry->GetTargetURL();
1150 0 : break;
1151 : }
1152 : }
1153 : }
1154 :
1155 0 : return ( pEntry != NULL );
1156 : }
1157 :
1158 :
1159 :
1160 0 : bool SfxDocumentTemplates::GetLogicNames
1161 : (
1162 : const OUString &rPath, // Full Path to the template
1163 : OUString &rRegion, // Out: Region name
1164 : OUString &rName // Out: Template name
1165 : ) const
1166 :
1167 : /* [Description]
1168 :
1169 : Returns and logical path name to the template specified by rPath
1170 :
1171 : [Return value]
1172 :
1173 : sal_Bool sal_True, Action could be performed
1174 : sal_False, Action could not be performed
1175 :
1176 : [Cross-references]
1177 :
1178 : <SfxDocumentTemplates::GetFull(const String&,const String&,DirEntry&)>
1179 : */
1180 :
1181 : {
1182 0 : DocTemplLocker_Impl aLocker( *pImp );
1183 :
1184 0 : if ( ! pImp->Construct() )
1185 0 : return false;
1186 :
1187 0 : INetURLObject aFullPath;
1188 :
1189 0 : aFullPath.SetSmartProtocol( INET_PROT_FILE );
1190 0 : aFullPath.SetURL( rPath );
1191 0 : OUString aPath( aFullPath.GetMainURL( INetURLObject::NO_DECODE ) );
1192 :
1193 0 : RegionData_Impl *pData = NULL;
1194 0 : DocTempl_EntryData_Impl *pEntry = NULL;
1195 0 : bool bFound = false;
1196 :
1197 0 : sal_uIntPtr nCount = GetRegionCount();
1198 :
1199 0 : for ( sal_uIntPtr i=0; !bFound && (i<nCount); i++ )
1200 : {
1201 0 : pData = pImp->GetRegion( i );
1202 0 : if ( pData )
1203 : {
1204 0 : sal_uIntPtr nChildCount = pData->GetCount();
1205 :
1206 0 : for ( sal_uIntPtr j=0; !bFound && (j<nChildCount); j++ )
1207 : {
1208 0 : pEntry = pData->GetEntry( j );
1209 0 : if ( pEntry && pEntry->GetTargetURL() == aPath )
1210 : {
1211 0 : bFound = true;
1212 : }
1213 : }
1214 : }
1215 : }
1216 :
1217 0 : if ( bFound )
1218 : {
1219 0 : rRegion = pData->GetTitle();
1220 0 : rName = pEntry->GetTitle();
1221 : }
1222 :
1223 0 : return bFound;
1224 : }
1225 :
1226 :
1227 :
1228 0 : SfxDocumentTemplates::SfxDocumentTemplates()
1229 :
1230 : /* [Description]
1231 :
1232 : Constructor
1233 : */
1234 : {
1235 0 : if ( !gpTemplateData )
1236 0 : gpTemplateData = new SfxDocTemplate_Impl;
1237 :
1238 0 : pImp = gpTemplateData;
1239 0 : }
1240 :
1241 :
1242 :
1243 0 : void SfxDocumentTemplates::Construct()
1244 :
1245 : // Delayed build-up of administrative data
1246 :
1247 : {
1248 0 : }
1249 :
1250 :
1251 :
1252 0 : SfxDocumentTemplates::~SfxDocumentTemplates()
1253 :
1254 : /* [Description]
1255 :
1256 : Destructor
1257 : Release of administrative data
1258 : */
1259 :
1260 : {
1261 0 : pImp = NULL;
1262 0 : }
1263 :
1264 0 : void SfxDocumentTemplates::Update( bool _bSmart )
1265 : {
1266 0 : if ( !_bSmart // don't be smart
1267 0 : || ::svt::TemplateFolderCache( true ).needsUpdate() // update is really necessary
1268 : )
1269 : {
1270 0 : if ( pImp->Construct() )
1271 0 : pImp->Rescan();
1272 : }
1273 0 : }
1274 :
1275 0 : void SfxDocumentTemplates::ReInitFromComponent()
1276 : {
1277 0 : pImp->ReInitFromComponent();
1278 0 : }
1279 :
1280 :
1281 0 : DocTempl_EntryData_Impl::DocTempl_EntryData_Impl( RegionData_Impl* pParent,
1282 0 : const OUString& rTitle )
1283 : {
1284 0 : mpParent = pParent;
1285 0 : maTitle = SfxDocumentTemplates::ConvertResourceString(
1286 0 : STR_TEMPLATE_NAME1_DEF, STR_TEMPLATE_NAME1, NUM_TEMPLATE_NAMES, rTitle );
1287 0 : mbIsOwner = false;
1288 0 : mbDidConvert= false;
1289 0 : }
1290 :
1291 :
1292 0 : int DocTempl_EntryData_Impl::Compare( const OUString& rTitle ) const
1293 : {
1294 0 : return maTitle.compareTo( rTitle );
1295 : }
1296 :
1297 :
1298 0 : const OUString& DocTempl_EntryData_Impl::GetHierarchyURL()
1299 : {
1300 0 : if ( maOwnURL.isEmpty() )
1301 : {
1302 0 : INetURLObject aTemplateObj( GetParent()->GetHierarchyURL() );
1303 :
1304 0 : aTemplateObj.insertName( GetTitle(), false,
1305 : INetURLObject::LAST_SEGMENT, true,
1306 0 : INetURLObject::ENCODE_ALL );
1307 :
1308 0 : maOwnURL = aTemplateObj.GetMainURL( INetURLObject::NO_DECODE );
1309 0 : DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1310 : }
1311 :
1312 0 : return maOwnURL;
1313 : }
1314 :
1315 :
1316 0 : const OUString& DocTempl_EntryData_Impl::GetTargetURL()
1317 : {
1318 0 : if ( maTargetURL.isEmpty() )
1319 : {
1320 0 : uno::Reference< XCommandEnvironment > aCmdEnv;
1321 0 : Content aRegion;
1322 :
1323 0 : if ( Content::create( GetHierarchyURL(), aCmdEnv, comphelper::getProcessComponentContext(), aRegion ) )
1324 : {
1325 0 : OUString aPropName( TARGET_URL );
1326 :
1327 0 : getTextProperty_Impl( aRegion, aPropName, maTargetURL );
1328 : }
1329 : else
1330 : {
1331 : SAL_WARN( "sfx.doc", "GetTargetURL(): Could not create hierarchy content!" );
1332 0 : }
1333 : }
1334 :
1335 0 : return maTargetURL;
1336 : }
1337 :
1338 :
1339 0 : RegionData_Impl::RegionData_Impl( const SfxDocTemplate_Impl* pParent,
1340 0 : const OUString& rTitle )
1341 : {
1342 0 : maTitle = rTitle;
1343 0 : mpParent = pParent;
1344 0 : }
1345 :
1346 :
1347 0 : RegionData_Impl::~RegionData_Impl()
1348 : {
1349 0 : for ( size_t i = 0, n = maEntries.size(); i < n; ++i )
1350 0 : delete maEntries[ i ];
1351 0 : maEntries.clear();
1352 0 : }
1353 :
1354 :
1355 0 : size_t RegionData_Impl::GetEntryPos( const OUString& rTitle, bool& rFound ) const
1356 : {
1357 : #if 1 // Don't use binary search today
1358 : size_t i;
1359 0 : size_t nCount = maEntries.size();
1360 :
1361 0 : for ( i=0; i<nCount; i++ )
1362 : {
1363 0 : DocTempl_EntryData_Impl *pData = maEntries[ i ];
1364 :
1365 0 : if ( pData->Compare( rTitle ) == 0 )
1366 : {
1367 0 : rFound = true;
1368 0 : return i;
1369 : }
1370 : }
1371 :
1372 0 : rFound = false;
1373 0 : return i;
1374 :
1375 : #else
1376 : // use binary search to find the correct position
1377 : // in the maEntries list
1378 :
1379 : int nCompVal = 1;
1380 : size_t nStart = 0;
1381 : size_t nEnd = maEntries.size() - 1;
1382 : size_t nMid;
1383 :
1384 : DocTempl_EntryData_Impl* pMid;
1385 :
1386 : rFound = sal_False;
1387 :
1388 : while ( nCompVal && ( nStart <= nEnd ) )
1389 : {
1390 : nMid = ( nEnd - nStart ) / 2 + nStart;
1391 : pMid = maEntries[ nMid ];
1392 :
1393 : nCompVal = pMid->Compare( rTitle );
1394 :
1395 : if ( nCompVal < 0 ) // pMid < pData
1396 : nStart = nMid + 1;
1397 : else
1398 : nEnd = nMid - 1;
1399 : }
1400 :
1401 : if ( nCompVal == 0 )
1402 : {
1403 : rFound = sal_True;
1404 : }
1405 : else
1406 : {
1407 : if ( nCompVal < 0 ) // pMid < pData
1408 : nMid++;
1409 : }
1410 :
1411 : return nMid;
1412 : #endif
1413 : }
1414 :
1415 :
1416 0 : void RegionData_Impl::AddEntry( const OUString& rTitle,
1417 : const OUString& rTargetURL,
1418 : size_t *pPos )
1419 : {
1420 0 : INetURLObject aLinkObj( GetHierarchyURL() );
1421 : aLinkObj.insertName( rTitle, false,
1422 : INetURLObject::LAST_SEGMENT, true,
1423 0 : INetURLObject::ENCODE_ALL );
1424 0 : OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE );
1425 :
1426 : DocTempl_EntryData_Impl* pEntry;
1427 0 : bool bFound = false;
1428 0 : size_t nPos = GetEntryPos( rTitle, bFound );
1429 :
1430 0 : if ( bFound )
1431 : {
1432 0 : pEntry = maEntries[ nPos ];
1433 : }
1434 : else
1435 : {
1436 0 : if ( pPos )
1437 0 : nPos = *pPos;
1438 :
1439 0 : pEntry = new DocTempl_EntryData_Impl( this, rTitle );
1440 0 : pEntry->SetTargetURL( rTargetURL );
1441 0 : pEntry->SetHierarchyURL( aLinkURL );
1442 0 : if ( nPos < maEntries.size() ) {
1443 0 : vector< DocTempl_EntryData_Impl* >::iterator it = maEntries.begin();
1444 0 : advance( it, nPos );
1445 0 : maEntries.insert( it, pEntry );
1446 : }
1447 : else
1448 0 : maEntries.push_back( pEntry );
1449 0 : }
1450 0 : }
1451 :
1452 :
1453 0 : size_t RegionData_Impl::GetCount() const
1454 : {
1455 0 : return maEntries.size();
1456 : }
1457 :
1458 :
1459 0 : const OUString& RegionData_Impl::GetHierarchyURL()
1460 : {
1461 0 : if ( maOwnURL.isEmpty() )
1462 : {
1463 0 : INetURLObject aRegionObj( GetParent()->GetRootURL() );
1464 :
1465 0 : aRegionObj.insertName( GetTitle(), false,
1466 : INetURLObject::LAST_SEGMENT, true,
1467 0 : INetURLObject::ENCODE_ALL );
1468 :
1469 0 : maOwnURL = aRegionObj.GetMainURL( INetURLObject::NO_DECODE );
1470 0 : DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1471 : }
1472 :
1473 0 : return maOwnURL;
1474 : }
1475 :
1476 :
1477 0 : DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( const OUString& rName ) const
1478 : {
1479 0 : bool bFound = false;
1480 0 : long nPos = GetEntryPos( rName, bFound );
1481 :
1482 0 : if ( bFound )
1483 0 : return maEntries[ nPos ];
1484 : else
1485 0 : return NULL;
1486 : }
1487 :
1488 :
1489 0 : DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( size_t nIndex ) const
1490 : {
1491 0 : if ( nIndex < maEntries.size() )
1492 0 : return maEntries[ nIndex ];
1493 0 : return NULL;
1494 : }
1495 :
1496 :
1497 0 : void RegionData_Impl::DeleteEntry( size_t nIndex )
1498 : {
1499 0 : if ( nIndex < maEntries.size() )
1500 : {
1501 0 : delete maEntries[ nIndex ];
1502 0 : vector< DocTempl_EntryData_Impl*>::iterator it = maEntries.begin();
1503 0 : advance( it, nIndex );
1504 0 : maEntries.erase( it );
1505 : }
1506 0 : }
1507 :
1508 :
1509 0 : int RegionData_Impl::Compare( RegionData_Impl* pCompare ) const
1510 : {
1511 0 : int nCompare = maTitle.compareTo( pCompare->maTitle );
1512 :
1513 0 : return nCompare;
1514 : }
1515 :
1516 :
1517 :
1518 0 : SfxDocTemplate_Impl::SfxDocTemplate_Impl()
1519 : : mbConstructed( false )
1520 0 : , mnLockCounter( 0 )
1521 : {
1522 0 : }
1523 :
1524 :
1525 0 : SfxDocTemplate_Impl::~SfxDocTemplate_Impl()
1526 : {
1527 0 : Clear();
1528 :
1529 0 : gpTemplateData = NULL;
1530 0 : }
1531 :
1532 :
1533 0 : void SfxDocTemplate_Impl::IncrementLock()
1534 : {
1535 0 : ::osl::MutexGuard aGuard( maMutex );
1536 0 : mnLockCounter++;
1537 0 : }
1538 :
1539 :
1540 0 : void SfxDocTemplate_Impl::DecrementLock()
1541 : {
1542 0 : ::osl::MutexGuard aGuard( maMutex );
1543 0 : if ( mnLockCounter )
1544 0 : mnLockCounter--;
1545 0 : }
1546 :
1547 :
1548 0 : RegionData_Impl* SfxDocTemplate_Impl::GetRegion( size_t nIndex ) const
1549 : {
1550 0 : if ( nIndex < maRegions.size() )
1551 0 : return maRegions[ nIndex ];
1552 0 : return NULL;
1553 : }
1554 :
1555 :
1556 0 : RegionData_Impl* SfxDocTemplate_Impl::GetRegion( const OUString& rName )
1557 : const
1558 : {
1559 0 : for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
1560 : {
1561 0 : RegionData_Impl* pData = maRegions[ i ];
1562 0 : if( pData->GetTitle() == rName )
1563 0 : return pData;
1564 : }
1565 0 : return NULL;
1566 : }
1567 :
1568 :
1569 0 : void SfxDocTemplate_Impl::DeleteRegion( size_t nIndex )
1570 : {
1571 0 : if ( nIndex < maRegions.size() )
1572 : {
1573 0 : delete maRegions[ nIndex ];
1574 0 : RegionList_Impl::iterator it = maRegions.begin();
1575 0 : advance( it, nIndex );
1576 0 : maRegions.erase( it );
1577 : }
1578 0 : }
1579 :
1580 :
1581 : /* AddRegion adds a Region to the RegionList
1582 : */
1583 0 : void SfxDocTemplate_Impl::AddRegion( const OUString& rTitle,
1584 : Content& rContent )
1585 : {
1586 : RegionData_Impl* pRegion;
1587 0 : pRegion = new RegionData_Impl( this, rTitle );
1588 :
1589 0 : if ( ! InsertRegion( pRegion ) )
1590 : {
1591 0 : delete pRegion;
1592 0 : return;
1593 : }
1594 :
1595 : // now get the content of the region
1596 0 : uno::Reference< XResultSet > xResultSet;
1597 0 : Sequence< OUString > aProps(2);
1598 0 : aProps[0] = TITLE;
1599 0 : aProps[1] = TARGET_URL;
1600 :
1601 : try
1602 : {
1603 0 : ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1604 0 : Sequence< NumberedSortingInfo > aSortingInfo(1);
1605 0 : aSortingInfo.getArray()->ColumnIndex = 1;
1606 0 : aSortingInfo.getArray()->Ascending = sal_True;
1607 0 : xResultSet = rContent.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
1608 : }
1609 0 : catch ( Exception& ) {}
1610 :
1611 0 : if ( xResultSet.is() )
1612 : {
1613 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
1614 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
1615 :
1616 : try
1617 : {
1618 0 : while ( xResultSet->next() )
1619 : {
1620 0 : OUString aTitle( xRow->getString( 1 ) );
1621 0 : OUString aTargetDir( xRow->getString( 2 ) );
1622 :
1623 0 : pRegion->AddEntry( aTitle, aTargetDir );
1624 0 : }
1625 : }
1626 0 : catch ( Exception& ) {}
1627 0 : }
1628 : }
1629 :
1630 :
1631 0 : void SfxDocTemplate_Impl::CreateFromHierarchy( Content &rTemplRoot )
1632 : {
1633 0 : uno::Reference< XResultSet > xResultSet;
1634 0 : Sequence< OUString > aProps(1);
1635 0 : aProps[0] = TITLE;
1636 :
1637 : try
1638 : {
1639 0 : ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY;
1640 0 : Sequence< NumberedSortingInfo > aSortingInfo(1);
1641 0 : aSortingInfo.getArray()->ColumnIndex = 1;
1642 0 : aSortingInfo.getArray()->Ascending = sal_True;
1643 0 : xResultSet = rTemplRoot.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
1644 : }
1645 0 : catch ( Exception& ) {}
1646 :
1647 0 : if ( xResultSet.is() )
1648 : {
1649 0 : uno::Reference< XCommandEnvironment > aCmdEnv;
1650 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
1651 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
1652 :
1653 : try
1654 : {
1655 0 : while ( xResultSet->next() )
1656 : {
1657 0 : OUString aTitle( xRow->getString( 1 ) );
1658 :
1659 0 : OUString aId = xContentAccess->queryContentIdentifierString();
1660 0 : Content aContent = Content( aId, aCmdEnv, comphelper::getProcessComponentContext() );
1661 :
1662 0 : AddRegion( aTitle, aContent );
1663 0 : }
1664 : }
1665 0 : catch ( Exception& ) {}
1666 0 : }
1667 0 : }
1668 :
1669 :
1670 0 : bool SfxDocTemplate_Impl::Construct( )
1671 : {
1672 0 : ::osl::MutexGuard aGuard( maMutex );
1673 :
1674 0 : if ( mbConstructed )
1675 0 : return true;
1676 :
1677 0 : uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1678 :
1679 0 : uno::Reference< XPersist > xInfo( document::DocumentProperties::create(xContext), UNO_QUERY );
1680 0 : mxInfo = xInfo;
1681 :
1682 0 : mxTemplates = frame::DocumentTemplates::create(xContext);
1683 :
1684 0 : uno::Reference< XLocalizable > xLocalizable( mxTemplates, UNO_QUERY );
1685 :
1686 0 : m_rCompareFactory = AnyCompareFactory::createWithLocale(xContext, xLocalizable->getLocale());
1687 :
1688 0 : uno::Reference < XContent > aRootContent = mxTemplates->getContent();
1689 0 : uno::Reference < XCommandEnvironment > aCmdEnv;
1690 :
1691 0 : if ( ! aRootContent.is() )
1692 0 : return false;
1693 :
1694 0 : mbConstructed = true;
1695 0 : maRootURL = aRootContent->getIdentifier()->getContentIdentifier();
1696 :
1697 0 : ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) );
1698 :
1699 0 : if ( aLongNames.Count() )
1700 0 : maStandardGroup = aLongNames.GetString( 0 );
1701 :
1702 0 : Content aTemplRoot( aRootContent, aCmdEnv, xContext );
1703 0 : CreateFromHierarchy( aTemplRoot );
1704 :
1705 0 : return true;
1706 : }
1707 :
1708 :
1709 0 : void SfxDocTemplate_Impl::ReInitFromComponent()
1710 : {
1711 0 : uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
1712 0 : if ( xTemplates.is() )
1713 : {
1714 0 : uno::Reference < XContent > aRootContent = xTemplates->getContent();
1715 0 : uno::Reference < XCommandEnvironment > aCmdEnv;
1716 0 : Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
1717 0 : Clear();
1718 0 : CreateFromHierarchy( aTemplRoot );
1719 0 : }
1720 0 : }
1721 :
1722 :
1723 0 : bool SfxDocTemplate_Impl::InsertRegion( RegionData_Impl *pNew, size_t nPos )
1724 : {
1725 0 : ::osl::MutexGuard aGuard( maMutex );
1726 :
1727 : // return false (not inserted) if the entry already exists
1728 0 : for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
1729 0 : if ( maRegions[ i ]->Compare( pNew ) == 0 )
1730 0 : return false;
1731 :
1732 0 : size_t newPos = nPos;
1733 0 : if ( pNew->GetTitle() == maStandardGroup )
1734 0 : newPos = 0;
1735 :
1736 0 : if ( newPos < maRegions.size() )
1737 : {
1738 0 : RegionList_Impl::iterator it = maRegions.begin();
1739 0 : advance( it, newPos );
1740 0 : maRegions.insert( it, pNew );
1741 : }
1742 : else
1743 0 : maRegions.push_back( pNew );
1744 :
1745 0 : return true;
1746 : }
1747 :
1748 :
1749 0 : void SfxDocTemplate_Impl::Rescan()
1750 : {
1751 0 : Clear();
1752 :
1753 : try
1754 : {
1755 0 : uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
1756 : DBG_ASSERT( xTemplates.is(), "SfxDocTemplate_Impl::Rescan:invalid template instance!" );
1757 0 : if ( xTemplates.is() )
1758 : {
1759 0 : xTemplates->update();
1760 :
1761 0 : uno::Reference < XContent > aRootContent = xTemplates->getContent();
1762 0 : uno::Reference < XCommandEnvironment > aCmdEnv;
1763 :
1764 0 : Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
1765 0 : CreateFromHierarchy( aTemplRoot );
1766 0 : }
1767 : }
1768 0 : catch( const Exception& )
1769 : {
1770 : SAL_WARN( "sfx.doc", "SfxDocTemplate_Impl::Rescan: caught an exception while doing the update!" );
1771 : }
1772 0 : }
1773 :
1774 :
1775 0 : bool SfxDocTemplate_Impl::GetTitleFromURL( const OUString& rURL,
1776 : OUString& aTitle )
1777 : {
1778 0 : if ( mxInfo.is() )
1779 : {
1780 : try
1781 : {
1782 0 : mxInfo->read( rURL );
1783 : }
1784 0 : catch ( Exception& )
1785 : {
1786 : // the document is not a StarOffice document
1787 0 : return false;
1788 : }
1789 :
1790 :
1791 : try
1792 : {
1793 0 : uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
1794 0 : if ( aPropSet.is() )
1795 : {
1796 0 : OUString aPropName( TITLE );
1797 0 : Any aValue = aPropSet->getPropertyValue( aPropName );
1798 0 : aValue >>= aTitle;
1799 0 : }
1800 : }
1801 0 : catch ( IOException& ) {}
1802 0 : catch ( UnknownPropertyException& ) {}
1803 0 : catch ( Exception& ) {}
1804 : }
1805 :
1806 0 : if ( aTitle.isEmpty() )
1807 : {
1808 0 : INetURLObject aURL( rURL );
1809 0 : aURL.CutExtension();
1810 0 : aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
1811 0 : INetURLObject::DECODE_WITH_CHARSET );
1812 : }
1813 :
1814 0 : return true;
1815 : }
1816 :
1817 :
1818 :
1819 0 : void SfxDocTemplate_Impl::Clear()
1820 : {
1821 0 : ::osl::MutexGuard aGuard( maMutex );
1822 0 : if ( mnLockCounter )
1823 0 : return;
1824 :
1825 0 : for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
1826 0 : delete maRegions[ i ];
1827 0 : maRegions.clear();
1828 : }
1829 :
1830 :
1831 0 : bool getTextProperty_Impl( Content& rContent,
1832 : const OUString& rPropName,
1833 : OUString& rPropValue )
1834 : {
1835 0 : bool bGotProperty = false;
1836 :
1837 : // Get the property
1838 : try
1839 : {
1840 0 : uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1841 :
1842 : // check, whether or not the property exists
1843 0 : if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1844 : {
1845 0 : return false;
1846 : }
1847 :
1848 : // now get the property
1849 0 : Any aAnyValue;
1850 :
1851 0 : aAnyValue = rContent.getPropertyValue( rPropName );
1852 0 : aAnyValue >>= rPropValue;
1853 :
1854 0 : if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1855 : {
1856 0 : SfxURLRelocator_Impl aRelocImpl( ::comphelper::getProcessComponentContext() );
1857 0 : aRelocImpl.makeAbsoluteURL( rPropValue );
1858 : }
1859 :
1860 0 : bGotProperty = true;
1861 : }
1862 0 : catch ( RuntimeException& ) {}
1863 0 : catch ( Exception& ) {}
1864 :
1865 0 : return bGotProperty;
1866 : }
1867 :
1868 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|