LCOV - code coverage report
Current view: top level - sfx2/source/view - frmload.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 142 271 52.4 %
Date: 2014-11-03 Functions: 16 25 64.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <sal/macros.h>
      22             : #include "objshimp.hxx"
      23             : #include <sfx2/app.hxx>
      24             : #include <sfx2/dispatch.hxx>
      25             : #include <sfx2/docfac.hxx>
      26             : #include <sfx2/docfile.hxx>
      27             : #include <sfx2/docfilt.hxx>
      28             : #include <sfx2/doctempl.hxx>
      29             : #include <sfx2/fcontnr.hxx>
      30             : #include <sfx2/frame.hxx>
      31             : #include <sfx2/objsh.hxx>
      32             : #include <sfx2/request.hxx>
      33             : #include <sfx2/sfx.hrc>
      34             : #include <sfx2/sfxsids.hrc>
      35             : #include <sfx2/sfxuno.hxx>
      36             : #include <sfx2/viewfrm.hxx>
      37             : #include <sfx2/viewsh.hxx>
      38             : #include <sfx2/viewfac.hxx>
      39             : 
      40             : #include <com/sun/star/container/XContainerQuery.hpp>
      41             : #include <com/sun/star/document/XTypeDetection.hpp>
      42             : #include <com/sun/star/frame/XFrame.hpp>
      43             : #include <com/sun/star/frame/XLoadable.hpp>
      44             : #include <com/sun/star/frame/XModel.hpp>
      45             : #include <com/sun/star/task/XInteractionHandler.hpp>
      46             : #include <com/sun/star/task/XInteractionHandler2.hpp>
      47             : #include <com/sun/star/document/XViewDataSupplier.hpp>
      48             : #include <com/sun/star/container/XIndexAccess.hpp>
      49             : #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
      50             : #include <com/sun/star/frame/XController2.hpp>
      51             : #include <com/sun/star/frame/XModel2.hpp>
      52             : #include <com/sun/star/lang/XServiceInfo.hpp>
      53             : #include <com/sun/star/lang/XInitialization.hpp>
      54             : 
      55             : #include <comphelper/interaction.hxx>
      56             : #include <comphelper/namedvaluecollection.hxx>
      57             : #include <cppuhelper/exc_hlp.hxx>
      58             : #include <cppuhelper/implbase2.hxx>
      59             : #include <cppuhelper/supportsservice.hxx>
      60             : #include <framework/interaction.hxx>
      61             : #include <rtl/ref.hxx>
      62             : #include <rtl/ustring.h>
      63             : #include <sot/storinfo.hxx>
      64             : #include <svtools/ehdl.hxx>
      65             : #include <svl/eitem.hxx>
      66             : #include <svl/itemset.hxx>
      67             : #include <unotools/moduleoptions.hxx>
      68             : #include <svtools/sfxecode.hxx>
      69             : #include <svl/stritem.hxx>
      70             : #include <toolkit/helper/vclunohelper.hxx>
      71             : #include <tools/diagnose_ex.h>
      72             : #include <ucbhelper/simpleinteractionrequest.hxx>
      73             : #include <osl/mutex.hxx>
      74             : 
      75             : using namespace com::sun::star;
      76             : using ::com::sun::star::beans::PropertyValue;
      77             : using ::com::sun::star::container::XContainerQuery;
      78             : using ::com::sun::star::container::XEnumeration;
      79             : using ::com::sun::star::document::XTypeDetection;
      80             : using ::com::sun::star::frame::XFrame;
      81             : using ::com::sun::star::frame::XLoadable;
      82             : using ::com::sun::star::frame::XModel;
      83             : using ::com::sun::star::lang::XMultiServiceFactory;
      84             : using ::com::sun::star::task::XInteractionHandler;
      85             : using ::com::sun::star::task::XInteractionHandler2;
      86             : using ::com::sun::star::task::XInteractionRequest;
      87             : using ::com::sun::star::task::XStatusIndicator;
      88             : using ::com::sun::star::uno::Any;
      89             : using ::com::sun::star::uno::Exception;
      90             : using ::com::sun::star::uno::Reference;
      91             : using ::com::sun::star::uno::RuntimeException;
      92             : using ::com::sun::star::uno::Sequence;
      93             : using ::com::sun::star::uno::UNO_QUERY;
      94             : using ::com::sun::star::uno::UNO_QUERY_THROW;
      95             : using ::com::sun::star::uno::UNO_SET_THROW;
      96             : using ::com::sun::star::uno::makeAny;
      97             : using ::com::sun::star::util::XCloseable;
      98             : using ::com::sun::star::document::XViewDataSupplier;
      99             : using ::com::sun::star::container::XIndexAccess;
     100             : using ::com::sun::star::frame::XController2;
     101             : using ::com::sun::star::frame::XController;
     102             : using ::com::sun::star::frame::XModel2;
     103             : 
     104             : namespace {
     105             : 
     106             : class SfxFrameLoader_Impl : public ::cppu::WeakImplHelper2< css::frame::XSynchronousFrameLoader, css::lang::XServiceInfo >
     107             : {
     108             :     css::uno::Reference < css::uno::XComponentContext >  m_aContext;
     109             : 
     110             : public:
     111             :     SfxFrameLoader_Impl( const css::uno::Reference < css::uno::XComponentContext >& _rxContext );
     112             : 
     113             :     virtual OUString SAL_CALL getImplementationName()
     114             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     115             : 
     116             :     virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
     117             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     118             : 
     119             :     virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
     120             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     121             : 
     122             : 
     123             :     // XSynchronousFrameLoader
     124             : 
     125             :     virtual sal_Bool SAL_CALL load( const css::uno::Sequence< css::beans::PropertyValue >& _rArgs, const css::uno::Reference< css::frame::XFrame >& _rxFrame ) throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     126             :     virtual void SAL_CALL cancel() throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     127             : 
     128             : protected:
     129             :     virtual                 ~SfxFrameLoader_Impl();
     130             : 
     131             : private:
     132             :     const SfxFilter*    impl_getFilterFromServiceName_nothrow(
     133             :                             const OUString& i_rServiceName
     134             :                         ) const;
     135             : 
     136             :     OUString     impl_askForFilter_nothrow(
     137             :                             const css::uno::Reference< css::task::XInteractionHandler >& i_rxHandler,
     138             :                             const OUString& i_rDocumentURL
     139             :                         ) const;
     140             : 
     141             :     const SfxFilter*    impl_detectFilterForURL(
     142             :                             const OUString& _rURL,
     143             :                             const ::comphelper::NamedValueCollection& i_rDescriptor,
     144             :                             const SfxFilterMatcher& rMatcher
     145             :                         ) const;
     146             : 
     147             :     bool            impl_createNewDocWithSlotParam(
     148             :                             const sal_uInt16 _nSlotID,
     149             :                             const css::uno::Reference< css::frame::XFrame >& i_rxFrame,
     150             :                             const bool i_bHidden
     151             :                         );
     152             : 
     153             :     void                impl_determineFilter(
     154             :                                   ::comphelper::NamedValueCollection& io_rDescriptor
     155             :                         ) const;
     156             : 
     157             :     bool                impl_determineTemplateDocument(
     158             :                             ::comphelper::NamedValueCollection& io_rDescriptor
     159             :                         ) const;
     160             : 
     161             :     sal_uInt16              impl_findSlotParam(
     162             :                             const OUString& i_rFactoryURL
     163             :                         ) const;
     164             : 
     165             :     SfxObjectShellRef   impl_findObjectShell(
     166             :                             const css::uno::Reference< css::frame::XModel2 >& i_rxDocument
     167             :                         ) const;
     168             : 
     169             :     void                impl_handleCaughtError_nothrow(
     170             :                             const css::uno::Any& i_rCaughtError,
     171             :                             const ::comphelper::NamedValueCollection& i_rDescriptor
     172             :                         ) const;
     173             : 
     174             :     void                impl_removeLoaderArguments(
     175             :                             ::comphelper::NamedValueCollection& io_rDescriptor
     176             :                         );
     177             : 
     178             :     sal_Int16           impl_determineEffectiveViewId_nothrow(
     179             :                             const SfxObjectShell& i_rDocument,
     180             :                             const ::comphelper::NamedValueCollection& i_rDescriptor
     181             :                         );
     182             : 
     183             :     ::comphelper::NamedValueCollection
     184             :                         impl_extractViewCreationArgs(
     185             :                                   ::comphelper::NamedValueCollection& io_rDescriptor
     186             :                         );
     187             : 
     188             :     css::uno::Reference< css::frame::XController2 >
     189             :                         impl_createDocumentView(
     190             :                             const css::uno::Reference< css::frame::XModel2 >& i_rModel,
     191             :                             const css::uno::Reference< css::frame::XFrame >& i_rFrame,
     192             :                             const ::comphelper::NamedValueCollection& i_rViewFactoryArgs,
     193             :                             const OUString& i_rViewName
     194             :                         );
     195             : };
     196             : 
     197        5530 : SfxFrameLoader_Impl::SfxFrameLoader_Impl( const Reference< css::uno::XComponentContext >& _rxContext )
     198        5530 :     :m_aContext( _rxContext )
     199             : {
     200        5530 : }
     201             : 
     202       11060 : SfxFrameLoader_Impl::~SfxFrameLoader_Impl()
     203             : {
     204       11060 : }
     205             : 
     206             : 
     207           0 : const SfxFilter* SfxFrameLoader_Impl::impl_detectFilterForURL( const OUString& sURL,
     208             :         const ::comphelper::NamedValueCollection& i_rDescriptor, const SfxFilterMatcher& rMatcher ) const
     209             : {
     210           0 :     OUString sFilter;
     211             :     try
     212             :     {
     213           0 :         if ( sURL.isEmpty() )
     214           0 :             return 0;
     215             : 
     216             :         Reference< XTypeDetection > xDetect(
     217           0 :             m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_aContext),
     218           0 :             UNO_QUERY_THROW);
     219             : 
     220           0 :         ::comphelper::NamedValueCollection aNewArgs;
     221           0 :         aNewArgs.put( "URL", sURL );
     222             : 
     223           0 :         if ( i_rDescriptor.has( "InteractionHandler" ) )
     224           0 :             aNewArgs.put( "InteractionHandler", i_rDescriptor.get( "InteractionHandler" ) );
     225           0 :         if ( i_rDescriptor.has( "StatusIndicator" ) )
     226           0 :             aNewArgs.put( "StatusIndicator", i_rDescriptor.get( "StatusIndicator" ) );
     227             : 
     228           0 :         Sequence< PropertyValue > aQueryArgs( aNewArgs.getPropertyValues() );
     229           0 :         OUString sType = xDetect->queryTypeByDescriptor( aQueryArgs, sal_True );
     230           0 :         if ( !sType.isEmpty() )
     231             :         {
     232           0 :             const SfxFilter* pFilter = rMatcher.GetFilter4EA( sType );
     233           0 :             if ( pFilter )
     234           0 :                 sFilter = pFilter->GetName();
     235           0 :         }
     236             :     }
     237           0 :     catch ( const RuntimeException& )
     238             :     {
     239           0 :         throw;
     240             :     }
     241           0 :     catch( const Exception& )
     242             :     {
     243             :         DBG_UNHANDLED_EXCEPTION();
     244           0 :         sFilter = OUString();
     245             :     }
     246             : 
     247           0 :     const SfxFilter* pFilter = 0;
     248           0 :     if (!sFilter.isEmpty())
     249           0 :         pFilter = rMatcher.GetFilter4FilterName(sFilter);
     250           0 :     return pFilter;
     251             : }
     252             : 
     253             : 
     254           0 : const SfxFilter* SfxFrameLoader_Impl::impl_getFilterFromServiceName_nothrow( const OUString& i_rServiceName ) const
     255             : {
     256             :     try
     257             :     {
     258           0 :         ::comphelper::NamedValueCollection aQuery;
     259           0 :         aQuery.put( "DocumentService", i_rServiceName );
     260             : 
     261             :         const Reference< XContainerQuery > xQuery(
     262           0 :             m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_aContext),
     263           0 :             UNO_QUERY_THROW );
     264             : 
     265           0 :         const SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
     266           0 :         const SfxFilterFlags nMust = SFX_FILTER_IMPORT;
     267           0 :         const SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED;
     268             : 
     269           0 :         Reference < XEnumeration > xEnum( xQuery->createSubSetEnumerationByProperties(
     270           0 :             aQuery.getNamedValues() ), UNO_SET_THROW );
     271           0 :         while ( xEnum->hasMoreElements() )
     272             :         {
     273           0 :             ::comphelper::NamedValueCollection aType( xEnum->nextElement() );
     274           0 :             OUString sFilterName = aType.getOrDefault( "Name", OUString() );
     275           0 :             if ( sFilterName.isEmpty() )
     276           0 :                 continue;
     277             : 
     278           0 :             const SfxFilter* pFilter = rMatcher.GetFilter4FilterName( sFilterName );
     279           0 :             if ( !pFilter )
     280           0 :                 continue;
     281             : 
     282           0 :             SfxFilterFlags nFlags = pFilter->GetFilterFlags();
     283           0 :             if  (   ( ( nFlags & nMust ) == nMust )
     284           0 :                 &&  ( ( nFlags & nDont ) == 0 )
     285             :                 )
     286             :             {
     287           0 :                 return pFilter;
     288             :             }
     289           0 :         }
     290             :     }
     291           0 :     catch( const Exception& )
     292             :     {
     293             :         DBG_UNHANDLED_EXCEPTION();
     294             :     }
     295           0 :     return NULL;
     296             : }
     297             : 
     298             : 
     299           0 : OUString SfxFrameLoader_Impl::impl_askForFilter_nothrow( const Reference< XInteractionHandler >& i_rxHandler,
     300             :                                                                  const OUString& i_rDocumentURL ) const
     301             : {
     302           0 :     ENSURE_OR_THROW( i_rxHandler.is(), "invalid interaction handler" );
     303             : 
     304           0 :     OUString sFilterName;
     305             :     try
     306             :     {
     307           0 :         ::framework::RequestFilterSelect aRequest( i_rDocumentURL );
     308           0 :         i_rxHandler->handle( aRequest.GetRequest() );
     309           0 :         if( !aRequest.isAbort() )
     310           0 :             sFilterName = aRequest.getFilter();
     311             :     }
     312           0 :     catch( const Exception& )
     313             :     {
     314             :         DBG_UNHANDLED_EXCEPTION();
     315             :     }
     316             : 
     317           0 :     return sFilterName;
     318             : }
     319             : 
     320             : 
     321             : namespace
     322             : {
     323           0 :     bool lcl_getDispatchResult( const SfxPoolItem* _pResult )
     324             :     {
     325           0 :         if ( !_pResult )
     326           0 :             return false;
     327             : 
     328             :         // default must be set to true, because some return values
     329             :         // can't be checked, but nonetheless indicate "success"!
     330           0 :         bool bSuccess = true;
     331             : 
     332             :         // On the other side some special slots return a boolean state,
     333             :         // which can be set to FALSE.
     334           0 :         const SfxBoolItem *pItem = PTR_CAST( SfxBoolItem, _pResult );
     335           0 :         if ( pItem )
     336           0 :             bSuccess = pItem->GetValue();
     337             : 
     338           0 :         return bSuccess;
     339             :     }
     340             : }
     341             : 
     342             : 
     343           0 : bool SfxFrameLoader_Impl::impl_createNewDocWithSlotParam( const sal_uInt16 _nSlotID, const Reference< XFrame >& i_rxFrame,
     344             :                                                               const bool i_bHidden )
     345             : {
     346           0 :     SfxRequest aRequest( _nSlotID, SfxCallMode::SYNCHRON, SfxGetpApp()->GetPool() );
     347           0 :     aRequest.AppendItem( SfxUnoFrameItem( SID_FILLFRAME, i_rxFrame ) );
     348           0 :     if ( i_bHidden )
     349           0 :         aRequest.AppendItem( SfxBoolItem( SID_HIDDEN, true ) );
     350           0 :     return lcl_getDispatchResult( SfxGetpApp()->ExecuteSlot( aRequest ) );
     351             : }
     352             : 
     353             : 
     354        4034 : void SfxFrameLoader_Impl::impl_determineFilter( ::comphelper::NamedValueCollection& io_rDescriptor ) const
     355             : {
     356        4034 :     const OUString     sURL         = io_rDescriptor.getOrDefault( "URL",                OUString() );
     357        8068 :     const OUString     sTypeName    = io_rDescriptor.getOrDefault( "TypeName",           OUString() );
     358        8068 :     const OUString     sFilterName  = io_rDescriptor.getOrDefault( "FilterName",         OUString() );
     359        8068 :     const OUString     sServiceName = io_rDescriptor.getOrDefault( "DocumentService",    OUString() );
     360             :     const Reference< XInteractionHandler >
     361        8068 :                               xInteraction = io_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() );
     362             : 
     363        4034 :     const SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
     364        4034 :     const SfxFilter* pFilter = NULL;
     365             : 
     366             :     // get filter by its name directly ...
     367        4034 :     if ( !sFilterName.isEmpty() )
     368        4034 :         pFilter = rMatcher.GetFilter4FilterName( sFilterName );
     369             : 
     370             :     // or search the preferred filter for the detected type ...
     371        4034 :     if ( !pFilter && !sTypeName.isEmpty() )
     372           0 :         pFilter = rMatcher.GetFilter4EA( sTypeName );
     373             : 
     374             :     // or use given document service for detection, too
     375        4034 :     if ( !pFilter && !sServiceName.isEmpty() )
     376           0 :         pFilter = impl_getFilterFromServiceName_nothrow( sServiceName );
     377             : 
     378             :     // or use interaction to ask user for right filter.
     379        4034 :     if ( !pFilter && xInteraction.is() && !sURL.isEmpty() )
     380             :     {
     381           0 :         OUString sSelectedFilter = impl_askForFilter_nothrow( xInteraction, sURL );
     382           0 :         if ( !sSelectedFilter.isEmpty() )
     383           0 :             pFilter = rMatcher.GetFilter4FilterName( sSelectedFilter );
     384             :     }
     385             : 
     386        4034 :     if ( pFilter )
     387             :     {
     388        4034 :         io_rDescriptor.put( "FilterName", OUString( pFilter->GetFilterName() ) );
     389             : 
     390             :         // If detected filter indicates using of an own template format
     391             :         // add property "AsTemplate" to descriptor. But suppress this step
     392             :         // if such property already exists.
     393        4034 :         if ( pFilter->IsOwnTemplateFormat() && !io_rDescriptor.has( "AsTemplate" ) )
     394           0 :             io_rDescriptor.put( "AsTemplate", true );
     395             : 
     396             :         // The DocumentService property will finally be used to determine the document type to create, so
     397             :         // override it with the service name as indicated by the found filter.
     398        4034 :         io_rDescriptor.put( "DocumentService", OUString( pFilter->GetServiceName() ) );
     399        4034 :     }
     400        4034 : }
     401             : 
     402             : 
     403        5524 : SfxObjectShellRef SfxFrameLoader_Impl::impl_findObjectShell( const Reference< XModel2 >& i_rxDocument ) const
     404             : {
     405        6021 :     for ( SfxObjectShell* pDoc = SfxObjectShell::GetFirst( NULL, false ); pDoc; pDoc = SfxObjectShell::GetNext( *pDoc, NULL, false ) )
     406             :     {
     407        6021 :         if ( i_rxDocument == pDoc->GetModel() )
     408             :         {
     409        5524 :             return pDoc;
     410             :         }
     411             :     }
     412             : 
     413             :     SAL_WARN( "sfx.view", "SfxFrameLoader_Impl::impl_findObjectShell: model is not based on SfxObjectShell - wrong frame loader usage!" );
     414           0 :     return NULL;
     415             : }
     416             : 
     417             : 
     418        1442 : bool SfxFrameLoader_Impl::impl_determineTemplateDocument( ::comphelper::NamedValueCollection& io_rDescriptor ) const
     419             : {
     420             :     try
     421             :     {
     422        1442 :         const OUString sTemplateRegioName = io_rDescriptor.getOrDefault( "TemplateRegionName", OUString() );
     423        2884 :         const OUString sTemplateName      = io_rDescriptor.getOrDefault( "TemplateName",       OUString() );
     424        2884 :         const OUString sServiceName       = io_rDescriptor.getOrDefault( "DocumentService",    OUString() );
     425        2884 :         const OUString sURL               = io_rDescriptor.getOrDefault( "URL",                OUString() );
     426             : 
     427             :         // determine the full URL of the template to use, if any
     428        2884 :         OUString sTemplateURL;
     429        1442 :         if ( !sTemplateRegioName.isEmpty() && !sTemplateName.isEmpty() )
     430             :         {
     431           0 :             SfxDocumentTemplates aTmpFac;
     432           0 :             aTmpFac.GetFull( sTemplateRegioName, sTemplateName, sTemplateURL );
     433             :         }
     434             :         else
     435             :         {
     436        1442 :             if ( !sServiceName.isEmpty() )
     437           0 :                 sTemplateURL = SfxObjectFactory::GetStandardTemplate( sServiceName );
     438             :             else
     439        1442 :                 sTemplateURL = SfxObjectFactory::GetStandardTemplate( SfxObjectShell::GetServiceNameFromFactory( sURL ) );
     440             :         }
     441             : 
     442        1442 :         if ( !sTemplateURL.isEmpty() )
     443             :         {
     444             :             // detect the filter for the template. Might still be NULL (if the template is broken, or does not
     445             :             // exist, or some such), but this is handled by our caller the same way as if no template/URL was present.
     446           0 :             const SfxFilter* pTemplateFilter = impl_detectFilterForURL( sTemplateURL, io_rDescriptor, SfxGetpApp()->GetFilterMatcher() );
     447           0 :             if ( pTemplateFilter )
     448             :             {
     449             :                 // load the template document, but, well, "as template"
     450           0 :                 io_rDescriptor.put( "FilterName", OUString( pTemplateFilter->GetName() ) );
     451           0 :                 io_rDescriptor.put( "FileName", OUString( sTemplateURL ) );
     452           0 :                 io_rDescriptor.put( "AsTemplate", sal_True );
     453             : 
     454             :                 // #i21583#
     455             :                 // the DocumentService property will finally be used to create the document. Thus, override any possibly
     456             :                 // present value with the document service of the template.
     457           0 :                 io_rDescriptor.put( "DocumentService", OUString( pTemplateFilter->GetServiceName() ) );
     458           0 :                 return true;
     459             :             }
     460        1442 :         }
     461             :     }
     462           0 :     catch (...)
     463             :     {
     464             :     }
     465        1442 :     return false;
     466             : }
     467             : 
     468             : 
     469        1442 : sal_uInt16 SfxFrameLoader_Impl::impl_findSlotParam( const OUString& i_rFactoryURL ) const
     470             : {
     471        1442 :     OUString sSlotParam;
     472        1442 :     const sal_Int32 nParamPos = i_rFactoryURL.indexOf( '?' );
     473        1442 :     if ( nParamPos >= 0 )
     474             :     {
     475             :         // currently only the "slot" parameter is supported
     476           0 :         const sal_Int32 nSlotPos = i_rFactoryURL.indexOf( "slot=", nParamPos );
     477           0 :         if ( nSlotPos > 0 )
     478           0 :             sSlotParam = i_rFactoryURL.copy( nSlotPos + 5 );
     479             :     }
     480             : 
     481        1442 :     if ( !sSlotParam.isEmpty() )
     482           0 :         return sal_uInt16( sSlotParam.toInt32() );
     483             : 
     484        1442 :     return 0;
     485             : }
     486             : 
     487             : 
     488           0 : void SfxFrameLoader_Impl::impl_handleCaughtError_nothrow( const Any& i_rCaughtError, const ::comphelper::NamedValueCollection& i_rDescriptor ) const
     489             : {
     490             :     try
     491             :     {
     492             :         const Reference< XInteractionHandler > xInteraction =
     493           0 :             i_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() );
     494           0 :         if ( !xInteraction.is() )
     495           0 :             return;
     496           0 :         ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( i_rCaughtError ) );
     497           0 :         ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
     498           0 :         pRequest->addContinuation( pApprove.get() );
     499             : 
     500           0 :         const Reference< XInteractionHandler2 > xHandler( xInteraction, UNO_QUERY );
     501             :     #if OSL_DEBUG_LEVEL > 0
     502             :         const bool bHandled =
     503             :     #endif
     504           0 :         xHandler.is() && xHandler->handleInteractionRequest( pRequest.get() );
     505             : 
     506             :     #if OSL_DEBUG_LEVEL > 0
     507             :         if ( !bHandled )
     508             :             // the interaction handler couldn't deal with this error
     509             :             // => report it as assertion, at least (done in the DBG_UNHANDLED_EXCEPTION below)
     510             :             ::cppu::throwException( i_rCaughtError );
     511             :     #endif
     512             :     }
     513           0 :     catch( const Exception& )
     514             :     {
     515             :         DBG_UNHANDLED_EXCEPTION();
     516             :     }
     517             : }
     518             : 
     519             : 
     520        1490 : void SfxFrameLoader_Impl::impl_removeLoaderArguments( ::comphelper::NamedValueCollection& io_rDescriptor )
     521             : {
     522             :     // remove the arguments which are for the loader only, and not for a call to attachResource
     523        1490 :     io_rDescriptor.remove( "StatusIndicator" );
     524        1490 :     io_rDescriptor.remove( "Model" );
     525        1490 : }
     526             : 
     527             : 
     528        5524 : ::comphelper::NamedValueCollection SfxFrameLoader_Impl::impl_extractViewCreationArgs( ::comphelper::NamedValueCollection& io_rDescriptor )
     529             : {
     530             :     const sal_Char* pKnownViewArgs[] = {
     531             :         "JumpMark"
     532        5524 :     };
     533             : 
     534        5524 :     ::comphelper::NamedValueCollection aViewArgs;
     535       11048 :     for ( size_t i=0; i < sizeof( pKnownViewArgs ) / sizeof( pKnownViewArgs[0] ); ++i )
     536             :     {
     537        5524 :         if ( io_rDescriptor.has( pKnownViewArgs[i] ) )
     538             :         {
     539           0 :             aViewArgs.put( pKnownViewArgs[i], io_rDescriptor.get( pKnownViewArgs[i] ) );
     540           0 :             io_rDescriptor.remove( pKnownViewArgs[i] );
     541             :         }
     542             :     }
     543        5524 :     return aViewArgs;
     544             : }
     545             : 
     546             : 
     547        5524 : sal_Int16 SfxFrameLoader_Impl::impl_determineEffectiveViewId_nothrow( const SfxObjectShell& i_rDocument, const ::comphelper::NamedValueCollection& i_rDescriptor )
     548             : {
     549        5524 :     sal_Int16 nViewId = i_rDescriptor.getOrDefault( "ViewId", sal_Int16( 0 ) );
     550             :     try
     551             :     {
     552        5524 :         if ( nViewId == 0 ) do
     553             :         {
     554        5504 :             Reference< XViewDataSupplier > xViewDataSupplier( i_rDocument.GetModel(), UNO_QUERY );
     555        5890 :             Reference< XIndexAccess > xViewData;
     556        5504 :             if ( xViewDataSupplier.is() )
     557        5504 :                 xViewData.set( xViewDataSupplier->getViewData() );
     558             : 
     559        5504 :             if ( !xViewData.is() || ( xViewData->getCount() == 0 ) )
     560             :                 // no view data stored together with the model
     561        2108 :                 break;
     562             : 
     563             :             // obtain the ViewID from the view data
     564        3782 :             Sequence< PropertyValue > aViewData;
     565        3396 :             if ( !( xViewData->getByIndex( 0 ) >>= aViewData ) )
     566           0 :                 break;
     567             : 
     568        3782 :             ::comphelper::NamedValueCollection aNamedViewData( aViewData );
     569        3782 :             OUString sViewId = aNamedViewData.getOrDefault( "ViewId", OUString() );
     570        3396 :             if ( sViewId.isEmpty() )
     571        3010 :                 break;
     572             : 
     573             :             // somewhat weird convention here ... in the view data, the ViewId is a string, effectively describing
     574             :             // a view name. In the document load descriptor, the ViewId is in fact the numeric ID.
     575             : 
     576         386 :             SfxViewFactory* pViewFactory = i_rDocument.GetFactory().GetViewFactoryByViewName( sViewId );
     577         386 :             if ( pViewFactory )
     578         772 :                 nViewId = sal_Int16( pViewFactory->GetOrdinal() );
     579             :         }
     580             :         while ( false );
     581             :     }
     582           0 :     catch( const Exception& )
     583             :     {
     584             :         DBG_UNHANDLED_EXCEPTION();
     585             :     }
     586             : 
     587        5524 :     if ( nViewId == 0 )
     588        5118 :         nViewId = i_rDocument.GetFactory().GetViewFactory( 0 ).GetOrdinal();
     589        5524 :     return nViewId;
     590             : }
     591             : 
     592             : 
     593        5524 : Reference< XController2 > SfxFrameLoader_Impl::impl_createDocumentView( const Reference< XModel2 >& i_rModel,
     594             :         const Reference< XFrame >& i_rFrame, const ::comphelper::NamedValueCollection& i_rViewFactoryArgs,
     595             :         const OUString& i_rViewName )
     596             : {
     597             :     // let the model create a new controller
     598        5524 :     const Reference< XController2 > xController( i_rModel->createViewController(
     599             :         i_rViewName,
     600             :         i_rViewFactoryArgs.getPropertyValues(),
     601             :         i_rFrame
     602        5524 :     ), UNO_SET_THROW );
     603             : 
     604             :     // introduce model/view/controller to each other
     605        5524 :     xController->attachModel( i_rModel.get() );
     606        5524 :     i_rModel->connectController( xController.get() );
     607        5524 :     i_rFrame->setComponent( xController->getComponentWindow(), xController.get() );
     608        5524 :     xController->attachFrame( i_rFrame );
     609        5524 :     i_rModel->setCurrentController( xController.get() );
     610             : 
     611        5524 :     return xController;
     612             : }
     613             : 
     614             : 
     615        5524 : sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const Sequence< PropertyValue >& rArgs,
     616             :                                              const Reference< XFrame >& _rTargetFrame )
     617             :     throw( RuntimeException, std::exception )
     618             : {
     619        5524 :     ENSURE_OR_THROW( _rTargetFrame.is(), "illegal NULL frame" );
     620             : 
     621        5524 :     SolarMutexGuard aGuard;
     622             : 
     623             :     SAL_INFO( "sfx.view", "SfxFrameLoader::load" );
     624             : 
     625       11048 :     ::comphelper::NamedValueCollection aDescriptor( rArgs );
     626             : 
     627             :     // ensure the descriptor contains a referrer
     628        5524 :     if ( !aDescriptor.has( "Referer" ) )
     629        5506 :         aDescriptor.put( "Referer", OUString() );
     630             : 
     631             :     // did the caller already pass a model?
     632       11048 :     Reference< XModel2 > xModel = aDescriptor.getOrDefault( "Model", Reference< XModel2 >() );
     633        5524 :     const bool bExternalModel = xModel.is();
     634             : 
     635             :     // check for factory URLs to create a new doc, instead of loading one
     636       11048 :     const OUString sURL = aDescriptor.getOrDefault( "URL", OUString() );
     637        5524 :     const bool bIsFactoryURL = sURL.startsWith( "private:factory/" );
     638        5524 :     bool bInitNewModel = bIsFactoryURL;
     639        5524 :     if ( bIsFactoryURL && !bExternalModel )
     640             :     {
     641        1442 :         const OUString sFactory = sURL.copy( sizeof( "private:factory/" ) -1 );
     642             :         // special handling for some weird factory URLs a la private:factory/swriter?slot=21053
     643        1442 :         const sal_uInt16 nSlotParam = impl_findSlotParam( sFactory );
     644        1442 :         if ( nSlotParam != 0 )
     645             :         {
     646           0 :             return impl_createNewDocWithSlotParam( nSlotParam, _rTargetFrame, aDescriptor.getOrDefault( "Hidden", false ) );
     647             :         }
     648             : 
     649        1442 :         const bool bDescribesValidTemplate = impl_determineTemplateDocument( aDescriptor );
     650        1442 :         if ( bDescribesValidTemplate )
     651             :         {
     652             :             // if the media descriptor allowed us to determine a template document to create the new document
     653             :             // from, then do not init a new document model from scratch (below), but instead load the
     654             :             // template document
     655           0 :             bInitNewModel = false;
     656             :         }
     657             :         else
     658             :         {
     659        1442 :             const OUString sServiceName = SfxObjectShell::GetServiceNameFromFactory( sFactory );
     660        1442 :             aDescriptor.put( "DocumentService", sServiceName );
     661        1442 :         }
     662             :     }
     663             :     else
     664             :     {
     665             :         // compatibility
     666        4082 :         aDescriptor.put( "FileName", aDescriptor.get( "URL" ) );
     667             :     }
     668             : 
     669        5524 :     bool bLoadSuccess = false;
     670             :     try
     671             :     {
     672             :         // extract view releant arguments from the loader args
     673        5524 :         ::comphelper::NamedValueCollection aViewCreationArgs( impl_extractViewCreationArgs( aDescriptor ) );
     674             : 
     675             :         // no model passed from outside? => create one from scratch
     676        5524 :         if ( !xModel.is() )
     677             :         {
     678        5476 :             bool bInternalFilter = aDescriptor.getOrDefault<OUString>("FilterProvider", OUString()).isEmpty();
     679             : 
     680        5476 :             if (bInternalFilter && !bInitNewModel)
     681             :             {
     682             :                 // Ensure that the current SfxFilter instance is loaded before
     683             :                 // going further.  We don't need to do this for external
     684             :                 // filter providers.
     685        4034 :                 impl_determineFilter(aDescriptor);
     686             :             }
     687             : 
     688             :             // create the new doc
     689        5476 :             const OUString sServiceName = aDescriptor.getOrDefault( "DocumentService", OUString() );
     690        5476 :             xModel.set( m_aContext->getServiceManager()->createInstanceWithContext(sServiceName, m_aContext), UNO_QUERY_THROW );
     691             : 
     692             :             // load resp. init it
     693       10952 :             const Reference< XLoadable > xLoadable( xModel, UNO_QUERY_THROW );
     694        5476 :             if ( bInitNewModel )
     695             :             {
     696        1442 :                 xLoadable->initNew();
     697             : 
     698        1442 :                 impl_removeLoaderArguments( aDescriptor );
     699        1442 :                 xModel->attachResource( OUString(), aDescriptor.getPropertyValues() );
     700             :             }
     701             :             else
     702             :             {
     703        4034 :                 xLoadable->load( aDescriptor.getPropertyValues() );
     704        5476 :             }
     705             :         }
     706             :         else
     707             :         {
     708             :             // tell the doc its (current) load args.
     709          48 :             impl_removeLoaderArguments( aDescriptor );
     710          48 :             xModel->attachResource( xModel->getURL(), aDescriptor.getPropertyValues() );
     711             :         }
     712             : 
     713             :         // get the SfxObjectShell (still needed at the moment)
     714             :         // SfxObjectShellRef is used here ( instead of ...Lock ) since the model is closed below if necessary
     715             :         // SfxObjectShellLock would be even dangerous here, since the lifetime control should be done outside in case of success
     716       11048 :         const SfxObjectShellRef xDoc = impl_findObjectShell( xModel );
     717        5524 :         ENSURE_OR_THROW( xDoc.Is(), "no SfxObjectShell for the given model" );
     718             : 
     719             :         // ensure the ID of the to-be-created view is in the descriptor, if possible
     720        5524 :         const sal_Int16 nViewId = impl_determineEffectiveViewId_nothrow( *xDoc, aDescriptor );
     721        5524 :         const sal_Int16 nViewNo = xDoc->GetFactory().GetViewNo_Impl( nViewId, 0 );
     722       11048 :         const OUString sViewName( xDoc->GetFactory().GetViewFactory( nViewNo ).GetAPIViewName() );
     723             : 
     724             :         // plug the document into the frame
     725             :         Reference<XController2> xController =
     726       11048 :             impl_createDocumentView( xModel, _rTargetFrame, aViewCreationArgs, sViewName );
     727             : 
     728       11048 :         Reference<lang::XInitialization> xInit(xController, UNO_QUERY);
     729        5524 :         if (xInit.is())
     730             :         {
     731        5524 :             uno::Sequence<uno::Any> aArgs; // empty for now.
     732        5524 :             xInit->initialize(aArgs);
     733             :         }
     734             : 
     735       11048 :         bLoadSuccess = true;
     736             :     }
     737           0 :     catch ( Exception& )
     738             :     {
     739           0 :         const Any aError( ::cppu::getCaughtException() );
     740           0 :         if ( !aDescriptor.getOrDefault( "Silent", sal_False ) )
     741           0 :             impl_handleCaughtError_nothrow( aError, aDescriptor );
     742             :     }
     743             : 
     744             :     // if loading was not successful, close the document
     745        5524 :     if ( !bLoadSuccess && !bExternalModel )
     746             :     {
     747             :         try
     748             :         {
     749           0 :             const Reference< XCloseable > xCloseable( xModel, UNO_QUERY_THROW );
     750           0 :             xCloseable->close( sal_True );
     751             :         }
     752           0 :         catch ( Exception& )
     753             :         {
     754             :             DBG_UNHANDLED_EXCEPTION();
     755             :         }
     756             :     }
     757             : 
     758       11048 :     return bLoadSuccess;
     759             : }
     760             : 
     761           0 : void SfxFrameLoader_Impl::cancel() throw( RuntimeException, std::exception )
     762             : {
     763           0 : }
     764             : 
     765             : /* XServiceInfo */
     766           2 : OUString SAL_CALL SfxFrameLoader_Impl::getImplementationName() throw( RuntimeException, std::exception )
     767             : {
     768           2 :     return OUString("com.sun.star.comp.office.FrameLoader");
     769             : }
     770             :                                                                                                                                 \
     771             : /* XServiceInfo */
     772           0 : sal_Bool SAL_CALL SfxFrameLoader_Impl::supportsService( const OUString& sServiceName ) throw( RuntimeException, std::exception )
     773             : {
     774           0 :     return cppu::supportsService(this, sServiceName);
     775             : }
     776             : 
     777             : /* XServiceInfo */
     778           0 : Sequence< OUString > SAL_CALL SfxFrameLoader_Impl::getSupportedServiceNames() throw( RuntimeException, std::exception )
     779             : {
     780           0 :     Sequence< OUString > seqServiceNames( 2 );
     781           0 :     seqServiceNames.getArray() [0] = "com.sun.star.frame.SynchronousFrameLoader";
     782           0 :     seqServiceNames.getArray() [1] = "com.sun.star.frame.OfficeFrameLoader";
     783           0 :     return seqServiceNames ;
     784             : }
     785             : 
     786             : }
     787             : 
     788             : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
     789        5530 : com_sun_star_comp_office_FrameLoader_get_implementation(
     790             :     css::uno::XComponentContext *context,
     791             :     css::uno::Sequence<css::uno::Any> const &)
     792             : {
     793        5530 :     return cppu::acquire(new SfxFrameLoader_Impl(context));
     794         951 : }
     795             : 
     796             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10