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 controls 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 1 : uno::Reference< XDocumentTemplates > getDocTemplates() { return mxTemplates; }
241 : };
242 :
243 :
244 :
245 : class DocTemplLocker_Impl
246 : {
247 : SfxDocTemplate_Impl& m_aDocTempl;
248 : public:
249 39 : DocTemplLocker_Impl( SfxDocTemplate_Impl& aDocTempl )
250 39 : : m_aDocTempl( aDocTempl )
251 : {
252 39 : m_aDocTempl.IncrementLock();
253 39 : }
254 :
255 39 : ~DocTemplLocker_Impl()
256 : {
257 39 : m_aDocTempl.DecrementLock();
258 39 : }
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 // vcl::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 vcl::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 // vcl::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 vcl::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.clear();
341 : }
342 : else
343 0 : maTmpString.clear();
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 /* vcl::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, // vcl::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.clear();
436 : }
437 : else
438 0 : maTmpString.clear();
439 :
440 0 : return maTmpString;
441 : }
442 :
443 :
444 :
445 0 : OUString SfxDocumentTemplates::GetPath
446 : (
447 : sal_uInt16 nRegion, // vcl::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 vcl::Region Index
538 : sal_uInt16 nTargetIdx, // Target position Index
539 : sal_uInt16 nSourceRegion, // Source vcl::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 vcl::Region Index
644 : sal_uInt16 nTargetIdx, // Target position Index
645 : sal_uInt16 nSourceRegion, // Source vcl::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 vcl::Region Index
674 : sal_uInt16 nTargetIdx, // Target position Index
675 : sal_uInt16 nSourceRegion, // Source vcl::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, // vcl::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, /* vcl::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] Success (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, // vcl::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 // vcl::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 39 : bool SfxDocumentTemplates::GetFull
1105 : (
1106 : const OUString &rRegion, // vcl::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 39 : DocTemplLocker_Impl aLocker( *pImp );
1127 :
1128 : // We don't search for empty names!
1129 39 : if ( rName.isEmpty() )
1130 0 : return false;
1131 :
1132 39 : if ( ! pImp->Construct() )
1133 39 : 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: vcl::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( INetProtocol::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 45 : SfxDocumentTemplates::SfxDocumentTemplates()
1229 :
1230 : /* [Description]
1231 :
1232 : Constructor
1233 : */
1234 : {
1235 45 : if ( !gpTemplateData )
1236 41 : gpTemplateData = new SfxDocTemplate_Impl;
1237 :
1238 45 : pImp = gpTemplateData;
1239 45 : }
1240 :
1241 :
1242 :
1243 84 : SfxDocumentTemplates::~SfxDocumentTemplates()
1244 :
1245 : /* [Description]
1246 :
1247 : Destructor
1248 : Release of administrative data
1249 : */
1250 :
1251 : {
1252 42 : pImp = NULL;
1253 42 : }
1254 :
1255 0 : void SfxDocumentTemplates::Update( bool _bSmart )
1256 : {
1257 0 : if ( !_bSmart // don't be smart
1258 0 : || ::svt::TemplateFolderCache( true ).needsUpdate() // update is really necessary
1259 : )
1260 : {
1261 0 : if ( pImp->Construct() )
1262 0 : pImp->Rescan();
1263 : }
1264 0 : }
1265 :
1266 1 : void SfxDocumentTemplates::ReInitFromComponent()
1267 : {
1268 1 : pImp->ReInitFromComponent();
1269 1 : }
1270 :
1271 :
1272 0 : DocTempl_EntryData_Impl::DocTempl_EntryData_Impl( RegionData_Impl* pParent,
1273 0 : const OUString& rTitle )
1274 : {
1275 0 : mpParent = pParent;
1276 0 : maTitle = SfxDocumentTemplates::ConvertResourceString(
1277 0 : STR_TEMPLATE_NAME1_DEF, STR_TEMPLATE_NAME1, NUM_TEMPLATE_NAMES, rTitle );
1278 0 : mbIsOwner = false;
1279 0 : mbDidConvert= false;
1280 0 : }
1281 :
1282 :
1283 0 : int DocTempl_EntryData_Impl::Compare( const OUString& rTitle ) const
1284 : {
1285 0 : return maTitle.compareTo( rTitle );
1286 : }
1287 :
1288 :
1289 0 : const OUString& DocTempl_EntryData_Impl::GetHierarchyURL()
1290 : {
1291 0 : if ( maOwnURL.isEmpty() )
1292 : {
1293 0 : INetURLObject aTemplateObj( GetParent()->GetHierarchyURL() );
1294 :
1295 0 : aTemplateObj.insertName( GetTitle(), false,
1296 : INetURLObject::LAST_SEGMENT, true,
1297 0 : INetURLObject::ENCODE_ALL );
1298 :
1299 0 : maOwnURL = aTemplateObj.GetMainURL( INetURLObject::NO_DECODE );
1300 0 : DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1301 : }
1302 :
1303 0 : return maOwnURL;
1304 : }
1305 :
1306 :
1307 0 : const OUString& DocTempl_EntryData_Impl::GetTargetURL()
1308 : {
1309 0 : if ( maTargetURL.isEmpty() )
1310 : {
1311 0 : uno::Reference< XCommandEnvironment > aCmdEnv;
1312 0 : Content aRegion;
1313 :
1314 0 : if ( Content::create( GetHierarchyURL(), aCmdEnv, comphelper::getProcessComponentContext(), aRegion ) )
1315 : {
1316 0 : OUString aPropName( TARGET_URL );
1317 :
1318 0 : getTextProperty_Impl( aRegion, aPropName, maTargetURL );
1319 : }
1320 : else
1321 : {
1322 : SAL_WARN( "sfx.doc", "GetTargetURL(): Could not create hierarchy content!" );
1323 0 : }
1324 : }
1325 :
1326 0 : return maTargetURL;
1327 : }
1328 :
1329 :
1330 0 : RegionData_Impl::RegionData_Impl( const SfxDocTemplate_Impl* pParent,
1331 0 : const OUString& rTitle )
1332 : {
1333 0 : maTitle = rTitle;
1334 0 : mpParent = pParent;
1335 0 : }
1336 :
1337 :
1338 0 : RegionData_Impl::~RegionData_Impl()
1339 : {
1340 0 : for ( size_t i = 0, n = maEntries.size(); i < n; ++i )
1341 0 : delete maEntries[ i ];
1342 0 : maEntries.clear();
1343 0 : }
1344 :
1345 :
1346 0 : size_t RegionData_Impl::GetEntryPos( const OUString& rTitle, bool& rFound ) const
1347 : {
1348 : #if 1 // Don't use binary search today
1349 : size_t i;
1350 0 : size_t nCount = maEntries.size();
1351 :
1352 0 : for ( i=0; i<nCount; i++ )
1353 : {
1354 0 : DocTempl_EntryData_Impl *pData = maEntries[ i ];
1355 :
1356 0 : if ( pData->Compare( rTitle ) == 0 )
1357 : {
1358 0 : rFound = true;
1359 0 : return i;
1360 : }
1361 : }
1362 :
1363 0 : rFound = false;
1364 0 : return i;
1365 :
1366 : #else
1367 : // use binary search to find the correct position
1368 : // in the maEntries list
1369 :
1370 : int nCompVal = 1;
1371 : size_t nStart = 0;
1372 : size_t nEnd = maEntries.size() - 1;
1373 : size_t nMid;
1374 :
1375 : DocTempl_EntryData_Impl* pMid;
1376 :
1377 : rFound = sal_False;
1378 :
1379 : while ( nCompVal && ( nStart <= nEnd ) )
1380 : {
1381 : nMid = ( nEnd - nStart ) / 2 + nStart;
1382 : pMid = maEntries[ nMid ];
1383 :
1384 : nCompVal = pMid->Compare( rTitle );
1385 :
1386 : if ( nCompVal < 0 ) // pMid < pData
1387 : nStart = nMid + 1;
1388 : else
1389 : nEnd = nMid - 1;
1390 : }
1391 :
1392 : if ( nCompVal == 0 )
1393 : {
1394 : rFound = sal_True;
1395 : }
1396 : else
1397 : {
1398 : if ( nCompVal < 0 ) // pMid < pData
1399 : nMid++;
1400 : }
1401 :
1402 : return nMid;
1403 : #endif
1404 : }
1405 :
1406 :
1407 0 : void RegionData_Impl::AddEntry( const OUString& rTitle,
1408 : const OUString& rTargetURL,
1409 : size_t *pPos )
1410 : {
1411 0 : INetURLObject aLinkObj( GetHierarchyURL() );
1412 : aLinkObj.insertName( rTitle, false,
1413 : INetURLObject::LAST_SEGMENT, true,
1414 0 : INetURLObject::ENCODE_ALL );
1415 0 : OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE );
1416 :
1417 : DocTempl_EntryData_Impl* pEntry;
1418 0 : bool bFound = false;
1419 0 : size_t nPos = GetEntryPos( rTitle, bFound );
1420 :
1421 0 : if ( bFound )
1422 : {
1423 0 : pEntry = maEntries[ nPos ];
1424 : }
1425 : else
1426 : {
1427 0 : if ( pPos )
1428 0 : nPos = *pPos;
1429 :
1430 0 : pEntry = new DocTempl_EntryData_Impl( this, rTitle );
1431 0 : pEntry->SetTargetURL( rTargetURL );
1432 0 : pEntry->SetHierarchyURL( aLinkURL );
1433 0 : if ( nPos < maEntries.size() ) {
1434 0 : vector< DocTempl_EntryData_Impl* >::iterator it = maEntries.begin();
1435 0 : advance( it, nPos );
1436 0 : maEntries.insert( it, pEntry );
1437 : }
1438 : else
1439 0 : maEntries.push_back( pEntry );
1440 0 : }
1441 0 : }
1442 :
1443 :
1444 0 : size_t RegionData_Impl::GetCount() const
1445 : {
1446 0 : return maEntries.size();
1447 : }
1448 :
1449 :
1450 0 : const OUString& RegionData_Impl::GetHierarchyURL()
1451 : {
1452 0 : if ( maOwnURL.isEmpty() )
1453 : {
1454 0 : INetURLObject aRegionObj( GetParent()->GetRootURL() );
1455 :
1456 0 : aRegionObj.insertName( GetTitle(), false,
1457 : INetURLObject::LAST_SEGMENT, true,
1458 0 : INetURLObject::ENCODE_ALL );
1459 :
1460 0 : maOwnURL = aRegionObj.GetMainURL( INetURLObject::NO_DECODE );
1461 0 : DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1462 : }
1463 :
1464 0 : return maOwnURL;
1465 : }
1466 :
1467 :
1468 0 : DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( const OUString& rName ) const
1469 : {
1470 0 : bool bFound = false;
1471 0 : long nPos = GetEntryPos( rName, bFound );
1472 :
1473 0 : if ( bFound )
1474 0 : return maEntries[ nPos ];
1475 : else
1476 0 : return NULL;
1477 : }
1478 :
1479 :
1480 0 : DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( size_t nIndex ) const
1481 : {
1482 0 : if ( nIndex < maEntries.size() )
1483 0 : return maEntries[ nIndex ];
1484 0 : return NULL;
1485 : }
1486 :
1487 :
1488 0 : void RegionData_Impl::DeleteEntry( size_t nIndex )
1489 : {
1490 0 : if ( nIndex < maEntries.size() )
1491 : {
1492 0 : delete maEntries[ nIndex ];
1493 0 : vector< DocTempl_EntryData_Impl*>::iterator it = maEntries.begin();
1494 0 : advance( it, nIndex );
1495 0 : maEntries.erase( it );
1496 : }
1497 0 : }
1498 :
1499 :
1500 0 : int RegionData_Impl::Compare( RegionData_Impl* pCompare ) const
1501 : {
1502 0 : int nCompare = maTitle.compareTo( pCompare->maTitle );
1503 :
1504 0 : return nCompare;
1505 : }
1506 :
1507 :
1508 :
1509 41 : SfxDocTemplate_Impl::SfxDocTemplate_Impl()
1510 : : mbConstructed( false )
1511 41 : , mnLockCounter( 0 )
1512 : {
1513 41 : }
1514 :
1515 :
1516 114 : SfxDocTemplate_Impl::~SfxDocTemplate_Impl()
1517 : {
1518 38 : Clear();
1519 :
1520 38 : gpTemplateData = NULL;
1521 76 : }
1522 :
1523 :
1524 39 : void SfxDocTemplate_Impl::IncrementLock()
1525 : {
1526 39 : ::osl::MutexGuard aGuard( maMutex );
1527 39 : mnLockCounter++;
1528 39 : }
1529 :
1530 :
1531 39 : void SfxDocTemplate_Impl::DecrementLock()
1532 : {
1533 39 : ::osl::MutexGuard aGuard( maMutex );
1534 39 : if ( mnLockCounter )
1535 39 : mnLockCounter--;
1536 39 : }
1537 :
1538 :
1539 0 : RegionData_Impl* SfxDocTemplate_Impl::GetRegion( size_t nIndex ) const
1540 : {
1541 0 : if ( nIndex < maRegions.size() )
1542 0 : return maRegions[ nIndex ];
1543 0 : return NULL;
1544 : }
1545 :
1546 :
1547 0 : RegionData_Impl* SfxDocTemplate_Impl::GetRegion( const OUString& rName )
1548 : const
1549 : {
1550 0 : for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
1551 : {
1552 0 : RegionData_Impl* pData = maRegions[ i ];
1553 0 : if( pData->GetTitle() == rName )
1554 0 : return pData;
1555 : }
1556 0 : return NULL;
1557 : }
1558 :
1559 :
1560 0 : void SfxDocTemplate_Impl::DeleteRegion( size_t nIndex )
1561 : {
1562 0 : if ( nIndex < maRegions.size() )
1563 : {
1564 0 : delete maRegions[ nIndex ];
1565 0 : RegionList_Impl::iterator it = maRegions.begin();
1566 0 : advance( it, nIndex );
1567 0 : maRegions.erase( it );
1568 : }
1569 0 : }
1570 :
1571 :
1572 : /* AddRegion adds a vcl::Region to the RegionList
1573 : */
1574 0 : void SfxDocTemplate_Impl::AddRegion( const OUString& rTitle,
1575 : Content& rContent )
1576 : {
1577 : RegionData_Impl* pRegion;
1578 0 : pRegion = new RegionData_Impl( this, rTitle );
1579 :
1580 0 : if ( ! InsertRegion( pRegion ) )
1581 : {
1582 0 : delete pRegion;
1583 0 : return;
1584 : }
1585 :
1586 : // now get the content of the region
1587 0 : uno::Reference< XResultSet > xResultSet;
1588 0 : Sequence< OUString > aProps(2);
1589 0 : aProps[0] = TITLE;
1590 0 : aProps[1] = TARGET_URL;
1591 :
1592 : try
1593 : {
1594 0 : ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1595 0 : Sequence< NumberedSortingInfo > aSortingInfo(1);
1596 0 : aSortingInfo.getArray()->ColumnIndex = 1;
1597 0 : aSortingInfo.getArray()->Ascending = sal_True;
1598 0 : xResultSet = rContent.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
1599 : }
1600 0 : catch ( Exception& ) {}
1601 :
1602 0 : if ( xResultSet.is() )
1603 : {
1604 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
1605 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
1606 :
1607 : try
1608 : {
1609 0 : while ( xResultSet->next() )
1610 : {
1611 0 : OUString aTitle( xRow->getString( 1 ) );
1612 0 : OUString aTargetDir( xRow->getString( 2 ) );
1613 :
1614 0 : pRegion->AddEntry( aTitle, aTargetDir );
1615 0 : }
1616 : }
1617 0 : catch ( Exception& ) {}
1618 0 : }
1619 : }
1620 :
1621 :
1622 1 : void SfxDocTemplate_Impl::CreateFromHierarchy( Content &rTemplRoot )
1623 : {
1624 1 : uno::Reference< XResultSet > xResultSet;
1625 2 : Sequence< OUString > aProps(1);
1626 1 : aProps[0] = TITLE;
1627 :
1628 : try
1629 : {
1630 1 : ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY;
1631 1 : Sequence< NumberedSortingInfo > aSortingInfo(1);
1632 1 : aSortingInfo.getArray()->ColumnIndex = 1;
1633 1 : aSortingInfo.getArray()->Ascending = sal_True;
1634 1 : xResultSet = rTemplRoot.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
1635 : }
1636 0 : catch ( Exception& ) {}
1637 :
1638 1 : if ( xResultSet.is() )
1639 : {
1640 0 : uno::Reference< XCommandEnvironment > aCmdEnv;
1641 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
1642 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
1643 :
1644 : try
1645 : {
1646 0 : while ( xResultSet->next() )
1647 : {
1648 0 : OUString aTitle( xRow->getString( 1 ) );
1649 :
1650 0 : OUString aId = xContentAccess->queryContentIdentifierString();
1651 0 : Content aContent = Content( aId, aCmdEnv, comphelper::getProcessComponentContext() );
1652 :
1653 0 : AddRegion( aTitle, aContent );
1654 0 : }
1655 : }
1656 0 : catch ( Exception& ) {}
1657 1 : }
1658 1 : }
1659 :
1660 :
1661 39 : bool SfxDocTemplate_Impl::Construct( )
1662 : {
1663 39 : ::osl::MutexGuard aGuard( maMutex );
1664 :
1665 39 : if ( mbConstructed )
1666 0 : return true;
1667 :
1668 78 : uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1669 :
1670 78 : uno::Reference< XPersist > xInfo( document::DocumentProperties::create(xContext), UNO_QUERY );
1671 39 : mxInfo = xInfo;
1672 :
1673 39 : mxTemplates = frame::DocumentTemplates::create(xContext);
1674 :
1675 78 : uno::Reference< XLocalizable > xLocalizable( mxTemplates, UNO_QUERY );
1676 :
1677 39 : m_rCompareFactory = AnyCompareFactory::createWithLocale(xContext, xLocalizable->getLocale());
1678 :
1679 78 : uno::Reference < XContent > aRootContent = mxTemplates->getContent();
1680 78 : uno::Reference < XCommandEnvironment > aCmdEnv;
1681 :
1682 39 : if ( ! aRootContent.is() )
1683 39 : return false;
1684 :
1685 0 : mbConstructed = true;
1686 0 : maRootURL = aRootContent->getIdentifier()->getContentIdentifier();
1687 :
1688 0 : ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) );
1689 :
1690 0 : if ( aLongNames.Count() )
1691 0 : maStandardGroup = aLongNames.GetString( 0 );
1692 :
1693 0 : Content aTemplRoot( aRootContent, aCmdEnv, xContext );
1694 0 : CreateFromHierarchy( aTemplRoot );
1695 :
1696 39 : return true;
1697 : }
1698 :
1699 :
1700 1 : void SfxDocTemplate_Impl::ReInitFromComponent()
1701 : {
1702 1 : uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
1703 1 : if ( xTemplates.is() )
1704 : {
1705 1 : uno::Reference < XContent > aRootContent = xTemplates->getContent();
1706 2 : uno::Reference < XCommandEnvironment > aCmdEnv;
1707 2 : Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
1708 1 : Clear();
1709 2 : CreateFromHierarchy( aTemplRoot );
1710 1 : }
1711 1 : }
1712 :
1713 :
1714 0 : bool SfxDocTemplate_Impl::InsertRegion( RegionData_Impl *pNew, size_t nPos )
1715 : {
1716 0 : ::osl::MutexGuard aGuard( maMutex );
1717 :
1718 : // return false (not inserted) if the entry already exists
1719 0 : for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
1720 0 : if ( maRegions[ i ]->Compare( pNew ) == 0 )
1721 0 : return false;
1722 :
1723 0 : size_t newPos = nPos;
1724 0 : if ( pNew->GetTitle() == maStandardGroup )
1725 0 : newPos = 0;
1726 :
1727 0 : if ( newPos < maRegions.size() )
1728 : {
1729 0 : RegionList_Impl::iterator it = maRegions.begin();
1730 0 : advance( it, newPos );
1731 0 : maRegions.insert( it, pNew );
1732 : }
1733 : else
1734 0 : maRegions.push_back( pNew );
1735 :
1736 0 : return true;
1737 : }
1738 :
1739 :
1740 0 : void SfxDocTemplate_Impl::Rescan()
1741 : {
1742 0 : Clear();
1743 :
1744 : try
1745 : {
1746 0 : uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
1747 : DBG_ASSERT( xTemplates.is(), "SfxDocTemplate_Impl::Rescan:invalid template instance!" );
1748 0 : if ( xTemplates.is() )
1749 : {
1750 0 : xTemplates->update();
1751 :
1752 0 : uno::Reference < XContent > aRootContent = xTemplates->getContent();
1753 0 : uno::Reference < XCommandEnvironment > aCmdEnv;
1754 :
1755 0 : Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
1756 0 : CreateFromHierarchy( aTemplRoot );
1757 0 : }
1758 : }
1759 0 : catch( const Exception& )
1760 : {
1761 : SAL_WARN( "sfx.doc", "SfxDocTemplate_Impl::Rescan: caught an exception while doing the update!" );
1762 : }
1763 0 : }
1764 :
1765 :
1766 0 : bool SfxDocTemplate_Impl::GetTitleFromURL( const OUString& rURL,
1767 : OUString& aTitle )
1768 : {
1769 0 : if ( mxInfo.is() )
1770 : {
1771 : try
1772 : {
1773 0 : mxInfo->read( rURL );
1774 : }
1775 0 : catch ( Exception& )
1776 : {
1777 : // the document is not a StarOffice document
1778 0 : return false;
1779 : }
1780 :
1781 :
1782 : try
1783 : {
1784 0 : uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
1785 0 : if ( aPropSet.is() )
1786 : {
1787 0 : OUString aPropName( TITLE );
1788 0 : Any aValue = aPropSet->getPropertyValue( aPropName );
1789 0 : aValue >>= aTitle;
1790 0 : }
1791 : }
1792 0 : catch ( IOException& ) {}
1793 0 : catch ( UnknownPropertyException& ) {}
1794 0 : catch ( Exception& ) {}
1795 : }
1796 :
1797 0 : if ( aTitle.isEmpty() )
1798 : {
1799 0 : INetURLObject aURL( rURL );
1800 0 : aURL.CutExtension();
1801 0 : aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
1802 0 : INetURLObject::DECODE_WITH_CHARSET );
1803 : }
1804 :
1805 0 : return true;
1806 : }
1807 :
1808 :
1809 :
1810 39 : void SfxDocTemplate_Impl::Clear()
1811 : {
1812 39 : ::osl::MutexGuard aGuard( maMutex );
1813 39 : if ( mnLockCounter )
1814 39 : return;
1815 :
1816 39 : for ( size_t i = 0, n = maRegions.size(); i < n; ++i )
1817 0 : delete maRegions[ i ];
1818 39 : maRegions.clear();
1819 : }
1820 :
1821 :
1822 0 : bool getTextProperty_Impl( Content& rContent,
1823 : const OUString& rPropName,
1824 : OUString& rPropValue )
1825 : {
1826 0 : bool bGotProperty = false;
1827 :
1828 : // Get the property
1829 : try
1830 : {
1831 0 : uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1832 :
1833 : // check, whether or not the property exists
1834 0 : if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1835 : {
1836 0 : return false;
1837 : }
1838 :
1839 : // now get the property
1840 0 : Any aAnyValue;
1841 :
1842 0 : aAnyValue = rContent.getPropertyValue( rPropName );
1843 0 : aAnyValue >>= rPropValue;
1844 :
1845 0 : if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1846 : {
1847 0 : SfxURLRelocator_Impl aRelocImpl( ::comphelper::getProcessComponentContext() );
1848 0 : aRelocImpl.makeAbsoluteURL( rPropValue );
1849 : }
1850 :
1851 0 : bGotProperty = true;
1852 : }
1853 0 : catch ( RuntimeException& ) {}
1854 0 : catch ( Exception& ) {}
1855 :
1856 0 : return bGotProperty;
1857 : }
1858 :
1859 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|