1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
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/task/XInteractionHandler.hpp>
45 #include <com/sun/star/task/XInteractionHandler2.hpp>
46 #include <com/sun/star/document/XViewDataSupplier.hpp>
47 #include <com/sun/star/container/XIndexAccess.hpp>
48 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
49 #include <com/sun/star/frame/XController2.hpp>
50 #include <com/sun/star/frame/XModel2.hpp>
51 #include <com/sun/star/lang/XServiceInfo.hpp>
52 #include <com/sun/star/lang/XInitialization.hpp>
54 #include <comphelper/interaction.hxx>
55 #include <comphelper/namedvaluecollection.hxx>
56 #include <cppuhelper/exc_hlp.hxx>
57 #include <cppuhelper/implbase.hxx>
58 #include <cppuhelper/supportsservice.hxx>
59 #include <framework/interaction.hxx>
60 #include <rtl/ref.hxx>
61 #include <rtl/ustring.h>
62 #include <sot/storinfo.hxx>
63 #include <svtools/ehdl.hxx>
64 #include <svl/eitem.hxx>
65 #include <svl/itemset.hxx>
66 #include <unotools/moduleoptions.hxx>
67 #include <svtools/sfxecode.hxx>
68 #include <svl/stritem.hxx>
69 #include <toolkit/helper/vclunohelper.hxx>
70 #include <tools/diagnose_ex.h>
71 #include <ucbhelper/simpleinteractionrequest.hxx>
72 #include <osl/mutex.hxx>
74 using namespace com::sun::star
;
75 using ::com::sun::star::beans::PropertyValue
;
76 using ::com::sun::star::container::XContainerQuery
;
77 using ::com::sun::star::container::XEnumeration
;
78 using ::com::sun::star::document::XTypeDetection
;
79 using ::com::sun::star::frame::XFrame
;
80 using ::com::sun::star::frame::XLoadable
;
81 using ::com::sun::star::task::XInteractionHandler
;
82 using ::com::sun::star::task::XInteractionHandler2
;
83 using ::com::sun::star::uno::Any
;
84 using ::com::sun::star::uno::Exception
;
85 using ::com::sun::star::uno::Reference
;
86 using ::com::sun::star::uno::RuntimeException
;
87 using ::com::sun::star::uno::Sequence
;
88 using ::com::sun::star::uno::UNO_QUERY
;
89 using ::com::sun::star::uno::UNO_QUERY_THROW
;
90 using ::com::sun::star::uno::UNO_SET_THROW
;
91 using ::com::sun::star::util::XCloseable
;
92 using ::com::sun::star::document::XViewDataSupplier
;
93 using ::com::sun::star::container::XIndexAccess
;
94 using ::com::sun::star::frame::XController2
;
95 using ::com::sun::star::frame::XModel2
;
99 class SfxFrameLoader_Impl
: public ::cppu::WeakImplHelper
< css::frame::XSynchronousFrameLoader
, css::lang::XServiceInfo
>
101 css::uno::Reference
< css::uno::XComponentContext
> m_aContext
;
104 explicit SfxFrameLoader_Impl( const css::uno::Reference
< css::uno::XComponentContext
>& _rxContext
);
106 virtual OUString SAL_CALL
getImplementationName()
107 throw (css::uno::RuntimeException
, std::exception
) override
;
109 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
)
110 throw (css::uno::RuntimeException
, std::exception
) override
;
112 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames()
113 throw (css::uno::RuntimeException
, std::exception
) override
;
116 // XSynchronousFrameLoader
118 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
) override
;
119 virtual void SAL_CALL
cancel() throw( css::uno::RuntimeException
, std::exception
) override
;
122 virtual ~SfxFrameLoader_Impl() override
;
125 std::shared_ptr
<const SfxFilter
> impl_getFilterFromServiceName_nothrow(
126 const OUString
& i_rServiceName
129 static OUString
impl_askForFilter_nothrow(
130 const css::uno::Reference
< css::task::XInteractionHandler
>& i_rxHandler
,
131 const OUString
& i_rDocumentURL
134 std::shared_ptr
<const SfxFilter
> impl_detectFilterForURL(
135 const OUString
& _rURL
,
136 const ::comphelper::NamedValueCollection
& i_rDescriptor
,
137 const SfxFilterMatcher
& rMatcher
140 static bool impl_createNewDocWithSlotParam(
141 const sal_uInt16 _nSlotID
,
142 const css::uno::Reference
< css::frame::XFrame
>& i_rxFrame
,
146 void impl_determineFilter(
147 ::comphelper::NamedValueCollection
& io_rDescriptor
150 bool impl_determineTemplateDocument(
151 ::comphelper::NamedValueCollection
& io_rDescriptor
154 static sal_uInt16
impl_findSlotParam(
155 const OUString
& i_rFactoryURL
158 static SfxObjectShellRef
impl_findObjectShell(
159 const css::uno::Reference
< css::frame::XModel2
>& i_rxDocument
162 static void impl_handleCaughtError_nothrow(
163 const css::uno::Any
& i_rCaughtError
,
164 const ::comphelper::NamedValueCollection
& i_rDescriptor
167 static void impl_removeLoaderArguments(
168 ::comphelper::NamedValueCollection
& io_rDescriptor
171 static sal_Int16
impl_determineEffectiveViewId_nothrow(
172 const SfxObjectShell
& i_rDocument
,
173 const ::comphelper::NamedValueCollection
& i_rDescriptor
176 static ::comphelper::NamedValueCollection
177 impl_extractViewCreationArgs(
178 ::comphelper::NamedValueCollection
& io_rDescriptor
181 static css::uno::Reference
< css::frame::XController2
>
182 impl_createDocumentView(
183 const css::uno::Reference
< css::frame::XModel2
>& i_rModel
,
184 const css::uno::Reference
< css::frame::XFrame
>& i_rFrame
,
185 const ::comphelper::NamedValueCollection
& i_rViewFactoryArgs
,
186 const OUString
& i_rViewName
190 SfxFrameLoader_Impl::SfxFrameLoader_Impl( const Reference
< css::uno::XComponentContext
>& _rxContext
)
191 :m_aContext( _rxContext
)
195 SfxFrameLoader_Impl::~SfxFrameLoader_Impl()
200 std::shared_ptr
<const SfxFilter
> SfxFrameLoader_Impl::impl_detectFilterForURL( const OUString
& sURL
,
201 const ::comphelper::NamedValueCollection
& i_rDescriptor
, const SfxFilterMatcher
& rMatcher
) const
206 if ( sURL
.isEmpty() )
209 Reference
< XTypeDetection
> xDetect(
210 m_aContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_aContext
),
213 ::comphelper::NamedValueCollection aNewArgs
;
214 aNewArgs
.put( "URL", sURL
);
216 if ( i_rDescriptor
.has( "InteractionHandler" ) )
217 aNewArgs
.put( "InteractionHandler", i_rDescriptor
.get( "InteractionHandler" ) );
218 if ( i_rDescriptor
.has( "StatusIndicator" ) )
219 aNewArgs
.put( "StatusIndicator", i_rDescriptor
.get( "StatusIndicator" ) );
221 Sequence
< PropertyValue
> aQueryArgs( aNewArgs
.getPropertyValues() );
222 OUString sType
= xDetect
->queryTypeByDescriptor( aQueryArgs
, true );
223 if ( !sType
.isEmpty() )
225 std::shared_ptr
<const SfxFilter
> pFilter
= rMatcher
.GetFilter4EA( sType
);
227 sFilter
= pFilter
->GetName();
230 catch ( const RuntimeException
& )
234 catch( const Exception
& )
236 DBG_UNHANDLED_EXCEPTION();
240 std::shared_ptr
<const SfxFilter
> pFilter
;
241 if (!sFilter
.isEmpty())
242 pFilter
= rMatcher
.GetFilter4FilterName(sFilter
);
247 std::shared_ptr
<const SfxFilter
> SfxFrameLoader_Impl::impl_getFilterFromServiceName_nothrow( const OUString
& i_rServiceName
) const
251 ::comphelper::NamedValueCollection aQuery
;
252 aQuery
.put( "DocumentService", i_rServiceName
);
254 const Reference
< XContainerQuery
> xQuery(
255 m_aContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_aContext
),
258 const SfxFilterMatcher
& rMatcher
= SfxGetpApp()->GetFilterMatcher();
259 const SfxFilterFlags nMust
= SfxFilterFlags::IMPORT
;
260 const SfxFilterFlags nDont
= SFX_FILTER_NOTINSTALLED
;
262 Reference
< XEnumeration
> xEnum( xQuery
->createSubSetEnumerationByProperties(
263 aQuery
.getNamedValues() ), UNO_SET_THROW
);
264 while ( xEnum
->hasMoreElements() )
266 ::comphelper::NamedValueCollection
aType( xEnum
->nextElement() );
267 OUString sFilterName
= aType
.getOrDefault( "Name", OUString() );
268 if ( sFilterName
.isEmpty() )
271 std::shared_ptr
<const SfxFilter
> pFilter
= rMatcher
.GetFilter4FilterName( sFilterName
);
275 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
276 if ( ( ( nFlags
& nMust
) == nMust
)
277 && ( ( nFlags
& nDont
) == SfxFilterFlags::NONE
)
284 catch( const Exception
& )
286 DBG_UNHANDLED_EXCEPTION();
292 OUString
SfxFrameLoader_Impl::impl_askForFilter_nothrow( const Reference
< XInteractionHandler
>& i_rxHandler
,
293 const OUString
& i_rDocumentURL
)
295 ENSURE_OR_THROW( i_rxHandler
.is(), "invalid interaction handler" );
297 OUString sFilterName
;
300 ::framework::RequestFilterSelect
aRequest( i_rDocumentURL
);
301 i_rxHandler
->handle( aRequest
.GetRequest() );
302 if( !aRequest
.isAbort() )
303 sFilterName
= aRequest
.getFilter();
305 catch( const Exception
& )
307 DBG_UNHANDLED_EXCEPTION();
316 bool lcl_getDispatchResult( const SfxPoolItem
* _pResult
)
321 // default must be set to true, because some return values
322 // can't be checked, but nonetheless indicate "success"!
323 bool bSuccess
= true;
325 // On the other side some special slots return a boolean state,
326 // which can be set to FALSE.
327 const SfxBoolItem
*pItem
= dynamic_cast<const SfxBoolItem
*>( _pResult
);
329 bSuccess
= pItem
->GetValue();
336 bool SfxFrameLoader_Impl::impl_createNewDocWithSlotParam( const sal_uInt16 _nSlotID
, const Reference
< XFrame
>& i_rxFrame
,
337 const bool i_bHidden
)
339 SfxRequest
aRequest( _nSlotID
, SfxCallMode::SYNCHRON
, SfxGetpApp()->GetPool() );
340 aRequest
.AppendItem( SfxUnoFrameItem( SID_FILLFRAME
, i_rxFrame
) );
342 aRequest
.AppendItem( SfxBoolItem( SID_HIDDEN
, true ) );
343 return lcl_getDispatchResult( SfxGetpApp()->ExecuteSlot( aRequest
) );
347 void SfxFrameLoader_Impl::impl_determineFilter( ::comphelper::NamedValueCollection
& io_rDescriptor
) const
349 const OUString sURL
= io_rDescriptor
.getOrDefault( "URL", OUString() );
350 const OUString sTypeName
= io_rDescriptor
.getOrDefault( "TypeName", OUString() );
351 const OUString sFilterName
= io_rDescriptor
.getOrDefault( "FilterName", OUString() );
352 const OUString sServiceName
= io_rDescriptor
.getOrDefault( "DocumentService", OUString() );
353 const Reference
< XInteractionHandler
>
354 xInteraction
= io_rDescriptor
.getOrDefault( "InteractionHandler", Reference
< XInteractionHandler
>() );
356 const SfxFilterMatcher
& rMatcher
= SfxGetpApp()->GetFilterMatcher();
357 std::shared_ptr
<const SfxFilter
> pFilter
;
359 // get filter by its name directly ...
360 if ( !sFilterName
.isEmpty() )
361 pFilter
= rMatcher
.GetFilter4FilterName( sFilterName
);
363 // or search the preferred filter for the detected type ...
364 if ( !pFilter
&& !sTypeName
.isEmpty() )
365 pFilter
= rMatcher
.GetFilter4EA( sTypeName
);
367 // or use given document service for detection, too
368 if ( !pFilter
&& !sServiceName
.isEmpty() )
369 pFilter
= impl_getFilterFromServiceName_nothrow( sServiceName
);
371 // or use interaction to ask user for right filter.
372 if ( !pFilter
&& xInteraction
.is() && !sURL
.isEmpty() )
374 OUString sSelectedFilter
= impl_askForFilter_nothrow( xInteraction
, sURL
);
375 if ( !sSelectedFilter
.isEmpty() )
376 pFilter
= rMatcher
.GetFilter4FilterName( sSelectedFilter
);
381 io_rDescriptor
.put( "FilterName", OUString( pFilter
->GetFilterName() ) );
383 // If detected filter indicates using of an own template format
384 // add property "AsTemplate" to descriptor. But suppress this step
385 // if such property already exists.
386 if ( pFilter
->IsOwnTemplateFormat() && !io_rDescriptor
.has( "AsTemplate" ) )
387 io_rDescriptor
.put( "AsTemplate", true );
389 // The DocumentService property will finally be used to determine the document type to create, so
390 // override it with the service name as indicated by the found filter.
391 io_rDescriptor
.put( "DocumentService", OUString( pFilter
->GetServiceName() ) );
396 SfxObjectShellRef
SfxFrameLoader_Impl::impl_findObjectShell( const Reference
< XModel2
>& i_rxDocument
)
398 for ( SfxObjectShell
* pDoc
= SfxObjectShell::GetFirst( nullptr, false ); pDoc
;
399 pDoc
= SfxObjectShell::GetNext( *pDoc
, nullptr, false ) )
401 if ( i_rxDocument
== pDoc
->GetModel() )
407 SAL_WARN( "sfx.view", "SfxFrameLoader_Impl::impl_findObjectShell: model is not based on SfxObjectShell - wrong frame loader usage!" );
412 bool SfxFrameLoader_Impl::impl_determineTemplateDocument( ::comphelper::NamedValueCollection
& io_rDescriptor
) const
416 const OUString sTemplateRegioName
= io_rDescriptor
.getOrDefault( "TemplateRegionName", OUString() );
417 const OUString sTemplateName
= io_rDescriptor
.getOrDefault( "TemplateName", OUString() );
418 const OUString sServiceName
= io_rDescriptor
.getOrDefault( "DocumentService", OUString() );
419 const OUString sURL
= io_rDescriptor
.getOrDefault( "URL", OUString() );
421 // determine the full URL of the template to use, if any
422 OUString sTemplateURL
;
423 if ( !sTemplateRegioName
.isEmpty() && !sTemplateName
.isEmpty() )
425 SfxDocumentTemplates aTmpFac
;
426 aTmpFac
.GetFull( sTemplateRegioName
, sTemplateName
, sTemplateURL
);
430 if ( !sServiceName
.isEmpty() )
431 sTemplateURL
= SfxObjectFactory::GetStandardTemplate( sServiceName
);
433 sTemplateURL
= SfxObjectFactory::GetStandardTemplate( SfxObjectShell::GetServiceNameFromFactory( sURL
) );
436 if ( !sTemplateURL
.isEmpty() )
438 // detect the filter for the template. Might still be NULL (if the template is broken, or does not
439 // exist, or some such), but this is handled by our caller the same way as if no template/URL was present.
440 std::shared_ptr
<const SfxFilter
> pTemplateFilter
= impl_detectFilterForURL( sTemplateURL
, io_rDescriptor
, SfxGetpApp()->GetFilterMatcher() );
441 if ( pTemplateFilter
)
443 // load the template document, but, well, "as template"
444 io_rDescriptor
.put( "FilterName", OUString( pTemplateFilter
->GetName() ) );
445 io_rDescriptor
.put( "FileName", OUString( sTemplateURL
) );
446 io_rDescriptor
.put( "AsTemplate", true );
449 // the DocumentService property will finally be used to create the document. Thus, override any possibly
450 // present value with the document service of the template.
451 io_rDescriptor
.put( "DocumentService", OUString( pTemplateFilter
->GetServiceName() ) );
463 sal_uInt16
SfxFrameLoader_Impl::impl_findSlotParam( const OUString
& i_rFactoryURL
)
466 const sal_Int32 nParamPos
= i_rFactoryURL
.indexOf( '?' );
467 if ( nParamPos
>= 0 )
469 // currently only the "slot" parameter is supported
470 const sal_Int32 nSlotPos
= i_rFactoryURL
.indexOf( "slot=", nParamPos
);
472 sSlotParam
= i_rFactoryURL
.copy( nSlotPos
+ 5 );
475 if ( !sSlotParam
.isEmpty() )
476 return sal_uInt16( sSlotParam
.toInt32() );
482 void SfxFrameLoader_Impl::impl_handleCaughtError_nothrow( const Any
& i_rCaughtError
, const ::comphelper::NamedValueCollection
& i_rDescriptor
)
486 const Reference
< XInteractionHandler
> xInteraction
=
487 i_rDescriptor
.getOrDefault( "InteractionHandler", Reference
< XInteractionHandler
>() );
488 if ( !xInteraction
.is() )
490 ::rtl::Reference
< ::comphelper::OInteractionRequest
> pRequest( new ::comphelper::OInteractionRequest( i_rCaughtError
) );
491 ::rtl::Reference
< ::comphelper::OInteractionApprove
> pApprove( new ::comphelper::OInteractionApprove
);
492 pRequest
->addContinuation( pApprove
.get() );
494 const Reference
< XInteractionHandler2
> xHandler( xInteraction
, UNO_QUERY
);
495 #if OSL_DEBUG_LEVEL > 0
496 const bool bHandled
=
498 xHandler
.is() && xHandler
->handleInteractionRequest( pRequest
.get() );
500 #if OSL_DEBUG_LEVEL > 0
502 // the interaction handler couldn't deal with this error
503 // => report it as assertion, at least (done in the DBG_UNHANDLED_EXCEPTION below)
504 ::cppu::throwException( i_rCaughtError
);
507 catch( const Exception
& )
509 DBG_UNHANDLED_EXCEPTION();
514 void SfxFrameLoader_Impl::impl_removeLoaderArguments( ::comphelper::NamedValueCollection
& io_rDescriptor
)
516 // remove the arguments which are for the loader only, and not for a call to attachResource
517 io_rDescriptor
.remove( "StatusIndicator" );
518 io_rDescriptor
.remove( "Model" );
522 ::comphelper::NamedValueCollection
SfxFrameLoader_Impl::impl_extractViewCreationArgs( ::comphelper::NamedValueCollection
& io_rDescriptor
)
524 static const char* pKnownViewArgs
[] = {
529 ::comphelper::NamedValueCollection aViewArgs
;
530 for (const char* pKnownViewArg
: pKnownViewArgs
)
532 if ( io_rDescriptor
.has( pKnownViewArg
) )
534 aViewArgs
.put( pKnownViewArg
, io_rDescriptor
.get( pKnownViewArg
) );
535 io_rDescriptor
.remove( pKnownViewArg
);
542 sal_Int16
SfxFrameLoader_Impl::impl_determineEffectiveViewId_nothrow( const SfxObjectShell
& i_rDocument
, const ::comphelper::NamedValueCollection
& i_rDescriptor
)
544 sal_Int16 nViewId
= i_rDescriptor
.getOrDefault( "ViewId", sal_Int16( 0 ) );
547 if ( nViewId
== 0 ) do
549 Reference
< XViewDataSupplier
> xViewDataSupplier( i_rDocument
.GetModel(), UNO_QUERY
);
550 Reference
< XIndexAccess
> xViewData
;
551 if ( xViewDataSupplier
.is() )
552 xViewData
.set( xViewDataSupplier
->getViewData() );
554 if ( !xViewData
.is() || ( xViewData
->getCount() == 0 ) )
555 // no view data stored together with the model
558 // obtain the ViewID from the view data
559 Sequence
< PropertyValue
> aViewData
;
560 if ( !( xViewData
->getByIndex( 0 ) >>= aViewData
) )
563 ::comphelper::NamedValueCollection
aNamedViewData( aViewData
);
564 OUString sViewId
= aNamedViewData
.getOrDefault( "ViewId", OUString() );
565 if ( sViewId
.isEmpty() )
568 // somewhat weird convention here ... in the view data, the ViewId is a string, effectively describing
569 // a view name. In the document load descriptor, the ViewId is in fact the numeric ID.
571 SfxViewFactory
* pViewFactory
= i_rDocument
.GetFactory().GetViewFactoryByViewName( sViewId
);
573 nViewId
= sal_Int16( pViewFactory
->GetOrdinal() );
577 catch( const Exception
& )
579 DBG_UNHANDLED_EXCEPTION();
583 nViewId
= i_rDocument
.GetFactory().GetViewFactory().GetOrdinal();
588 Reference
< XController2
> SfxFrameLoader_Impl::impl_createDocumentView( const Reference
< XModel2
>& i_rModel
,
589 const Reference
< XFrame
>& i_rFrame
, const ::comphelper::NamedValueCollection
& i_rViewFactoryArgs
,
590 const OUString
& i_rViewName
)
592 // let the model create a new controller
593 const Reference
< XController2
> xController( i_rModel
->createViewController(
595 i_rViewFactoryArgs
.getPropertyValues(),
599 // introduce model/view/controller to each other
600 xController
->attachModel( i_rModel
.get() );
601 i_rModel
->connectController( xController
.get() );
602 i_rFrame
->setComponent( xController
->getComponentWindow(), xController
.get() );
603 xController
->attachFrame( i_rFrame
);
604 i_rModel
->setCurrentController( xController
.get() );
610 sal_Bool SAL_CALL
SfxFrameLoader_Impl::load( const Sequence
< PropertyValue
>& rArgs
,
611 const Reference
< XFrame
>& _rTargetFrame
)
612 throw( RuntimeException
, std::exception
)
614 ENSURE_OR_THROW( _rTargetFrame
.is(), "illegal NULL frame" );
616 SolarMutexGuard aGuard
;
618 SAL_INFO( "sfx.view", "SfxFrameLoader::load" );
620 ::comphelper::NamedValueCollection
aDescriptor( rArgs
);
622 // ensure the descriptor contains a referrer
623 if ( !aDescriptor
.has( "Referer" ) )
624 aDescriptor
.put( "Referer", OUString() );
626 // did the caller already pass a model?
627 Reference
< XModel2
> xModel
= aDescriptor
.getOrDefault( "Model", Reference
< XModel2
>() );
628 const bool bExternalModel
= xModel
.is();
630 // check for factory URLs to create a new doc, instead of loading one
631 const OUString sURL
= aDescriptor
.getOrDefault( "URL", OUString() );
632 const bool bIsFactoryURL
= sURL
.startsWith( "private:factory/" );
633 bool bInitNewModel
= bIsFactoryURL
;
634 if ( bIsFactoryURL
&& !bExternalModel
)
636 const OUString sFactory
= sURL
.copy( sizeof( "private:factory/" ) -1 );
637 // special handling for some weird factory URLs a la private:factory/swriter?slot=21053
638 const sal_uInt16 nSlotParam
= impl_findSlotParam( sFactory
);
639 if ( nSlotParam
!= 0 )
641 return impl_createNewDocWithSlotParam( nSlotParam
, _rTargetFrame
, aDescriptor
.getOrDefault( "Hidden", false ) );
644 const bool bDescribesValidTemplate
= impl_determineTemplateDocument( aDescriptor
);
645 if ( bDescribesValidTemplate
)
647 // if the media descriptor allowed us to determine a template document to create the new document
648 // from, then do not init a new document model from scratch (below), but instead load the
650 bInitNewModel
= false;
654 const OUString sServiceName
= SfxObjectShell::GetServiceNameFromFactory( sFactory
);
655 aDescriptor
.put( "DocumentService", sServiceName
);
661 aDescriptor
.put( "FileName", aDescriptor
.get( "URL" ) );
664 bool bLoadSuccess
= false;
667 // extract view relevant arguments from the loader args
668 ::comphelper::NamedValueCollection
aViewCreationArgs( impl_extractViewCreationArgs( aDescriptor
) );
670 // no model passed from outside? => create one from scratch
671 if ( !bExternalModel
)
673 bool bInternalFilter
= aDescriptor
.getOrDefault
<OUString
>("FilterProvider", OUString()).isEmpty();
675 if (bInternalFilter
&& !bInitNewModel
)
677 // Ensure that the current SfxFilter instance is loaded before
678 // going further. We don't need to do this for external
680 impl_determineFilter(aDescriptor
);
683 // create the new doc
684 const OUString sServiceName
= aDescriptor
.getOrDefault( "DocumentService", OUString() );
685 xModel
.set( m_aContext
->getServiceManager()->createInstanceWithContext(sServiceName
, m_aContext
), UNO_QUERY_THROW
);
687 // load resp. init it
688 const Reference
< XLoadable
> xLoadable( xModel
, UNO_QUERY_THROW
);
691 xLoadable
->initNew();
693 impl_removeLoaderArguments( aDescriptor
);
694 xModel
->attachResource( OUString(), aDescriptor
.getPropertyValues() );
698 xLoadable
->load( aDescriptor
.getPropertyValues() );
703 // tell the doc its (current) load args.
704 impl_removeLoaderArguments( aDescriptor
);
705 xModel
->attachResource( xModel
->getURL(), aDescriptor
.getPropertyValues() );
708 // get the SfxObjectShell (still needed at the moment)
709 // SfxObjectShellRef is used here ( instead of ...Lock ) since the model is closed below if necessary
710 // SfxObjectShellLock would be even dangerous here, since the lifetime control should be done outside in case of success
711 const SfxObjectShellRef xDoc
= impl_findObjectShell( xModel
);
712 ENSURE_OR_THROW( xDoc
.Is(), "no SfxObjectShell for the given model" );
714 // ensure the ID of the to-be-created view is in the descriptor, if possible
715 const sal_Int16 nViewId
= impl_determineEffectiveViewId_nothrow( *xDoc
, aDescriptor
);
716 const sal_Int16 nViewNo
= xDoc
->GetFactory().GetViewNo_Impl( nViewId
, 0 );
717 const OUString
sViewName( xDoc
->GetFactory().GetViewFactory( nViewNo
).GetAPIViewName() );
719 // plug the document into the frame
720 Reference
<XController2
> xController
=
721 impl_createDocumentView( xModel
, _rTargetFrame
, aViewCreationArgs
, sViewName
);
723 Reference
<lang::XInitialization
> xInit(xController
, UNO_QUERY
);
726 uno::Sequence
<uno::Any
> aArgs
; // empty for now.
727 xInit
->initialize(aArgs
);
734 const Any
aError( ::cppu::getCaughtException() );
735 if ( !aDescriptor
.getOrDefault( "Silent", false ) )
736 impl_handleCaughtError_nothrow( aError
, aDescriptor
);
739 // if loading was not successful, close the document
740 if ( !bLoadSuccess
&& !bExternalModel
)
744 const Reference
< XCloseable
> xCloseable( xModel
, UNO_QUERY_THROW
);
745 xCloseable
->close( true );
749 DBG_UNHANDLED_EXCEPTION();
756 void SfxFrameLoader_Impl::cancel() throw( RuntimeException
, std::exception
)
761 OUString SAL_CALL
SfxFrameLoader_Impl::getImplementationName() throw( RuntimeException
, std::exception
)
763 return OUString("com.sun.star.comp.office.FrameLoader");
767 sal_Bool SAL_CALL
SfxFrameLoader_Impl::supportsService( const OUString
& sServiceName
) throw( RuntimeException
, std::exception
)
769 return cppu::supportsService(this, sServiceName
);
773 Sequence
< OUString
> SAL_CALL
SfxFrameLoader_Impl::getSupportedServiceNames() throw( RuntimeException
, std::exception
)
775 Sequence
< OUString
> seqServiceNames( 2 );
776 seqServiceNames
.getArray() [0] = "com.sun.star.frame.SynchronousFrameLoader";
777 seqServiceNames
.getArray() [1] = "com.sun.star.frame.OfficeFrameLoader";
778 return seqServiceNames
;
783 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
784 com_sun_star_comp_office_FrameLoader_get_implementation(
785 css::uno::XComponentContext
*context
,
786 css::uno::Sequence
<css::uno::Any
> const &)
788 return cppu::acquire(new SfxFrameLoader_Impl(context
));
791 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */