summaryrefslogtreecommitdiffstats
path: root/sfx2/source/doc/doctempl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/doc/doctempl.cxx')
-rw-r--r--sfx2/source/doc/doctempl.cxx1751
1 files changed, 1751 insertions, 0 deletions
diff --git a/sfx2/source/doc/doctempl.cxx b/sfx2/source/doc/doctempl.cxx
new file mode 100644
index 0000000000..63d83f1298
--- /dev/null
+++ b/sfx2/source/doc/doctempl.cxx
@@ -0,0 +1,1751 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <limits.h>
+#include <mutex>
+#include <string_view>
+
+#include <com/sun/star/uno/Any.h>
+#include <sal/log.hxx>
+
+#include <unotools/pathoptions.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <ucbhelper/content.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/document/XTypeDetection.hpp>
+#include <com/sun/star/document/DocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/DocumentTemplates.hpp>
+#include <com/sun/star/frame/XDocumentTemplates.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/io/XPersist.hpp>
+#include <com/sun/star/lang/XLocalizable.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/ucb/ContentCreationException.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/ucb/AnyCompareFactory.hpp>
+#include <com/sun/star/ucb/NumberedSortingInfo.hpp>
+
+#include "doctemplateslocal.hxx"
+#include <sfxurlrelocator.hxx>
+
+#include <sfx2/doctempl.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/sfxresid.hxx>
+#include <sfx2/strings.hrc>
+#include <strings.hxx>
+#include <svtools/templatefoldercache.hxx>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::document;
+using namespace ::rtl;
+using namespace ::ucbhelper;
+
+constexpr OUString TITLE = u"Title"_ustr;
+constexpr OUString TARGET_URL = u"TargetURL"_ustr;
+
+constexpr OUStringLiteral COMMAND_TRANSFER = u"transfer";
+
+namespace {
+
+class RegionData_Impl;
+
+}
+
+namespace DocTempl {
+
+namespace {
+
+class DocTempl_EntryData_Impl
+{
+ RegionData_Impl* mpParent;
+
+ // the following member must be SfxObjectShellLock since it controls that SfxObjectShell lifetime by design
+ // and users of this class expect it to be so.
+ SfxObjectShellLock mxObjShell;
+
+ OUString maTitle;
+ OUString maOwnURL;
+ OUString maTargetURL;
+
+public:
+ DocTempl_EntryData_Impl( RegionData_Impl* pParent,
+ const OUString& rTitle );
+
+ const OUString& GetTitle() const { return maTitle; }
+ const OUString& GetTargetURL();
+ const OUString& GetHierarchyURL();
+
+ void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
+ void SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
+ void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
+
+ int Compare( std::u16string_view rTitle ) const;
+};
+
+}
+
+}
+
+using namespace ::DocTempl;
+
+namespace {
+
+class RegionData_Impl
+{
+ const SfxDocTemplate_Impl* mpParent;
+ std::vector<std::unique_ptr<DocTempl_EntryData_Impl>> maEntries;
+ OUString maTitle;
+ OUString maOwnURL;
+
+private:
+ size_t GetEntryPos( std::u16string_view rTitle,
+ bool& rFound ) const;
+
+public:
+ RegionData_Impl( const SfxDocTemplate_Impl* pParent,
+ OUString aTitle );
+
+ void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
+
+ DocTempl_EntryData_Impl* GetEntry( size_t nIndex ) const;
+ DocTempl_EntryData_Impl* GetEntry( std::u16string_view rName ) const;
+
+ const OUString& GetTitle() const { return maTitle; }
+ const OUString& GetHierarchyURL();
+
+ size_t GetCount() const;
+
+ void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
+
+ void AddEntry( const OUString& rTitle,
+ const OUString& rTargetURL,
+ const size_t *pPos );
+ void DeleteEntry( size_t nIndex );
+
+ int Compare( RegionData_Impl const * pCompareWith ) const;
+};
+
+}
+
+class SfxDocTemplate_Impl : public SvRefBase
+{
+ uno::Reference< XPersist > mxInfo;
+ uno::Reference< XDocumentTemplates > mxTemplates;
+
+ std::mutex maMutex;
+ OUString maRootURL;
+ OUString maStandardGroup;
+ std::vector<std::unique_ptr<RegionData_Impl>> maRegions;
+ bool mbConstructed;
+
+ uno::Reference< XAnyCompareFactory > m_rCompareFactory;
+
+ // the following member is intended to prevent clearing of the global data when it is in use
+ // TODO/LATER: it still does not make the implementation complete thread-safe
+ sal_Int32 mnLockCounter;
+
+private:
+ void Clear();
+
+public:
+ SfxDocTemplate_Impl();
+ virtual ~SfxDocTemplate_Impl() override;
+
+ void IncrementLock();
+ void DecrementLock();
+
+ bool Construct( );
+ void CreateFromHierarchy( std::unique_lock<std::mutex>& rGuard, Content &rTemplRoot );
+ void ReInitFromComponent();
+ void AddRegion( std::unique_lock<std::mutex>& rGuard,
+ const OUString& rTitle,
+ Content& rContent );
+
+ void Rescan();
+
+ void DeleteRegion( size_t nIndex );
+
+ size_t GetRegionCount() const
+ { return maRegions.size(); }
+ RegionData_Impl* GetRegion( std::u16string_view rName ) const;
+ RegionData_Impl* GetRegion( size_t nIndex ) const;
+
+ bool GetTitleFromURL( const OUString& rURL, OUString& aTitle );
+ bool InsertRegion( std::unique_ptr<RegionData_Impl> pData, size_t nPos );
+ const OUString& GetRootURL() const { return maRootURL; }
+
+ const uno::Reference< XDocumentTemplates >& getDocTemplates() const { return mxTemplates; }
+};
+
+namespace {
+
+class DocTemplLocker_Impl
+{
+ SfxDocTemplate_Impl& m_aDocTempl;
+public:
+ explicit DocTemplLocker_Impl( SfxDocTemplate_Impl& aDocTempl )
+ : m_aDocTempl( aDocTempl )
+ {
+ m_aDocTempl.IncrementLock();
+ }
+
+ ~DocTemplLocker_Impl()
+ {
+ m_aDocTempl.DecrementLock();
+ }
+};
+
+}
+
+static SfxDocTemplate_Impl *gpTemplateData = nullptr;
+
+
+static bool getTextProperty_Impl( Content& rContent,
+ const OUString& rPropName,
+ OUString& rPropValue );
+
+
+OUString SfxDocumentTemplates::GetFullRegionName
+(
+ sal_uInt16 nIdx // Region Index
+) const
+
+/* [Description]
+
+ Returns the logical name of a region and its path
+
+ [Return value] Reference to the Region name
+
+*/
+
+{
+ // First: find the RegionData for the index
+
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( pImp->Construct() )
+ {
+ RegionData_Impl *pData1 = pImp->GetRegion( nIdx );
+
+ if ( pData1 )
+ return pData1->GetTitle();
+
+ // --**-- here was some code which appended the path to the
+ // group if there was more than one with the same name.
+ // this should not happen anymore
+ }
+
+ return OUString();
+}
+
+
+OUString SfxDocumentTemplates::GetRegionName
+(
+ sal_uInt16 nIdx // Region Index
+) const
+
+/* [Description]
+
+ Returns the logical name of a region
+
+ [Return value]
+
+ const String& Reference to the Region name
+
+*/
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( pImp->Construct() )
+ {
+ RegionData_Impl *pData = pImp->GetRegion( nIdx );
+
+ if ( pData )
+ return pData->GetTitle();
+ }
+
+ return OUString();
+}
+
+
+sal_uInt16 SfxDocumentTemplates::GetRegionCount() const
+
+/* [Description]
+
+ Returns the number of Regions
+
+ [Return value]
+
+ sal_uInt16 Number of Regions
+*/
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( !pImp->Construct() )
+ return 0;
+
+ return pImp->GetRegionCount();
+}
+
+
+sal_uInt16 SfxDocumentTemplates::GetCount
+(
+ sal_uInt16 nRegion /* Region index whose number is
+ to be determined */
+
+) const
+
+/* [Description]
+
+ Number of entries in Region
+
+ [Return value] Number of entries
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( !pImp->Construct() )
+ return 0;
+
+ RegionData_Impl *pData = pImp->GetRegion( nRegion );
+
+ if ( !pData )
+ return 0;
+
+ return pData->GetCount();
+}
+
+
+OUString SfxDocumentTemplates::GetName
+(
+ sal_uInt16 nRegion, // Region Index, in which the entry lies
+ sal_uInt16 nIdx // Index of the entry
+) const
+
+/* [Description]
+
+ Returns the logical name of an entry in Region
+
+ [Return value]
+
+ const String& Entry Name
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( pImp->Construct() )
+ {
+ RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
+
+ if ( pRegion )
+ {
+ DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
+ if ( pEntry )
+ return pEntry->GetTitle();
+ }
+ }
+
+ return OUString();
+}
+
+
+OUString SfxDocumentTemplates::GetPath
+(
+ sal_uInt16 nRegion, // Region Index, in which the entry lies
+ sal_uInt16 nIdx // Index of the entry
+) const
+
+/* [Description]
+
+ Returns the file name with full path to the file assigned to an entry
+
+ [Return value]
+
+ String File name with full path
+*/
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( !pImp->Construct() )
+ return OUString();
+
+ RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
+
+ if ( pRegion )
+ {
+ DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
+ if ( pEntry )
+ return pEntry->GetTargetURL();
+ }
+
+ return OUString();
+}
+
+
+OUString SfxDocumentTemplates::GetTemplateTargetURLFromComponent( std::u16string_view aGroupName,
+ std::u16string_view aTitle )
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ INetURLObject aTemplateObj( pImp->GetRootURL() );
+
+ aTemplateObj.insertName( aGroupName, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+
+ aTemplateObj.insertName( aTitle, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+
+
+ Content aTemplate;
+ uno::Reference< XCommandEnvironment > aCmdEnv;
+ if ( Content::create( aTemplateObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
+ {
+ OUString aResult;
+ getTextProperty_Impl( aTemplate, TARGET_URL, aResult );
+ return SvtPathOptions().SubstituteVariable( aResult );
+ }
+
+ return OUString();
+}
+
+
+/** Convert a template name to its localised pair if it exists.
+ @param rString
+ Name to be translated.
+ @return
+ The localised pair of rString or rString if the former does not exist.
+*/
+OUString SfxDocumentTemplates::ConvertResourceString(const OUString& rString)
+{
+ static constexpr OUString aTemplateNames[] =
+ {
+ STR_TEMPLATE_NAME1_DEF,
+ STR_TEMPLATE_NAME2_DEF,
+ STR_TEMPLATE_NAME3_DEF,
+ STR_TEMPLATE_NAME4_DEF,
+ STR_TEMPLATE_NAME5_DEF,
+ STR_TEMPLATE_NAME6_DEF,
+ STR_TEMPLATE_NAME7_DEF,
+ STR_TEMPLATE_NAME8_DEF,
+ STR_TEMPLATE_NAME9_DEF,
+ STR_TEMPLATE_NAME10_DEF,
+ STR_TEMPLATE_NAME11_DEF,
+ STR_TEMPLATE_NAME12_DEF,
+ STR_TEMPLATE_NAME13_DEF,
+ STR_TEMPLATE_NAME14_DEF,
+ STR_TEMPLATE_NAME15_DEF,
+ STR_TEMPLATE_NAME16_DEF,
+ STR_TEMPLATE_NAME17_DEF,
+ STR_TEMPLATE_NAME18_DEF,
+ STR_TEMPLATE_NAME19_DEF,
+ STR_TEMPLATE_NAME20_DEF,
+ STR_TEMPLATE_NAME21_DEF,
+ STR_TEMPLATE_NAME22_DEF,
+ STR_TEMPLATE_NAME23_DEF,
+ STR_TEMPLATE_NAME24_DEF,
+ STR_TEMPLATE_NAME25_DEF,
+ STR_TEMPLATE_NAME26_DEF,
+ STR_TEMPLATE_NAME27_DEF,
+ STR_TEMPLATE_NAME28_DEF,
+ STR_TEMPLATE_NAME29_DEF,
+ STR_TEMPLATE_NAME30_DEF,
+ STR_TEMPLATE_NAME31_DEF,
+ STR_TEMPLATE_NAME32_DEF,
+ STR_TEMPLATE_NAME33_DEF,
+ STR_TEMPLATE_NAME34_DEF
+ };
+
+ TranslateId STR_TEMPLATE_NAME[] =
+ {
+ STR_TEMPLATE_NAME1,
+ STR_TEMPLATE_NAME2,
+ STR_TEMPLATE_NAME3,
+ STR_TEMPLATE_NAME4,
+ STR_TEMPLATE_NAME5,
+ STR_TEMPLATE_NAME6,
+ STR_TEMPLATE_NAME7,
+ STR_TEMPLATE_NAME8,
+ STR_TEMPLATE_NAME9,
+ STR_TEMPLATE_NAME10,
+ STR_TEMPLATE_NAME11,
+ STR_TEMPLATE_NAME12,
+ STR_TEMPLATE_NAME13,
+ STR_TEMPLATE_NAME14,
+ STR_TEMPLATE_NAME15,
+ STR_TEMPLATE_NAME16,
+ STR_TEMPLATE_NAME17,
+ STR_TEMPLATE_NAME18,
+ STR_TEMPLATE_NAME19,
+ STR_TEMPLATE_NAME20,
+ STR_TEMPLATE_NAME21,
+ STR_TEMPLATE_NAME22,
+ STR_TEMPLATE_NAME23,
+ STR_TEMPLATE_NAME24,
+ STR_TEMPLATE_NAME25,
+ STR_TEMPLATE_NAME26,
+ STR_TEMPLATE_NAME27,
+ STR_TEMPLATE_NAME28,
+ STR_TEMPLATE_NAME29,
+ STR_TEMPLATE_NAME30,
+ STR_TEMPLATE_NAME31,
+ STR_TEMPLATE_NAME32,
+ STR_TEMPLATE_NAME33,
+ STR_TEMPLATE_NAME34
+ };
+
+ static_assert(SAL_N_ELEMENTS(aTemplateNames) == SAL_N_ELEMENTS(STR_TEMPLATE_NAME));
+
+ for (size_t i = 0; i < SAL_N_ELEMENTS(STR_TEMPLATE_NAME); ++i)
+ {
+ if (rString == aTemplateNames[i])
+ return SfxResId(STR_TEMPLATE_NAME[i]);
+ }
+ return rString;
+}
+
+
+bool SfxDocumentTemplates::CopyOrMove
+(
+ sal_uInt16 nTargetRegion, // Target Region Index
+ sal_uInt16 nTargetIdx, // Target position Index
+ sal_uInt16 nSourceRegion, // Source Region Index
+ sal_uInt16 nSourceIdx, /* Index to be copied / to moved template */
+ bool bMove // Copy / Move
+)
+
+/* [Description]
+
+ Copy or move a document template
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::Move(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
+ <SfxDocumentTemplates::Copy(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
+*/
+
+{
+ /* to perform a copy or move, we need to send a transfer command to
+ the destination folder with the URL of the source as parameter.
+ ( If the destination content doesn't support the transfer command,
+ we could try a copy ( and delete ) instead. )
+ We need two transfers ( one for the real template and one for its
+ representation in the hierarchy )
+ ...
+ */
+
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( !pImp->Construct() )
+ return false;
+
+ // Don't copy or move any folders
+ if( nSourceIdx == USHRT_MAX )
+ return false ;
+
+ if ( nSourceRegion == nTargetRegion )
+ {
+ SAL_WARN( "sfx.doc", "Don't know, what to do!" );
+ return false;
+ }
+
+ RegionData_Impl *pSourceRgn = pImp->GetRegion( nSourceRegion );
+ if ( !pSourceRgn )
+ return false;
+
+ DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nSourceIdx );
+ if ( !pSource )
+ return false;
+
+ RegionData_Impl *pTargetRgn = pImp->GetRegion( nTargetRegion );
+ if ( !pTargetRgn )
+ return false;
+
+ const OUString aTitle = pSource->GetTitle();
+
+ uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
+
+ if ( xTemplates->addTemplate( pTargetRgn->GetTitle(),
+ aTitle,
+ pSource->GetTargetURL() ) )
+ {
+ const OUString aNewTargetURL = GetTemplateTargetURLFromComponent( pTargetRgn->GetTitle(), aTitle );
+ if ( aNewTargetURL.isEmpty() )
+ return false;
+
+ if ( bMove )
+ {
+ // --**-- delete the original file
+ bool bDeleted = xTemplates->removeTemplate( pSourceRgn->GetTitle(),
+ pSource->GetTitle() );
+ if ( bDeleted )
+ pSourceRgn->DeleteEntry( nSourceIdx );
+ else
+ {
+ if ( xTemplates->removeTemplate( pTargetRgn->GetTitle(), aTitle ) )
+ return false; // will trigger retry with copy instead of move
+
+ // if it is not possible to remove just created template ( must be possible! )
+ // it is better to report success here, since at least the copy has succeeded
+ // TODO/LATER: solve it more gracefully in future
+ }
+ }
+
+ // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
+ size_t temp_nTargetIdx = nTargetIdx;
+ pTargetRgn->AddEntry( aTitle, aNewTargetURL, &temp_nTargetIdx );
+
+ return true;
+ }
+
+ // --**-- if the current file is opened,
+ // it must be re-opened afterwards.
+
+ return false;
+}
+
+
+bool SfxDocumentTemplates::Move
+(
+ sal_uInt16 nTargetRegion, // Target Region Index
+ sal_uInt16 nTargetIdx, // Target position Index
+ sal_uInt16 nSourceRegion, // Source Region Index
+ sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
+)
+
+/* [Description]
+
+ Moving a template
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
+*/
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ return CopyOrMove( nTargetRegion, nTargetIdx,
+ nSourceRegion, nSourceIdx, true );
+}
+
+
+bool SfxDocumentTemplates::Copy
+(
+ sal_uInt16 nTargetRegion, // Target Region Index
+ sal_uInt16 nTargetIdx, // Target position Index
+ sal_uInt16 nSourceRegion, // Source Region Index
+ sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
+)
+
+/* [Description]
+
+ Copying a template
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ return CopyOrMove( nTargetRegion, nTargetIdx,
+ nSourceRegion, nSourceIdx, false );
+}
+
+
+bool SfxDocumentTemplates::CopyTo
+(
+ sal_uInt16 nRegion, // Region of the template to be exported
+ sal_uInt16 nIdx, // Index of the template to be exported
+ std::u16string_view rName /* File name under which the template is to
+ be created */
+) const
+
+/* [Description]
+
+ Exporting a template into the file system
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::CopyFrom(sal_uInt16,sal_uInt16,String&)>
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( ! pImp->Construct() )
+ return false;
+
+ RegionData_Impl *pSourceRgn = pImp->GetRegion( nRegion );
+ if ( !pSourceRgn )
+ return false;
+
+ DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nIdx );
+ if ( !pSource )
+ return false;
+
+ INetURLObject aTargetURL( rName );
+
+ const OUString aTitle( aTargetURL.getName( INetURLObject::LAST_SEGMENT, true,
+ INetURLObject::DecodeMechanism::WithCharset ) );
+ aTargetURL.removeSegment();
+
+ const OUString aParentURL = aTargetURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ uno::Reference< XCommandEnvironment > aCmdEnv;
+ Content aTarget;
+
+ try
+ {
+ aTarget = Content( aParentURL, aCmdEnv, comphelper::getProcessComponentContext() );
+
+ TransferInfo aTransferInfo;
+ aTransferInfo.MoveData = false;
+ aTransferInfo.SourceURL = pSource->GetTargetURL();
+ aTransferInfo.NewTitle = aTitle;
+ aTransferInfo.NameClash = NameClash::RENAME;
+
+ Any aArg( aTransferInfo );
+ aTarget.executeCommand( COMMAND_TRANSFER, aArg );
+ }
+ catch ( ContentCreationException& )
+ { return false; }
+ catch ( Exception& )
+ { return false; }
+
+ return true;
+}
+
+
+bool SfxDocumentTemplates::CopyFrom
+(
+ sal_uInt16 nRegion, /* Region in which the template is to be
+ imported */
+ sal_uInt16 nIdx, // Index of the new template in this Region
+ OUString& rName /* File name of the template to be imported
+ as an out parameter of the (automatically
+ generated from the file name) logical name
+ of the template */
+)
+
+/* [Description]
+
+ Import a template from the file system
+
+ [Return value] Success (sal_True) or serfpTargetDirectory->GetContent());
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::CopyTo(sal_uInt16,sal_uInt16,const String&)>
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( ! pImp->Construct() )
+ return false;
+
+ RegionData_Impl *pTargetRgn = pImp->GetRegion( nRegion );
+
+ if ( !pTargetRgn )
+ return false;
+
+ uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
+ if ( !xTemplates.is() )
+ return false;
+
+ OUString aTitle;
+ bool bTemplateAdded = false;
+
+ if( pImp->GetTitleFromURL( rName, aTitle ) )
+ {
+ bTemplateAdded = xTemplates->addTemplate( pTargetRgn->GetTitle(), aTitle, rName );
+ }
+ else
+ {
+ uno::Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
+
+ Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("Hidden", true) };
+
+ INetURLObject aTemplURL( rName );
+ uno::Reference< XDocumentPropertiesSupplier > xDocPropsSupplier;
+ uno::Reference< XStorable > xStorable;
+ try
+ {
+ xStorable.set(
+ xDesktop->loadComponentFromURL( aTemplURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
+ "_blank",
+ 0,
+ aArgs ),
+ UNO_QUERY );
+
+ xDocPropsSupplier.set( xStorable, UNO_QUERY );
+ }
+ catch( Exception& )
+ {
+ }
+
+ if( xStorable.is() )
+ {
+ // get Title from XDocumentPropertiesSupplier
+ if( xDocPropsSupplier.is() )
+ {
+ uno::Reference< XDocumentProperties > xDocProps
+ = xDocPropsSupplier->getDocumentProperties();
+ if (xDocProps.is() ) {
+ aTitle = xDocProps->getTitle();
+ }
+ }
+
+ if( aTitle.isEmpty() )
+ {
+ INetURLObject aURL( aTemplURL );
+ aURL.CutExtension();
+ aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
+ INetURLObject::DecodeMechanism::WithCharset );
+ }
+
+ // write a template using XStorable interface
+ bTemplateAdded = xTemplates->storeTemplate( pTargetRgn->GetTitle(), aTitle, xStorable );
+ }
+ }
+
+
+ if( bTemplateAdded )
+ {
+ INetURLObject aTemplObj( pTargetRgn->GetHierarchyURL() );
+ aTemplObj.insertName( aTitle, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ const OUString aTemplURL = aTemplObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ uno::Reference< XCommandEnvironment > aCmdEnv;
+ Content aTemplCont;
+
+ if( Content::create( aTemplURL, aCmdEnv, comphelper::getProcessComponentContext(), aTemplCont ) )
+ {
+ OUString aTemplName;
+ if( getTextProperty_Impl( aTemplCont, TARGET_URL, aTemplName ) )
+ {
+ if ( nIdx == USHRT_MAX )
+ nIdx = 0;
+ else
+ ++nIdx;
+
+ // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
+ size_t temp_nIdx = nIdx;
+ pTargetRgn->AddEntry( aTitle, aTemplName, &temp_nIdx );
+ rName = aTitle;
+ return true;
+ }
+ else
+ {
+ SAL_WARN( "sfx.doc", "CopyFrom(): The content should contain target URL!" );
+ }
+ }
+ else
+ {
+ SAL_WARN( "sfx.doc", "CopyFrom(): The content just was created!" );
+ }
+ }
+
+ return false;
+}
+
+
+bool SfxDocumentTemplates::Delete
+(
+ sal_uInt16 nRegion, // Region Index
+ sal_uInt16 nIdx /* Index of the entry or USHRT_MAX,
+ if a directory is meant. */
+)
+
+/* [Description]
+
+ Deleting an entry or a directory
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::InsertDir(const String&,sal_uInt16)>
+ <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ /* delete the template or folder in the hierarchy and in the
+ template folder by sending a delete command to the content.
+ Then remove the data from the lists
+ */
+ if ( ! pImp->Construct() )
+ return false;
+
+ RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
+
+ if ( !pRegion )
+ return false;
+
+ bool bRet;
+ uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
+
+ if ( nIdx == USHRT_MAX )
+ {
+ bRet = xTemplates->removeGroup( pRegion->GetTitle() );
+ if ( bRet )
+ pImp->DeleteRegion( nRegion );
+ }
+ else
+ {
+ DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
+
+ if ( !pEntry )
+ return false;
+
+ bRet = xTemplates->removeTemplate( pRegion->GetTitle(),
+ pEntry->GetTitle() );
+ if( bRet )
+ pRegion->DeleteEntry( nIdx );
+ }
+
+ return bRet;
+}
+
+
+bool SfxDocumentTemplates::InsertDir
+(
+ const OUString& rText, // the logical name of the new Region
+ sal_uInt16 nRegion // Region Index
+)
+
+/* [Description]
+
+ Insert an index
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
+*/
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( ! pImp->Construct() )
+ return false;
+
+ RegionData_Impl *pRegion = pImp->GetRegion( rText );
+
+ if ( pRegion )
+ return false;
+
+ uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
+
+ if ( xTemplates->addGroup( rText ) )
+ {
+ return pImp->InsertRegion( std::make_unique<RegionData_Impl>( pImp.get(), rText ), nRegion );
+ }
+
+ return false;
+}
+
+bool SfxDocumentTemplates::InsertTemplate(sal_uInt16 nSourceRegion, sal_uInt16 nIdx, const OUString &rName, const OUString &rPath)
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( ! pImp->Construct() )
+ return false;
+
+ RegionData_Impl *pRegion = pImp->GetRegion( nSourceRegion );
+
+ if ( !pRegion )
+ return false;
+
+ size_t pos = nIdx;
+ pRegion->AddEntry( rName, rPath, &pos );
+
+ return true;
+}
+
+bool SfxDocumentTemplates::SetName( const OUString& rName, sal_uInt16 nRegion, sal_uInt16 nIdx )
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( ! pImp->Construct() )
+ return false;
+
+ RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
+
+ if ( !pRegion )
+ return false;
+
+ uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
+
+ if ( nIdx == USHRT_MAX )
+ {
+ if ( pRegion->GetTitle() == rName )
+ return true;
+
+ // we have to rename a region
+ if ( xTemplates->renameGroup( pRegion->GetTitle(), rName ) )
+ {
+ pRegion->SetTitle( rName );
+ pRegion->SetHierarchyURL( "" );
+ return true;
+ }
+ }
+ else
+ {
+ DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
+
+ if ( !pEntry )
+ return false;
+
+ if ( pEntry->GetTitle() == rName )
+ return true;
+
+ if ( xTemplates->renameTemplate( pRegion->GetTitle(),
+ pEntry->GetTitle(),
+ rName ) )
+ {
+ pEntry->SetTitle( rName );
+ pEntry->SetTargetURL( "" );
+ pEntry->SetHierarchyURL( "" );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool SfxDocumentTemplates::GetFull
+(
+ std::u16string_view rRegion, // Region Name
+ std::u16string_view rName, // Template Name
+ OUString &rPath // Out: Path + File name
+)
+
+/* [Description]
+
+ Returns Path + File name of the template specified by rRegion and rName.
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::GetLogicNames(const String&,String&,String&)>
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ // We don't search for empty names!
+ if ( rName.empty() )
+ return false;
+
+ if ( ! pImp->Construct() )
+ return false;
+
+ DocTempl_EntryData_Impl* pEntry = nullptr;
+ const sal_uInt16 nCount = GetRegionCount();
+
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ RegionData_Impl *pRegion = pImp->GetRegion( i );
+
+ if( pRegion &&
+ ( rRegion.empty() || ( rRegion == pRegion->GetTitle() ) ) )
+ {
+ pEntry = pRegion->GetEntry( rName );
+
+ if ( pEntry )
+ {
+ rPath = pEntry->GetTargetURL();
+ break;
+ }
+ }
+ }
+
+ return ( pEntry != nullptr );
+}
+
+
+bool SfxDocumentTemplates::GetLogicNames
+(
+ std::u16string_view rPath, // Full Path to the template
+ OUString &rRegion, // Out: Region name
+ OUString &rName // Out: Template name
+) const
+
+/* [Description]
+
+ Returns and logical path name to the template specified by rPath
+
+ [Return value]
+
+ sal_Bool sal_True, Action could be performed
+ sal_False, Action could not be performed
+
+ [Cross-references]
+
+ <SfxDocumentTemplates::GetFull(const String&,const String&,DirEntry&)>
+*/
+
+{
+ DocTemplLocker_Impl aLocker( *pImp );
+
+ if ( ! pImp->Construct() )
+ return false;
+
+ INetURLObject aFullPath;
+
+ aFullPath.SetSmartProtocol( INetProtocol::File );
+ aFullPath.SetURL( rPath );
+ const OUString aPath( aFullPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+
+ const sal_uInt16 nCount = GetRegionCount();
+
+ for ( sal_uInt16 i=0; i<nCount; ++i )
+ {
+ RegionData_Impl *pData = pImp->GetRegion( i );
+ if ( pData )
+ {
+ const sal_uInt16 nChildCount = pData->GetCount();
+
+ for ( sal_uInt16 j=0; j<nChildCount; ++j )
+ {
+ DocTempl_EntryData_Impl *pEntry = pData->GetEntry( j );
+ if ( pEntry && pEntry->GetTargetURL() == aPath )
+ {
+ rRegion = pData->GetTitle();
+ rName = pEntry->GetTitle();
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+SfxDocumentTemplates::SfxDocumentTemplates()
+
+/* [Description]
+
+ Constructor
+*/
+{
+ if ( !gpTemplateData )
+ gpTemplateData = new SfxDocTemplate_Impl;
+
+ pImp = gpTemplateData;
+}
+
+
+SfxDocumentTemplates::~SfxDocumentTemplates()
+
+/* [Description]
+
+ Destructor
+ Release of administrative data
+*/
+
+{
+ pImp = nullptr;
+}
+
+void SfxDocumentTemplates::Update( )
+{
+ if ( ::svt::TemplateFolderCache( true ).needsUpdate() ) // update is really necessary
+ {
+ if ( pImp->Construct() )
+ pImp->Rescan();
+ }
+}
+
+void SfxDocumentTemplates::ReInitFromComponent()
+{
+ pImp->ReInitFromComponent();
+}
+
+DocTempl_EntryData_Impl::DocTempl_EntryData_Impl( RegionData_Impl* pParent,
+ const OUString& rTitle )
+{
+ mpParent = pParent;
+ maTitle = SfxDocumentTemplates::ConvertResourceString(rTitle);
+}
+
+
+int DocTempl_EntryData_Impl::Compare( std::u16string_view rTitle ) const
+{
+ return maTitle.compareTo( rTitle );
+}
+
+
+const OUString& DocTempl_EntryData_Impl::GetHierarchyURL()
+{
+ if ( maOwnURL.isEmpty() )
+ {
+ INetURLObject aTemplateObj( mpParent->GetHierarchyURL() );
+
+ aTemplateObj.insertName( GetTitle(), false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+
+ maOwnURL = aTemplateObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
+ }
+
+ return maOwnURL;
+}
+
+
+const OUString& DocTempl_EntryData_Impl::GetTargetURL()
+{
+ if ( maTargetURL.isEmpty() )
+ {
+ uno::Reference< XCommandEnvironment > aCmdEnv;
+ Content aRegion;
+
+ if ( Content::create( GetHierarchyURL(), aCmdEnv, comphelper::getProcessComponentContext(), aRegion ) )
+ {
+ getTextProperty_Impl( aRegion, TARGET_URL, maTargetURL );
+ }
+ else
+ {
+ SAL_WARN( "sfx.doc", "GetTargetURL(): Could not create hierarchy content!" );
+ }
+ }
+
+ return maTargetURL;
+}
+
+
+RegionData_Impl::RegionData_Impl( const SfxDocTemplate_Impl* pParent,
+ OUString aTitle )
+ : mpParent(pParent), maTitle(std::move(aTitle))
+{
+}
+
+
+size_t RegionData_Impl::GetEntryPos( std::u16string_view rTitle, bool& rFound ) const
+{
+ const size_t nCount = maEntries.size();
+
+ for ( size_t i=0; i<nCount; ++i )
+ {
+ auto &pData = maEntries[ i ];
+
+ if ( pData->Compare( rTitle ) == 0 )
+ {
+ rFound = true;
+ return i;
+ }
+ }
+
+ rFound = false;
+ return nCount;
+}
+
+
+void RegionData_Impl::AddEntry( const OUString& rTitle,
+ const OUString& rTargetURL,
+ const size_t *pPos )
+{
+ INetURLObject aLinkObj( GetHierarchyURL() );
+ aLinkObj.insertName( rTitle, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ const OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ bool bFound = false;
+ size_t nPos = GetEntryPos( rTitle, bFound );
+
+ if ( bFound )
+ return;
+
+ if ( pPos )
+ nPos = *pPos;
+
+ auto pEntry = std::make_unique<DocTempl_EntryData_Impl>(
+ this, rTitle );
+ pEntry->SetTargetURL( rTargetURL );
+ pEntry->SetHierarchyURL( aLinkURL );
+ if ( nPos < maEntries.size() ) {
+ auto it = maEntries.begin();
+ std::advance( it, nPos );
+ maEntries.insert( it, std::move(pEntry) );
+ }
+ else
+ maEntries.push_back( std::move(pEntry) );
+}
+
+
+size_t RegionData_Impl::GetCount() const
+{
+ return maEntries.size();
+}
+
+
+const OUString& RegionData_Impl::GetHierarchyURL()
+{
+ if ( maOwnURL.isEmpty() )
+ {
+ INetURLObject aRegionObj( mpParent->GetRootURL() );
+
+ aRegionObj.insertName( GetTitle(), false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+
+ maOwnURL = aRegionObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
+ }
+
+ return maOwnURL;
+}
+
+
+DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( std::u16string_view rName ) const
+{
+ bool bFound = false;
+ tools::Long nPos = GetEntryPos( rName, bFound );
+
+ if ( bFound )
+ return maEntries[ nPos ].get();
+ return nullptr;
+}
+
+
+DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( size_t nIndex ) const
+{
+ if ( nIndex < maEntries.size() )
+ return maEntries[ nIndex ].get();
+ return nullptr;
+}
+
+
+void RegionData_Impl::DeleteEntry( size_t nIndex )
+{
+ if ( nIndex < maEntries.size() )
+ {
+ auto it = maEntries.begin();
+ std::advance( it, nIndex );
+ maEntries.erase( it );
+ }
+}
+
+
+int RegionData_Impl::Compare( RegionData_Impl const * pCompare ) const
+{
+ return maTitle.compareTo( pCompare->maTitle );
+}
+
+
+SfxDocTemplate_Impl::SfxDocTemplate_Impl()
+: mbConstructed( false )
+, mnLockCounter( 0 )
+{
+}
+
+
+SfxDocTemplate_Impl::~SfxDocTemplate_Impl()
+{
+ gpTemplateData = nullptr;
+}
+
+
+void SfxDocTemplate_Impl::IncrementLock()
+{
+ std::unique_lock aGuard( maMutex );
+ mnLockCounter++;
+}
+
+
+void SfxDocTemplate_Impl::DecrementLock()
+{
+ std::unique_lock aGuard( maMutex );
+ if ( mnLockCounter )
+ mnLockCounter--;
+}
+
+
+RegionData_Impl* SfxDocTemplate_Impl::GetRegion( size_t nIndex ) const
+{
+ if ( nIndex < maRegions.size() )
+ return maRegions[ nIndex ].get();
+ return nullptr;
+}
+
+
+RegionData_Impl* SfxDocTemplate_Impl::GetRegion( std::u16string_view rName )
+ const
+{
+ for (auto& pData : maRegions)
+ {
+ if( pData->GetTitle() == rName )
+ return pData.get();
+ }
+ return nullptr;
+}
+
+
+void SfxDocTemplate_Impl::DeleteRegion( size_t nIndex )
+{
+ if ( nIndex < maRegions.size() )
+ {
+ auto it = maRegions.begin();
+ std::advance( it, nIndex );
+ maRegions.erase( it );
+ }
+}
+
+
+/* AddRegion adds a Region to the RegionList
+*/
+void SfxDocTemplate_Impl::AddRegion( std::unique_lock<std::mutex>& /*rGuard*/,
+ const OUString& rTitle,
+ Content& rContent )
+{
+ auto pRegion = std::make_unique<RegionData_Impl>( this, rTitle );
+ auto pRegionTmp = pRegion.get();
+
+ if ( ! InsertRegion( std::move(pRegion), size_t(-1) ) )
+ {
+ return;
+ }
+
+ // now get the content of the region
+ uno::Reference< XResultSet > xResultSet;
+
+ try
+ {
+ xResultSet = rContent.createSortedCursor( { TITLE, TARGET_URL }, { { 1, true } }, m_rCompareFactory, INCLUDE_DOCUMENTS_ONLY );
+ }
+ catch ( Exception& ) {}
+
+ if ( !xResultSet.is() )
+ return;
+
+ uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
+
+ try
+ {
+ while ( xResultSet->next() )
+ {
+ pRegionTmp->AddEntry( xRow->getString( 1 ), xRow->getString( 2 ), nullptr );
+ }
+ }
+ catch ( Exception& ) {}
+}
+
+
+void SfxDocTemplate_Impl::CreateFromHierarchy( std::unique_lock<std::mutex>& rGuard, Content &rTemplRoot )
+{
+ uno::Reference< XResultSet > xResultSet;
+ Sequence< OUString > aProps { TITLE };
+
+ try
+ {
+ xResultSet = rTemplRoot.createSortedCursor(
+ aProps,
+ { // Sequence
+ { // NumberedSortingInfo
+ /* ColumnIndex */ 1, /* Ascending */ true
+ }
+ },
+ m_rCompareFactory,
+ INCLUDE_FOLDERS_ONLY
+ );
+ }
+ catch ( Exception& ) {}
+
+ if ( !xResultSet.is() )
+ return;
+
+ uno::Reference< XCommandEnvironment > aCmdEnv;
+ uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
+ uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
+
+ try
+ {
+ while ( xResultSet->next() )
+ {
+ const OUString aId = xContentAccess->queryContentIdentifierString();
+ Content aContent( aId, aCmdEnv, comphelper::getProcessComponentContext() );
+
+ AddRegion( rGuard, xRow->getString( 1 ), aContent );
+ }
+ }
+ catch ( Exception& ) {}
+}
+
+
+bool SfxDocTemplate_Impl::Construct( )
+{
+ std::unique_lock aGuard( maMutex );
+
+ if ( mbConstructed )
+ return true;
+
+ uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+
+ uno::Reference< XPersist > xInfo( document::DocumentProperties::create(xContext), UNO_QUERY );
+ mxInfo = xInfo;
+
+ mxTemplates = frame::DocumentTemplates::create(xContext);
+
+ uno::Reference< XLocalizable > xLocalizable( mxTemplates, UNO_QUERY );
+
+ m_rCompareFactory = AnyCompareFactory::createWithLocale(xContext, xLocalizable->getLocale());
+
+ uno::Reference < XContent > aRootContent = mxTemplates->getContent();
+ uno::Reference < XCommandEnvironment > aCmdEnv;
+
+ if ( ! aRootContent.is() )
+ return false;
+
+ mbConstructed = true;
+ maRootURL = aRootContent->getIdentifier()->getContentIdentifier();
+
+ maStandardGroup = DocTemplLocaleHelper::GetStandardGroupString();
+ Content aTemplRoot( aRootContent, aCmdEnv, xContext );
+ CreateFromHierarchy( aGuard, aTemplRoot );
+
+ return true;
+}
+
+
+void SfxDocTemplate_Impl::ReInitFromComponent()
+{
+ uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
+ if ( xTemplates.is() )
+ {
+ uno::Reference < XContent > aRootContent = xTemplates->getContent();
+ uno::Reference < XCommandEnvironment > aCmdEnv;
+ Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
+ Clear();
+ std::unique_lock aGuard(maMutex);
+ CreateFromHierarchy( aGuard, aTemplRoot );
+ }
+}
+
+
+bool SfxDocTemplate_Impl::InsertRegion( std::unique_ptr<RegionData_Impl> pNew, size_t nPos )
+{
+ // return false (not inserted) if the entry already exists
+ for (auto const& pRegion : maRegions)
+ if ( pRegion->Compare( pNew.get() ) == 0 )
+ return false;
+
+ size_t newPos = nPos;
+ if ( pNew->GetTitle() == maStandardGroup )
+ newPos = 0;
+
+ if ( newPos < maRegions.size() )
+ {
+ auto it = maRegions.begin();
+ std::advance( it, newPos );
+ maRegions.emplace( it, std::move(pNew) );
+ }
+ else
+ maRegions.emplace_back( std::move(pNew) );
+
+ return true;
+}
+
+
+void SfxDocTemplate_Impl::Rescan()
+{
+ Clear();
+
+ try
+ {
+ uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
+ DBG_ASSERT( xTemplates.is(), "SfxDocTemplate_Impl::Rescan:invalid template instance!" );
+ if ( xTemplates.is() )
+ {
+ xTemplates->update();
+
+ uno::Reference < XContent > aRootContent = xTemplates->getContent();
+ uno::Reference < XCommandEnvironment > aCmdEnv;
+
+ Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
+ std::unique_lock aGuard(maMutex);
+ CreateFromHierarchy( aGuard, aTemplRoot );
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sfx.doc", "SfxDocTemplate_Impl::Rescan: caught an exception while doing the update" );
+ }
+}
+
+
+bool SfxDocTemplate_Impl::GetTitleFromURL( const OUString& rURL,
+ OUString& aTitle )
+{
+ if ( mxInfo.is() )
+ {
+ try
+ {
+ mxInfo->read( rURL );
+ }
+ catch ( Exception& )
+ {
+ // the document is not a StarOffice document
+ return false;
+ }
+
+
+ try
+ {
+ uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
+ if ( aPropSet.is() )
+ {
+ Any aValue = aPropSet->getPropertyValue( TITLE );
+ aValue >>= aTitle;
+ }
+ }
+ catch ( IOException& ) {}
+ catch ( UnknownPropertyException& ) {}
+ catch ( Exception& ) {}
+ }
+
+ if ( aTitle.isEmpty() )
+ {
+ INetURLObject aURL( rURL );
+ aURL.CutExtension();
+ aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
+ INetURLObject::DecodeMechanism::WithCharset );
+ }
+
+ return true;
+}
+
+
+void SfxDocTemplate_Impl::Clear()
+{
+ std::unique_lock aGuard( maMutex );
+ if ( mnLockCounter )
+ return;
+ maRegions.clear();
+}
+
+
+bool getTextProperty_Impl( Content& rContent,
+ const OUString& rPropName,
+ OUString& rPropValue )
+{
+ bool bGotProperty = false;
+
+ // Get the property
+ try
+ {
+ uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
+
+ // check, whether or not the property exists
+ if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
+ {
+ return false;
+ }
+
+ // now get the property
+ Any aAnyValue = rContent.getPropertyValue( rPropName );
+ aAnyValue >>= rPropValue;
+
+ if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
+ {
+ SfxURLRelocator_Impl aRelocImpl( ::comphelper::getProcessComponentContext() );
+ aRelocImpl.makeAbsoluteURL( rPropValue );
+ }
+
+ bGotProperty = true;
+ }
+ catch ( RuntimeException& ) {}
+ catch ( Exception& ) {}
+
+ return bGotProperty;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */