/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sfxurlrelocator.hxx" 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; #include #include #include #include #include "sfxtypes.hxx" #include #include "sfx2/sfxresid.hxx" #include "doc.hrc" #include #include #include #include #include using ::std::vector; using ::std::advance; //======================================================================== // #define DONT_USE_HIERARCHY #define TITLE "Title" #define IS_FOLDER "IsFolder" #define PROPERTY_TYPE "TypeDescription" #define TARGET_URL "TargetURL" #define TYPE_FOLDER "application/vnd.sun.star.hier-folder" #define TYPE_LINK "application/vnd.sun.star.hier-link" #define TYPE_FSYS_FOLDER "application/vnd.sun.staroffice.fsys-folder" #define TARGET_DIR_URL "TargetDirURL" #define COMMAND_DELETE "delete" #define COMMAND_TRANSFER "transfer" #define STANDARD_FOLDER "standard" #define SERVICENAME_TYPEDETECTION "com.sun.star.document.TypeDetection" #define TYPEDETECTION_PARAMETER "FileName" #define SERVICENAME_DOCINFO "com.sun.star.document.DocumentProperties" #define SERVICENAME_DOCTEMPLATES "com.sun.star.frame.DocumentTemplates" #define SERVICENAME_DESKTOP "com.sun.star.frame.Desktop" //======================================================================== class RegionData_Impl; namespace DocTempl { class DocTempl_EntryData_Impl { RegionData_Impl* mpParent; // the following member must be SfxObjectShellLock since it controlls that SfxObjectShell lifetime by design // and users of this class expect it to be so. SfxObjectShellLock mxObjShell; OUString maTitle; OUString maOwnURL; OUString maTargetURL; sal_Bool mbIsOwner : 1; sal_Bool mbDidConvert: 1; private: RegionData_Impl* GetParent() const { return mpParent; } 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( const OUString& rTitle ) const; SfxObjectShellRef CreateObjectShell(); sal_Bool DeleteObjectShell(); }; } using namespace ::DocTempl; // ------------------------------------------------------------------------ class RegionData_Impl { const SfxDocTemplate_Impl* mpParent; vector< DocTempl_EntryData_Impl* > maEntries; OUString maTitle; OUString maOwnURL; OUString maTargetURL; private: size_t GetEntryPos( const OUString& rTitle, sal_Bool& rFound ) const; const SfxDocTemplate_Impl* GetParent() const { return mpParent; } public: RegionData_Impl( const SfxDocTemplate_Impl* pParent, const OUString& rTitle ); ~RegionData_Impl(); void SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; } void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; } DocTempl_EntryData_Impl* GetEntry( size_t nIndex ) const; DocTempl_EntryData_Impl* GetEntry( const OUString& rName ) const; DocTempl_EntryData_Impl* GetByTargetURL( const OUString& rName ) const; const OUString& GetTitle() const { return maTitle; } const OUString& GetTargetURL(); const OUString& GetHierarchyURL(); size_t GetCount() const; void SetTitle( const OUString& rTitle ) { maTitle = rTitle; } void AddEntry( const OUString& rTitle, const OUString& rTargetURL, size_t *pPos = NULL ); void DeleteEntry( size_t nIndex ); int Compare( const OUString& rTitle ) const { return maTitle.compareTo( rTitle ); } int Compare( RegionData_Impl* pCompareWith ) const; }; typedef vector< RegionData_Impl* > RegionList_Impl; // ------------------------------------------------------------------------ class SfxDocTemplate_Impl : public SvRefBase { uno::Reference< XPersist > mxInfo; uno::Reference< XDocumentTemplates > mxTemplates; ::osl::Mutex maMutex; OUString maRootURL; OUString maStandardGroup; RegionList_Impl maRegions; sal_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(); ~SfxDocTemplate_Impl(); void IncrementLock(); void DecrementLock(); sal_Bool Construct( ); void CreateFromHierarchy( Content &rTemplRoot ); void ReInitFromComponent(); void AddRegion( const OUString& rTitle, Content& rContent ); void Rescan(); void DeleteRegion( size_t nIndex ); size_t GetRegionCount() const { return maRegions.size(); } RegionData_Impl* GetRegion( const OUString& rName ) const; RegionData_Impl* GetRegion( size_t nIndex ) const; void GetTemplates( Content& rTargetFolder, Content& rParentFolder, RegionData_Impl* pRegion ); size_t GetRegionPos( const OUString& rTitle, sal_Bool& rFound ) const; sal_Bool GetTitleFromURL( const OUString& rURL, OUString& aTitle ); sal_Bool InsertRegion( RegionData_Impl *pData, size_t nPos = size_t(-1) ); OUString GetRootURL() const { return maRootURL; } uno::Reference< XDocumentTemplates > getDocTemplates() { return mxTemplates; } }; // ------------------------------------------------------------------------ class DocTemplLocker_Impl { SfxDocTemplate_Impl& m_aDocTempl; public: DocTemplLocker_Impl( SfxDocTemplate_Impl& aDocTempl ) : m_aDocTempl( aDocTempl ) { m_aDocTempl.IncrementLock(); } ~DocTemplLocker_Impl() { m_aDocTempl.DecrementLock(); } }; // ------------------------------------------------------------------------ #ifndef SFX_DECL_DOCTEMPLATES_DEFINED #define SFX_DECL_DOCTEMPLATES_DEFINED SV_DECL_REF(SfxDocTemplate_Impl) #endif SV_IMPL_REF(SfxDocTemplate_Impl) // ------------------------------------------------------------------------ SfxDocTemplate_Impl *gpTemplateData = 0; // ----------------------------------------------------------------------- static sal_Bool getTextProperty_Impl( Content& rContent, const OUString& rPropName, OUString& rPropValue ); //======================================================================== String 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 String aName; DocTemplLocker_Impl aLocker( *pImp ); if ( pImp->Construct() ) { RegionData_Impl *pData1 = pImp->GetRegion( nIdx ); if ( pData1 ) aName = 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 aName; } //------------------------------------------------------------------------ const String& 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 */ { static String maTmpString; DocTemplLocker_Impl aLocker( *pImp ); if ( pImp->Construct() ) { RegionData_Impl *pData = pImp->GetRegion( nIdx ); if ( pData ) maTmpString = pData->GetTitle(); else maTmpString.Erase(); } else maTmpString.Erase(); return maTmpString; } //------------------------------------------------------------------------ sal_uInt16 SfxDocumentTemplates::GetRegionNo ( const String &rRegion // Region Name ) const /* [Description] Returns the Index for a logical Region Name. [Return value] sal_uInt16 Index of 'rRegion' or USHRT_MAX if unknown */ { DocTemplLocker_Impl aLocker( *pImp ); if ( !pImp->Construct() ) return USHRT_MAX; sal_Bool bFound; size_t nIndex = pImp->GetRegionPos( rRegion, bFound ); if ( bFound ) return (sal_uInt16) nIndex; else return USHRT_MAX; } //------------------------------------------------------------------------ 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; sal_uIntPtr nCount = pImp->GetRegionCount(); return (sal_uInt16) nCount; } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::IsRegionLoaded( sal_uInt16 nIdx ) const { DocTemplLocker_Impl aLocker( *pImp ); if ( !pImp->Construct() ) return sal_False; RegionData_Impl *pData = pImp->GetRegion( nIdx ); if ( pData ) return sal_True; else return sal_False; } //------------------------------------------------------------------------ sal_uInt16 SfxDocumentTemplates::GetCount ( const String& rName /* Region Name, for which the entries should be counted */ ) const /* [Description] Number of entries in Region [Return value] sal_uInt16 Number of entries */ { DocTemplLocker_Impl aLocker( *pImp ); if ( !pImp->Construct() ) return 0; RegionData_Impl *pData = pImp->GetRegion( rName ); sal_uIntPtr nCount = 0; if ( pData ) nCount = pData->GetCount(); return (sal_uInt16) nCount; } //------------------------------------------------------------------------ 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 ); sal_uIntPtr nCount = 0; if ( pData ) nCount = pData->GetCount(); return (sal_uInt16) nCount; } //------------------------------------------------------------------------ const String& 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 ); static String maTmpString; if ( pImp->Construct() ) { DocTempl_EntryData_Impl *pEntry = NULL; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); if ( pRegion ) pEntry = pRegion->GetEntry( nIdx ); if ( pEntry ) maTmpString = pEntry->GetTitle(); else maTmpString.Erase(); } else maTmpString.Erase(); return maTmpString; } //------------------------------------------------------------------------ String SfxDocumentTemplates::GetFileName ( sal_uInt16 nRegion, // Region Index, in which the entry lies sal_uInt16 nIdx // Index of the entry ) const /* [Description] Returns the file name of an entry in Region [Return value] File name of the entry */ { DocTemplLocker_Impl aLocker( *pImp ); if ( !pImp->Construct() ) return String(); DocTempl_EntryData_Impl *pEntry = NULL; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); if ( pRegion ) pEntry = pRegion->GetEntry( nIdx ); if ( pEntry ) { INetURLObject aURLObj( pEntry->GetTargetURL() ); return aURLObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); } else return String(); } //------------------------------------------------------------------------ String 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 String(); DocTempl_EntryData_Impl *pEntry = NULL; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); if ( pRegion ) pEntry = pRegion->GetEntry( nIdx ); if ( pEntry ) return pEntry->GetTargetURL(); else return String(); } //------------------------------------------------------------------------ String SfxDocumentTemplates::GetTemplatePath ( sal_uInt16 nRegion, // Region Index, in which the entry lies const String& rLongName // logical Entry Name ) 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 String(); DocTempl_EntryData_Impl *pEntry = NULL; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); if ( pRegion ) pEntry = pRegion->GetEntry( rLongName ); if ( pEntry ) return pEntry->GetTargetURL(); else if ( pRegion ) { // a new template is going to be inserted, generate a new URL // TODO/LATER: if the title is localized, use minimized URL in future // --**-- extension handling will become more complicated, because // every new document type will have it's own extension // e.g.: .stw or .stc instead of .vor INetURLObject aURLObj( pRegion->GetTargetURL() ); aURLObj.insertName( rLongName, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); OUString aExtension = aURLObj.getExtension(); if ( ! aExtension.getLength() ) aURLObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM( "vor" ) ) ); return aURLObj.GetMainURL( INetURLObject::NO_DECODE ); } else return String(); } //------------------------------------------------------------------------ String SfxDocumentTemplates::GetDefaultTemplatePath ( const String& rLongName ) /* [Description] Returns the default location for templates [Return value] String Default location for templates */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return String(); // the first region in the list should always be the standard // group // --**-- perhaps we have to create it ??? RegionData_Impl *pRegion = pImp->GetRegion( 0L ); DocTempl_EntryData_Impl *pEntry = NULL; if ( pRegion ) pEntry = pRegion->GetEntry( rLongName ); if ( pEntry ) return pEntry->GetTargetURL(); else if ( pRegion ) { // a new template is going to be inserted, generate a new URL // TODO/LATER: if the title is localized, use minimized URL in future INetURLObject aURLObj( pRegion->GetTargetURL() ); aURLObj.insertName( rLongName, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); OUString aExtension = aURLObj.getExtension(); if ( ! aExtension.getLength() ) aURLObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM( "vor" ) ) ); return aURLObj.GetMainURL( INetURLObject::NO_DECODE ); } else return String(); } //------------------------------------------------------------------------ ::rtl::OUString SfxDocumentTemplates::GetTemplateTargetURLFromComponent( const ::rtl::OUString& aGroupName, const ::rtl::OUString& aTitle ) { DocTemplLocker_Impl aLocker( *pImp ); INetURLObject aTemplateObj( pImp->GetRootURL() ); aTemplateObj.insertName( aGroupName, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); aTemplateObj.insertName( aTitle, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); ::rtl::OUString aResult; Content aTemplate; uno::Reference< XCommandEnvironment > aCmdEnv; if ( Content::create( aTemplateObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv, aTemplate ) ) { OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); getTextProperty_Impl( aTemplate, aPropName, aResult ); aResult = SvtPathOptions().SubstituteVariable( aResult ); } return aResult; } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::SaveDir ( // SfxTemplateDir& rDir // Save Directory ) /* [Description] Saves the Directory rDir [Return value] sal_Bool sal_False, Write error sal_True, Saved */ { return sal_True; } //------------------------------------------------------------------------ void SfxDocumentTemplates::NewTemplate ( sal_uInt16 nRegion, /* Region Index, in which the template should be applied */ const String& rLongName, // logical name of the new template const String& rFileName // File name of the new template ) /* [Description] Submit a new template in the administrative structures overwriting a template of the same name is prevented (! Error message) */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return; DocTempl_EntryData_Impl *pEntry; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); // do nothing if there is no region with that index if ( !pRegion ) return; pEntry = pRegion->GetEntry( rLongName ); // do nothing if there is already an entry with that name if ( pEntry ) return; uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates(); if ( xTemplates->addTemplate( pRegion->GetTitle(), rLongName, rFileName ) ) pRegion->AddEntry( rLongName, rFileName ); } //------------------------------------------------------------------------ sal_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 */ sal_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] */ { /* 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 sal_False; // Don't copy or move any folders if( nSourceIdx == USHRT_MAX ) return sal_False ; if ( nSourceRegion == nTargetRegion ) { DBG_ERRORFILE( "Don't know, what to do!" ); return sal_False; } RegionData_Impl *pSourceRgn = pImp->GetRegion( nSourceRegion ); if ( !pSourceRgn ) return sal_False; DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nSourceIdx ); if ( !pSource ) return sal_False; RegionData_Impl *pTargetRgn = pImp->GetRegion( nTargetRegion ); if ( !pTargetRgn ) return sal_False; OUString aTitle = pSource->GetTitle(); uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates(); if ( xTemplates->addTemplate( pTargetRgn->GetTitle(), aTitle, pSource->GetTargetURL() ) ) { INetURLObject aSourceObj( pSource->GetTargetURL() ); ::rtl::OUString aNewTargetURL = GetTemplateTargetURLFromComponent( pTargetRgn->GetTitle(), aTitle ); if ( !aNewTargetURL.getLength() ) return sal_False; if ( bMove ) { // --**-- delete the original file sal_Bool bDeleted = xTemplates->removeTemplate( pSourceRgn->GetTitle(), pSource->GetTitle() ); if ( bDeleted ) pSourceRgn->DeleteEntry( nSourceIdx ); else { if ( xTemplates->removeTemplate( pTargetRgn->GetTitle(), aTitle ) ) return sal_False; // will trigger tetry 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 sal_True; } // --**-- if the current file is opened, // it must be re-opened afterwards. return sal_False; } //------------------------------------------------------------------------ sal_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] */ { DocTemplLocker_Impl aLocker( *pImp ); return CopyOrMove( nTargetRegion, nTargetIdx, nSourceRegion, nSourceIdx, sal_True ); } //------------------------------------------------------------------------ sal_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] */ { DocTemplLocker_Impl aLocker( *pImp ); return CopyOrMove( nTargetRegion, nTargetIdx, nSourceRegion, nSourceIdx, sal_False ); } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::CopyTo ( sal_uInt16 nRegion, // Region of the template to be exported sal_uInt16 nIdx, // Index of the template to be exported const String& 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] */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return sal_False; RegionData_Impl *pSourceRgn = pImp->GetRegion( nRegion ); if ( !pSourceRgn ) return sal_False; DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nIdx ); if ( !pSource ) return sal_False; INetURLObject aTargetURL( rName ); OUString aTitle( aTargetURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ) ); aTargetURL.removeSegment(); OUString aParentURL = aTargetURL.GetMainURL( INetURLObject::NO_DECODE ); uno::Reference< XCommandEnvironment > aCmdEnv; Content aTarget; try { aTarget = Content( aParentURL, aCmdEnv ); TransferInfo aTransferInfo; aTransferInfo.MoveData = sal_False; aTransferInfo.SourceURL = pSource->GetTargetURL(); aTransferInfo.NewTitle = aTitle; aTransferInfo.NameClash = NameClash::OVERWRITE; Any aArg = makeAny( aTransferInfo ); OUString aCmd( RTL_CONSTASCII_USTRINGPARAM( COMMAND_TRANSFER ) ); aTarget.executeCommand( aCmd, aArg ); } catch ( ContentCreationException& ) { return sal_False; } catch ( Exception& ) { return sal_False; } return sal_True; } //------------------------------------------------------------------------ sal_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 String& 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] Sucess (sal_True) or serfpTargetDirectory->GetContent()); sal_Bool sal_True, Action could be performed sal_False, Action could not be performed [Cross-references] */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return sal_False; RegionData_Impl *pTargetRgn = pImp->GetRegion( nRegion ); if ( !pTargetRgn ) return sal_False; uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates(); if ( !xTemplates.is() ) return sal_False; OUString aTitle; sal_Bool bTemplateAdded = sal_False; if( pImp->GetTitleFromURL( rName, aTitle ) ) { bTemplateAdded = xTemplates->addTemplate( pTargetRgn->GetTitle(), aTitle, rName ); } else { OUString aService( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DESKTOP ) ); uno::Reference< XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( aService ), UNO_QUERY ); Sequence< PropertyValue > aArgs( 1 ); aArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden")); aArgs[0].Value <<= sal_True; INetURLObject aTemplURL( rName ); uno::Reference< XDocumentPropertiesSupplier > xDocPropsSupplier; uno::Reference< XStorable > xStorable; try { xStorable = uno::Reference< XStorable >( xDesktop->loadComponentFromURL( aTemplURL.GetMainURL(INetURLObject::NO_DECODE), OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, aArgs ), UNO_QUERY ); xDocPropsSupplier = uno::Reference< XDocumentPropertiesSupplier >( 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.getLength() ) { INetURLObject aURL( aTemplURL ); aURL.CutExtension(); aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); } // 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, true, INetURLObject::ENCODE_ALL ); OUString aTemplURL = aTemplObj.GetMainURL( INetURLObject::NO_DECODE ); uno::Reference< XCommandEnvironment > aCmdEnv; Content aTemplCont; if( Content::create( aTemplURL, aCmdEnv, aTemplCont ) ) { OUString aTemplName; OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); if( getTextProperty_Impl( aTemplCont, aPropName, aTemplName ) ) { if ( nIdx == USHRT_MAX ) nIdx = 0; else nIdx += 1; // 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 sal_True; } else { DBG_ASSERT( sal_False, "CopyFrom(): The content should contain target URL!" ); } } else { DBG_ASSERT( sal_False, "CopyFrom(): The content just was created!" ); } } return sal_False; } //------------------------------------------------------------------------ sal_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] */ { 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 sal_False; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); if ( !pRegion ) return sal_False; sal_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 sal_False; bRet = xTemplates->removeTemplate( pRegion->GetTitle(), pEntry->GetTitle() ); if( bRet ) pRegion->DeleteEntry( nIdx ); } return bRet; } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::InsertDir ( const String& 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] */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return sal_False; RegionData_Impl *pRegion = pImp->GetRegion( rText ); if ( pRegion ) return sal_False; uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates(); if ( xTemplates->addGroup( rText ) ) { RegionData_Impl* pNewRegion = new RegionData_Impl( pImp, rText ); if ( ! pImp->InsertRegion( pNewRegion, nRegion ) ) { delete pNewRegion; return sal_False; } return sal_True; } return sal_False; } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::SetName ( const String& rName, // Der zu setzende Name sal_uInt16 nRegion, // Region Index sal_uInt16 nIdx /* Index of the entry oder USHRT_MAX, if a directory is meant. */ ) /* [Description] Change the name of an entry or a directory [Return value] sal_Bool sal_True, Action could be performed sal_False, Action could not be performed */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return sal_False; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); DocTempl_EntryData_Impl *pEntry = NULL; if ( !pRegion ) return sal_False; uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates(); OUString aEmpty; if ( nIdx == USHRT_MAX ) { if ( pRegion->GetTitle() == OUString( rName ) ) return sal_True; // we have to rename a region if ( xTemplates->renameGroup( pRegion->GetTitle(), rName ) ) { pRegion->SetTitle( rName ); pRegion->SetTargetURL( aEmpty ); pRegion->SetHierarchyURL( aEmpty ); return sal_True; } } else { pEntry = pRegion->GetEntry( nIdx ); if ( !pEntry ) return sal_False; if ( pEntry->GetTitle() == OUString( rName ) ) return sal_True; if ( xTemplates->renameTemplate( pRegion->GetTitle(), pEntry->GetTitle(), rName ) ) { pEntry->SetTitle( rName ); pEntry->SetTargetURL( aEmpty ); pEntry->SetHierarchyURL( aEmpty ); return sal_True; } } return sal_False; } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::Rescan() /* [Description] Comparison of administrative data with the current state on disk. The logical name for which no file exists, will be removed from the administrative structure. Files for which no record exists will be included. [Return value] sal_Bool sal_True, Action could be performed sal_False, Action could not be performed [Cross-references] */ { if ( !pImp->Construct() ) return sal_False; pImp->Rescan(); return sal_True; } //------------------------------------------------------------------------ SfxObjectShellRef SfxDocumentTemplates::CreateObjectShell ( sal_uInt16 nRegion, // Region Index sal_uInt16 nIdx // Index of the entry ) /* [Description] Access to the document shell of an entry [Return value] SfxObjectShellRef Referece to the ObjectShell [Cross-references] */ { DocTemplLocker_Impl aLocker( *pImp ); if ( !pImp->Construct() ) return NULL; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); DocTempl_EntryData_Impl *pEntry = NULL; if ( pRegion ) pEntry = pRegion->GetEntry( nIdx ); if ( pEntry ) return pEntry->CreateObjectShell(); else return NULL; } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::DeleteObjectShell ( sal_uInt16 nRegion, // Region Index sal_uInt16 nIdx // Index of the entry ) /* [Description] Releasing the ObjectShell of an entry [Return value] sal_Bool sal_True, Action could be performed sal_False, Action could not be performed [Cross-references] */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return sal_True; RegionData_Impl *pRegion = pImp->GetRegion( nRegion ); DocTempl_EntryData_Impl *pEntry = NULL; if ( pRegion ) pEntry = pRegion->GetEntry( nIdx ); if ( pEntry ) return pEntry->DeleteObjectShell(); else return sal_True; } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::GetFull ( const String &rRegion, // Region Name const String &rName, // Template Name String &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] */ { DocTemplLocker_Impl aLocker( *pImp ); // We don't search for empty names! if ( ! rName.Len() ) return sal_False; if ( ! pImp->Construct() ) return sal_False; DocTempl_EntryData_Impl* pEntry = NULL; const sal_uInt16 nCount = GetRegionCount(); for ( sal_uInt16 i = 0; i < nCount; ++i ) { RegionData_Impl *pRegion = pImp->GetRegion( i ); if( pRegion && ( !rRegion.Len() || ( rRegion == String( pRegion->GetTitle() ) ) ) ) { pEntry = pRegion->GetEntry( rName ); if ( pEntry ) { rPath = pEntry->GetTargetURL(); break; } } } return ( pEntry != NULL ); } //------------------------------------------------------------------------ sal_Bool SfxDocumentTemplates::GetLogicNames ( const String &rPath, // Full Path to the template String &rRegion, // Out: Region name String &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] */ { DocTemplLocker_Impl aLocker( *pImp ); if ( ! pImp->Construct() ) return sal_False; INetURLObject aFullPath; aFullPath.SetSmartProtocol( INET_PROT_FILE ); aFullPath.SetURL( rPath ); OUString aPath( aFullPath.GetMainURL( INetURLObject::NO_DECODE ) ); RegionData_Impl *pData = NULL; DocTempl_EntryData_Impl *pEntry = NULL; sal_Bool bFound = sal_False; sal_uIntPtr nCount = GetRegionCount(); for ( sal_uIntPtr i=0; !bFound && (iGetRegion( i ); if ( pData ) { sal_uIntPtr nChildCount = pData->GetCount(); for ( sal_uIntPtr j=0; !bFound && (jGetEntry( j ); if ( pEntry->GetTargetURL() == aPath ) { bFound = sal_True; } } } } if ( bFound ) { rRegion = pData->GetTitle(); rName = pEntry->GetTitle(); } return bFound; } //------------------------------------------------------------------------ SfxDocumentTemplates::SfxDocumentTemplates() /* [Description] Constructor */ { if ( !gpTemplateData ) gpTemplateData = new SfxDocTemplate_Impl; pImp = gpTemplateData; } //------------------------------------------------------------------------- void SfxDocumentTemplates::Construct() // Delayed build-up of administrative data { } //------------------------------------------------------------------------ SfxDocumentTemplates::~SfxDocumentTemplates() /* [Description] Destructor Release of administrative data */ { pImp = NULL; } void SfxDocumentTemplates::Update( sal_Bool _bSmart ) { if ( !_bSmart // don't be smart || ::svt::TemplateFolderCache( sal_True ).needsUpdate() // update is really necessary ) { if ( pImp->Construct() ) pImp->Rescan(); } } void SfxDocumentTemplates::ReInitFromComponent() { pImp->ReInitFromComponent(); } sal_Bool SfxDocumentTemplates::HasUserContents( sal_uInt16 nRegion, sal_uInt16 nIdx ) const { DocTemplLocker_Impl aLocker( *pImp ); sal_Bool bResult = sal_False; RegionData_Impl* pRegion = pImp->GetRegion( nRegion ); if ( pRegion ) { ::rtl::OUString aRegionTargetURL = pRegion->GetTargetURL(); if ( aRegionTargetURL.getLength() ) { sal_uInt16 nLen = 0; sal_uInt16 nStartInd = 0; if( nIdx == USHRT_MAX ) { // this is a folder // check whether there is at least one editable template nLen = ( sal_uInt16 )pRegion->GetCount(); nStartInd = 0; if ( nLen == 0 ) bResult = sal_True; // the writing part of empty folder with writing URL can be removed } else { // this is a template // check whether the template is inserted by user nLen = 1; nStartInd = nIdx; } for ( sal_uInt16 nInd = nStartInd; nInd < nStartInd + nLen; nInd++ ) { DocTempl_EntryData_Impl* pEntryData = pRegion->GetEntry( nInd ); if ( pEntryData ) { ::rtl::OUString aEntryTargetURL = pEntryData->GetTargetURL(); if ( aEntryTargetURL.getLength() && ::utl::UCBContentHelper::IsSubPath( aRegionTargetURL, aEntryTargetURL ) ) { bResult = sal_True; break; } } } } } return bResult; } // ----------------------------------------------------------------------- DocTempl_EntryData_Impl::DocTempl_EntryData_Impl( RegionData_Impl* pParent, const OUString& rTitle ) { mpParent = pParent; maTitle = rTitle; mbIsOwner = sal_False; mbDidConvert= sal_False; } // ----------------------------------------------------------------------- int DocTempl_EntryData_Impl::Compare( const OUString& rTitle ) const { return maTitle.compareTo( rTitle ); } //------------------------------------------------------------------------ SfxObjectShellRef DocTempl_EntryData_Impl::CreateObjectShell() { if( ! mxObjShell.Is() ) { mbIsOwner = sal_False; sal_Bool bDum = sal_False; SfxApplication *pSfxApp = SFX_APP(); String aTargetURL = GetTargetURL(); mxObjShell = pSfxApp->DocAlreadyLoaded( aTargetURL, sal_True, bDum ); if( ! mxObjShell.Is() ) { mbIsOwner = sal_True; SfxMedium *pMed=new SfxMedium( aTargetURL,(STREAM_STD_READWRITE | STREAM_SHARE_DENYALL), sal_False, 0 ); const SfxFilter* pFilter = NULL; pMed->UseInteractionHandler(sal_True); if( pSfxApp->GetFilterMatcher().GuessFilter( *pMed, &pFilter, SFX_FILTER_TEMPLATE, 0 ) || (pFilter && !pFilter->IsOwnFormat()) || (pFilter && !pFilter->UsesStorage()) ) { SfxErrorContext aEc( ERRCTX_SFX_LOADTEMPLATE, aTargetURL ); delete pMed; mbDidConvert=sal_True; sal_uIntPtr lErr; if ( mxObjShell.Is() ) { lErr = pSfxApp->LoadTemplate( mxObjShell,aTargetURL); if( lErr != ERRCODE_NONE ) ErrorHandler::HandleError(lErr); } } else if (pFilter) { mbDidConvert=sal_False; mxObjShell = SfxObjectShell::CreateObject( pFilter->GetServiceName(), SFX_CREATE_MODE_ORGANIZER ); if ( mxObjShell.Is() ) { mxObjShell->DoInitNew(0); // TODO/LATER: make sure that we don't use binary templates! if( mxObjShell->LoadFrom( *pMed ) ) { mxObjShell->DoSaveCompleted( pMed ); } else mxObjShell.Clear(); } } } } return (SfxObjectShellRef)(SfxObjectShell*) mxObjShell; } //------------------------------------------------------------------------ sal_Bool DocTempl_EntryData_Impl::DeleteObjectShell() { sal_Bool bRet = sal_True; if ( mxObjShell.Is() ) { if( mxObjShell->IsModified() ) { // Here we also save, if the Template is being processed ... bRet = sal_False; if ( mbIsOwner ) { if( mbDidConvert ) { bRet=mxObjShell->PreDoSaveAs_Impl( GetTargetURL(), mxObjShell->GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_EXPORT | SFX_FILTER_IMPORT, SFX_FILTER_INTERNAL )->GetFilterName(), 0 ); } else { if( mxObjShell->Save() ) { uno::Reference< embed::XTransactedObject > xTransacted( mxObjShell->GetStorage(), uno::UNO_QUERY ); DBG_ASSERT( xTransacted.is(), "Storage must implement XTransactedObject!\n" ); if ( xTransacted.is() ) { try { xTransacted->commit(); bRet = sal_True; } catch( uno::Exception& ) { } } } } } } if( bRet ) { mxObjShell.Clear(); } } return bRet; } // ----------------------------------------------------------------------- const OUString& DocTempl_EntryData_Impl::GetHierarchyURL() { if ( !maOwnURL.getLength() ) { INetURLObject aTemplateObj( GetParent()->GetHierarchyURL() ); aTemplateObj.insertName( GetTitle(), false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); maOwnURL = aTemplateObj.GetMainURL( INetURLObject::NO_DECODE ); DBG_ASSERT( maOwnURL.getLength(), "GetHierarchyURL(): Could not create URL!" ); } return maOwnURL; } // ----------------------------------------------------------------------- const OUString& DocTempl_EntryData_Impl::GetTargetURL() { if ( !maTargetURL.getLength() ) { uno::Reference< XCommandEnvironment > aCmdEnv; Content aRegion; if ( Content::create( GetHierarchyURL(), aCmdEnv, aRegion ) ) { OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); getTextProperty_Impl( aRegion, aPropName, maTargetURL ); } else { DBG_ERRORFILE( "GetTargetURL(): Could not create hierarchy content!" ); } } return maTargetURL; } // ----------------------------------------------------------------------- RegionData_Impl::RegionData_Impl( const SfxDocTemplate_Impl* pParent, const OUString& rTitle ) { maTitle = rTitle; mpParent = pParent; } // ----------------------------------------------------------------------- RegionData_Impl::~RegionData_Impl() { for ( size_t i = 0, n = maEntries.size(); i < n; ++i ) delete maEntries[ i ]; maEntries.clear(); } // ----------------------------------------------------------------------- size_t RegionData_Impl::GetEntryPos( const OUString& rTitle, sal_Bool& rFound ) const { #if 1 // Don't use binary search today size_t i; size_t nCount = maEntries.size(); for ( i=0; iCompare( rTitle ) == 0 ) { rFound = sal_True; return i; } } rFound = sal_False; return i; #else // use binary search to find the correct position // in the maEntries list int nCompVal = 1; size_t nStart = 0; size_t nEnd = maEntries.size() - 1; size_t nMid; DocTempl_EntryData_Impl* pMid; rFound = sal_False; while ( nCompVal && ( nStart <= nEnd ) ) { nMid = ( nEnd - nStart ) / 2 + nStart; pMid = maEntries[ nMid ]; nCompVal = pMid->Compare( rTitle ); if ( nCompVal < 0 ) // pMid < pData nStart = nMid + 1; else nEnd = nMid - 1; } if ( nCompVal == 0 ) { rFound = sal_True; } else { if ( nCompVal < 0 ) // pMid < pData nMid++; } return nMid; #endif } // ----------------------------------------------------------------------- void RegionData_Impl::AddEntry( const OUString& rTitle, const OUString& rTargetURL, size_t *pPos ) { INetURLObject aLinkObj( GetHierarchyURL() ); aLinkObj.insertName( rTitle, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE ); DocTempl_EntryData_Impl* pEntry; sal_Bool bFound = sal_False; size_t nPos = GetEntryPos( rTitle, bFound ); if ( bFound ) { pEntry = maEntries[ nPos ]; } else { if ( pPos ) nPos = *pPos; pEntry = new DocTempl_EntryData_Impl( this, rTitle ); pEntry->SetTargetURL( rTargetURL ); pEntry->SetHierarchyURL( aLinkURL ); if ( nPos < maEntries.size() ) { vector< DocTempl_EntryData_Impl* >::iterator it = maEntries.begin(); advance( it, nPos ); maEntries.insert( it, pEntry ); } else maEntries.push_back( pEntry ); } } // ----------------------------------------------------------------------- size_t RegionData_Impl::GetCount() const { return maEntries.size(); } // ----------------------------------------------------------------------- const OUString& RegionData_Impl::GetHierarchyURL() { if ( !maOwnURL.getLength() ) { INetURLObject aRegionObj( GetParent()->GetRootURL() ); aRegionObj.insertName( GetTitle(), false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); maOwnURL = aRegionObj.GetMainURL( INetURLObject::NO_DECODE ); DBG_ASSERT( maOwnURL.getLength(), "GetHierarchyURL(): Could not create URL!" ); } return maOwnURL; } // ----------------------------------------------------------------------- const OUString& RegionData_Impl::GetTargetURL() { if ( !maTargetURL.getLength() ) { uno::Reference< XCommandEnvironment > aCmdEnv; Content aRegion; if ( Content::create( GetHierarchyURL(), aCmdEnv, aRegion ) ) { OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); getTextProperty_Impl( aRegion, aPropName, maTargetURL ); // The targeturl must be substituted: $(baseinsturl) (#i32656#) maTargetURL = SvtPathOptions().SubstituteVariable( maTargetURL ); } else { DBG_ERRORFILE( "GetTargetURL(): Could not create hierarchy content!" ); } } return maTargetURL; } // ----------------------------------------------------------------------- DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( const OUString& rName ) const { sal_Bool bFound = sal_False; long nPos = GetEntryPos( rName, bFound ); if ( bFound ) return maEntries[ nPos ]; else return NULL; } // ----------------------------------------------------------------------- DocTempl_EntryData_Impl* RegionData_Impl::GetByTargetURL( const OUString& rName ) const { for ( size_t i = 0, n = maEntries.size(); i < n; ++i ) { DocTempl_EntryData_Impl *pEntry = maEntries[ i ]; if ( pEntry->GetTargetURL() == rName ) return pEntry; } return NULL; } // ----------------------------------------------------------------------- DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( size_t nIndex ) const { if ( nIndex < maEntries.size() ) return maEntries[ nIndex ]; return NULL; } // ----------------------------------------------------------------------- void RegionData_Impl::DeleteEntry( size_t nIndex ) { if ( nIndex < maEntries.size() ) { delete maEntries[ nIndex ]; vector< DocTempl_EntryData_Impl*>::iterator it = maEntries.begin(); advance( it, nIndex ); maEntries.erase( it ); } } // ----------------------------------------------------------------------- int RegionData_Impl::Compare( RegionData_Impl* pCompare ) const { int nCompare = maTitle.compareTo( pCompare->maTitle ); return nCompare; } // ----------------------------------------------------------------------- SfxDocTemplate_Impl::SfxDocTemplate_Impl() : mbConstructed( sal_False ) , mnLockCounter( 0 ) { } // ----------------------------------------------------------------------- SfxDocTemplate_Impl::~SfxDocTemplate_Impl() { Clear(); gpTemplateData = NULL; } // ----------------------------------------------------------------------- void SfxDocTemplate_Impl::IncrementLock() { ::osl::MutexGuard aGuard( maMutex ); mnLockCounter++; } // ----------------------------------------------------------------------- void SfxDocTemplate_Impl::DecrementLock() { ::osl::MutexGuard aGuard( maMutex ); if ( mnLockCounter ) mnLockCounter--; } // ----------------------------------------------------------------------- RegionData_Impl* SfxDocTemplate_Impl::GetRegion( size_t nIndex ) const { if ( nIndex < maRegions.size() ) return maRegions[ nIndex ]; return NULL; } // ----------------------------------------------------------------------- RegionData_Impl* SfxDocTemplate_Impl::GetRegion( const OUString& rName ) const { for ( size_t i = 0, n = maRegions.size(); i < n; ++i ) { RegionData_Impl* pData = maRegions[ i ]; if( pData->GetTitle() == rName ) return pData; } return NULL; } // ----------------------------------------------------------------------- void SfxDocTemplate_Impl::DeleteRegion( size_t nIndex ) { if ( nIndex < maRegions.size() ) { delete maRegions[ nIndex ]; RegionList_Impl::iterator it = maRegions.begin(); advance( it, nIndex ); maRegions.erase( it ); } } // ----------------------------------------------------------------------- /* AddRegion adds a Region to the RegionList */ void SfxDocTemplate_Impl::AddRegion( const OUString& rTitle, Content& rContent ) { RegionData_Impl* pRegion; pRegion = new RegionData_Impl( this, rTitle ); if ( ! InsertRegion( pRegion ) ) { delete pRegion; return; } // now get the content of the region uno::Reference< XResultSet > xResultSet; Sequence< OUString > aProps(2); aProps[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( TITLE )); aProps[1] = OUString(RTL_CONSTASCII_USTRINGPARAM( TARGET_URL )); try { ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY; Sequence< NumberedSortingInfo > aSortingInfo(1); aSortingInfo.getArray()->ColumnIndex = 1; aSortingInfo.getArray()->Ascending = sal_True; xResultSet = rContent.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude ); } catch ( Exception& ) {} if ( xResultSet.is() ) { uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); uno::Reference< XRow > xRow( xResultSet, UNO_QUERY ); try { while ( xResultSet->next() ) { OUString aTitle( xRow->getString( 1 ) ); OUString aTargetDir( xRow->getString( 2 ) ); pRegion->AddEntry( aTitle, aTargetDir ); } } catch ( Exception& ) {} } } // ----------------------------------------------------------------------- void SfxDocTemplate_Impl::CreateFromHierarchy( Content &rTemplRoot ) { uno::Reference< XResultSet > xResultSet; Sequence< OUString > aProps(1); aProps[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( TITLE )); try { ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY; Sequence< NumberedSortingInfo > aSortingInfo(1); aSortingInfo.getArray()->ColumnIndex = 1; aSortingInfo.getArray()->Ascending = sal_True; xResultSet = rTemplRoot.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude ); } catch ( Exception& ) {} if ( xResultSet.is() ) { uno::Reference< XCommandEnvironment > aCmdEnv; uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); uno::Reference< XRow > xRow( xResultSet, UNO_QUERY ); try { while ( xResultSet->next() ) { OUString aTitle( xRow->getString( 1 ) ); OUString aId = xContentAccess->queryContentIdentifierString(); Content aContent = Content( aId, aCmdEnv ); AddRegion( aTitle, aContent ); } } catch ( Exception& ) {} } } // ------------------------------------------------------------------------ sal_Bool SfxDocTemplate_Impl::Construct( ) { ::osl::MutexGuard aGuard( maMutex ); if ( mbConstructed ) return sal_True; uno::Reference< XMultiServiceFactory > xFactory; xFactory = ::comphelper::getProcessServiceFactory(); OUString aService( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DOCINFO ) ); uno::Reference< XPersist > xInfo( xFactory->createInstance( aService ), UNO_QUERY ); mxInfo = xInfo; aService = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DOCTEMPLATES ) ); uno::Reference< XDocumentTemplates > xTemplates( xFactory->createInstance( aService ), UNO_QUERY ); if ( xTemplates.is() ) mxTemplates = xTemplates; else return sal_False; uno::Reference< XLocalizable > xLocalizable( xTemplates, UNO_QUERY ); Sequence< Any > aCompareArg(1); *(aCompareArg.getArray()) <<= xLocalizable->getLocale();; m_rCompareFactory = uno::Reference< XAnyCompareFactory >( xFactory->createInstanceWithArguments( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.AnyCompareFactory")), aCompareArg ), UNO_QUERY ); uno::Reference < XContent > aRootContent = xTemplates->getContent(); uno::Reference < XCommandEnvironment > aCmdEnv; if ( ! aRootContent.is() ) return sal_False; mbConstructed = sal_True; maRootURL = aRootContent->getIdentifier()->getContentIdentifier(); ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) ); if ( aLongNames.Count() ) maStandardGroup = aLongNames.GetString( 0 ); Content aTemplRoot( aRootContent, aCmdEnv ); CreateFromHierarchy( aTemplRoot ); return sal_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 ); Clear(); CreateFromHierarchy( aTemplRoot ); } } // ----------------------------------------------------------------------- void SfxDocTemplate_Impl::GetTemplates( Content& rTargetFolder, Content& /*rParentFolder*/, RegionData_Impl* pRegion ) { uno::Reference< XResultSet > xResultSet; Sequence< OUString > aProps(1); aProps[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( TITLE )); try { ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY; Sequence< NumberedSortingInfo > aSortingInfo(1); aSortingInfo.getArray()->ColumnIndex = 1; aSortingInfo.getArray()->Ascending = sal_True; xResultSet = rTargetFolder.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude ); } catch ( Exception& ) {} if ( xResultSet.is() ) { uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); uno::Reference< XRow > xRow( xResultSet, UNO_QUERY ); try { while ( xResultSet->next() ) { OUString aTitle( xRow->getString(1) ); if ( aTitle.compareToAscii( "sfx.tlx" ) == 0 ) continue; OUString aId = xContentAccess->queryContentIdentifierString(); DocTempl_EntryData_Impl* pEntry = pRegion->GetByTargetURL( aId ); if ( ! pEntry ) { OUString aFullTitle; if( !GetTitleFromURL( aId, aFullTitle ) ) { DBG_ERRORFILE( "GetTemplates(): template of alien format" ); continue; } if ( aFullTitle.getLength() ) aTitle = aFullTitle; pRegion->AddEntry( aTitle, aId ); } } } catch ( Exception& ) {} } } // ----------------------------------------------------------------------- size_t SfxDocTemplate_Impl::GetRegionPos( const OUString& rTitle, sal_Bool& rFound ) const { int nCompVal = 1; size_t nStart = 0; size_t nEnd = maRegions.size() - 1; size_t nMid = 0; RegionData_Impl* pMid; while ( nCompVal && ( nStart <= nEnd ) ) { nMid = ( nEnd - nStart ) / 2 + nStart; pMid = maRegions[ nMid ]; nCompVal = pMid->Compare( rTitle ); if ( nCompVal < 0 ) // pMid < pData nStart = nMid + 1; else nEnd = nMid - 1; } if ( nCompVal == 0 ) rFound = sal_True; else { if ( nCompVal < 0 ) // pMid < pData nMid++; rFound = sal_False; } return nMid; } // ----------------------------------------------------------------------- sal_Bool SfxDocTemplate_Impl::InsertRegion( RegionData_Impl *pNew, size_t nPos ) { ::osl::MutexGuard aGuard( maMutex ); // return false (not inserted) if the entry already exists for ( size_t i = 0, n = maRegions.size(); i < n; ++i ) if ( maRegions[ i ]->Compare( pNew ) == 0 ) return sal_False; size_t newPos = nPos; if ( pNew->GetTitle() == maStandardGroup ) newPos = 0; if ( newPos < maRegions.size() ) { RegionList_Impl::iterator it = maRegions.begin(); advance( it, newPos ); maRegions.insert( it, pNew ); } else maRegions.push_back( pNew ); return sal_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 ); CreateFromHierarchy( aTemplRoot ); } } catch( const Exception& ) { DBG_ERRORFILE( "SfxDocTemplate_Impl::Rescan: caught an exception while doing the update!" ); } } // ----------------------------------------------------------------------- sal_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 sal_False; } try { uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY ); if ( aPropSet.is() ) { OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); Any aValue = aPropSet->getPropertyValue( aPropName ); aValue >>= aTitle; } } catch ( IOException& ) {} catch ( UnknownPropertyException& ) {} catch ( Exception& ) {} } if ( ! aTitle.getLength() ) { INetURLObject aURL( rURL ); aURL.CutExtension(); aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); } return sal_True; } // ----------------------------------------------------------------------- void SfxDocTemplate_Impl::Clear() { ::osl::MutexGuard aGuard( maMutex ); if ( mnLockCounter ) return; for ( size_t i = 0, n = maRegions.size(); i < n; ++i ) delete maRegions[ i ]; maRegions.clear(); } // ----------------------------------------------------------------------- sal_Bool getTextProperty_Impl( Content& rContent, const OUString& rPropName, OUString& rPropValue ) { sal_Bool bGotProperty = sal_False; // Get the property try { uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties(); // check, wether or not the property exists if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) ) { return sal_False; } // now get the property Any aAnyValue; aAnyValue = rContent.getPropertyValue( rPropName ); aAnyValue >>= rPropValue; if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) ) { SfxURLRelocator_Impl aRelocImpl( ::comphelper::getProcessServiceFactory() ); aRelocImpl.makeAbsoluteURL( rPropValue ); } bGotProperty = sal_True; } catch ( RuntimeException& ) {} catch ( Exception& ) {} return bGotProperty; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */