Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / view / frmload.cxx
blobbb9c3218da210221412f6d9f36adefb5c057565e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <sfx2/app.hxx>
22 #include <sfx2/bindings.hxx>
23 #include <sfx2/docfac.hxx>
24 #include <sfx2/docfilt.hxx>
25 #include <sfx2/doctempl.hxx>
26 #include <sfx2/fcontnr.hxx>
27 #include <sfx2/frame.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <sfx2/request.hxx>
30 #include <sfx2/sfxsids.hrc>
31 #include <sfx2/viewfac.hxx>
33 #include <com/sun/star/container/XContainerQuery.hpp>
34 #include <com/sun/star/document/XTypeDetection.hpp>
35 #include <com/sun/star/frame/XFrame.hpp>
36 #include <com/sun/star/frame/XLoadable.hpp>
37 #include <com/sun/star/task/XInteractionHandler.hpp>
38 #include <com/sun/star/task/XInteractionHandler2.hpp>
39 #include <com/sun/star/document/XViewDataSupplier.hpp>
40 #include <com/sun/star/container/XIndexAccess.hpp>
41 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
42 #include <com/sun/star/frame/XController2.hpp>
43 #include <com/sun/star/frame/XModel2.hpp>
44 #include <com/sun/star/lang/XServiceInfo.hpp>
45 #include <com/sun/star/lang/XInitialization.hpp>
46 #include <com/sun/star/uno/XComponentContext.hpp>
47 #include <com/sun/star/util/XCloseable.hpp>
49 #include <comphelper/interaction.hxx>
50 #include <comphelper/namedvaluecollection.hxx>
51 #include <cppuhelper/exc_hlp.hxx>
52 #include <cppuhelper/implbase.hxx>
53 #include <cppuhelper/supportsservice.hxx>
54 #include <framework/interaction.hxx>
55 #include <rtl/ref.hxx>
56 #include <sal/log.hxx>
57 #include <svl/eitem.hxx>
58 #include <unotools/moduleoptions.hxx>
59 #include <tools/diagnose_ex.h>
60 #include <vcl/svapp.hxx>
62 using namespace com::sun::star;
63 using ::com::sun::star::beans::PropertyValue;
64 using ::com::sun::star::container::XContainerQuery;
65 using ::com::sun::star::container::XEnumeration;
66 using ::com::sun::star::document::XTypeDetection;
67 using ::com::sun::star::frame::XFrame;
68 using ::com::sun::star::frame::XLoadable;
69 using ::com::sun::star::task::XInteractionHandler;
70 using ::com::sun::star::task::XInteractionHandler2;
71 using ::com::sun::star::uno::Any;
72 using ::com::sun::star::uno::Exception;
73 using ::com::sun::star::uno::Reference;
74 using ::com::sun::star::uno::RuntimeException;
75 using ::com::sun::star::uno::Sequence;
76 using ::com::sun::star::uno::UNO_QUERY;
77 using ::com::sun::star::uno::UNO_QUERY_THROW;
78 using ::com::sun::star::uno::UNO_SET_THROW;
79 using ::com::sun::star::util::XCloseable;
80 using ::com::sun::star::document::XViewDataSupplier;
81 using ::com::sun::star::container::XIndexAccess;
82 using ::com::sun::star::frame::XController2;
83 using ::com::sun::star::frame::XModel2;
85 namespace {
87 class SfxFrameLoader_Impl : public ::cppu::WeakImplHelper< css::frame::XSynchronousFrameLoader, css::lang::XServiceInfo >
89 css::uno::Reference < css::uno::XComponentContext > m_aContext;
91 public:
92 explicit SfxFrameLoader_Impl( const css::uno::Reference < css::uno::XComponentContext >& _rxContext );
94 virtual OUString SAL_CALL getImplementationName() override;
96 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
98 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
101 // XSynchronousFrameLoader
103 virtual sal_Bool SAL_CALL load( const css::uno::Sequence< css::beans::PropertyValue >& _rArgs, const css::uno::Reference< css::frame::XFrame >& _rxFrame ) override;
104 virtual void SAL_CALL cancel() override;
106 protected:
107 virtual ~SfxFrameLoader_Impl() override;
109 private:
110 std::shared_ptr<const SfxFilter> impl_getFilterFromServiceName_nothrow(
111 const OUString& i_rServiceName
112 ) const;
114 static OUString impl_askForFilter_nothrow(
115 const css::uno::Reference< css::task::XInteractionHandler >& i_rxHandler,
116 const OUString& i_rDocumentURL
119 std::shared_ptr<const SfxFilter> impl_detectFilterForURL(
120 const OUString& _rURL,
121 const ::comphelper::NamedValueCollection& i_rDescriptor,
122 const SfxFilterMatcher& rMatcher
123 ) const;
125 static bool impl_createNewDocWithSlotParam(
126 const sal_uInt16 _nSlotID,
127 const css::uno::Reference< css::frame::XFrame >& i_rxFrame,
128 const bool i_bHidden
131 void impl_determineFilter(
132 ::comphelper::NamedValueCollection& io_rDescriptor
133 ) const;
135 bool impl_determineTemplateDocument(
136 ::comphelper::NamedValueCollection& io_rDescriptor
137 ) const;
139 static sal_uInt16 impl_findSlotParam(
140 const OUString& i_rFactoryURL
143 static SfxObjectShellRef impl_findObjectShell(
144 const css::uno::Reference< css::frame::XModel2 >& i_rxDocument
147 static void impl_handleCaughtError_nothrow(
148 const css::uno::Any& i_rCaughtError,
149 const ::comphelper::NamedValueCollection& i_rDescriptor
152 static void impl_removeLoaderArguments(
153 ::comphelper::NamedValueCollection& io_rDescriptor
156 static SfxInterfaceId impl_determineEffectiveViewId_nothrow(
157 const SfxObjectShell& i_rDocument,
158 const ::comphelper::NamedValueCollection& i_rDescriptor
161 static ::comphelper::NamedValueCollection
162 impl_extractViewCreationArgs(
163 ::comphelper::NamedValueCollection& io_rDescriptor
166 static css::uno::Reference< css::frame::XController2 >
167 impl_createDocumentView(
168 const css::uno::Reference< css::frame::XModel2 >& i_rModel,
169 const css::uno::Reference< css::frame::XFrame >& i_rFrame,
170 const ::comphelper::NamedValueCollection& i_rViewFactoryArgs,
171 const OUString& i_rViewName
175 SfxFrameLoader_Impl::SfxFrameLoader_Impl( const Reference< css::uno::XComponentContext >& _rxContext )
176 :m_aContext( _rxContext )
180 SfxFrameLoader_Impl::~SfxFrameLoader_Impl()
185 std::shared_ptr<const SfxFilter> SfxFrameLoader_Impl::impl_detectFilterForURL( const OUString& sURL,
186 const ::comphelper::NamedValueCollection& i_rDescriptor, const SfxFilterMatcher& rMatcher ) const
188 OUString sFilter;
191 if ( sURL.isEmpty() )
192 return nullptr;
194 Reference< XTypeDetection > xDetect(
195 m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_aContext),
196 UNO_QUERY_THROW);
198 ::comphelper::NamedValueCollection aNewArgs;
199 aNewArgs.put( "URL", sURL );
201 if ( i_rDescriptor.has( "InteractionHandler" ) )
202 aNewArgs.put( "InteractionHandler", i_rDescriptor.get( "InteractionHandler" ) );
203 if ( i_rDescriptor.has( "StatusIndicator" ) )
204 aNewArgs.put( "StatusIndicator", i_rDescriptor.get( "StatusIndicator" ) );
206 Sequence< PropertyValue > aQueryArgs( aNewArgs.getPropertyValues() );
207 OUString sType = xDetect->queryTypeByDescriptor( aQueryArgs, true );
208 if ( !sType.isEmpty() )
210 std::shared_ptr<const SfxFilter> pFilter = rMatcher.GetFilter4EA( sType );
211 if ( pFilter )
212 sFilter = pFilter->GetName();
215 catch ( const RuntimeException& )
217 throw;
219 catch( const Exception& )
221 DBG_UNHANDLED_EXCEPTION("sfx.view");
222 sFilter.clear();
225 std::shared_ptr<const SfxFilter> pFilter;
226 if (!sFilter.isEmpty())
227 pFilter = rMatcher.GetFilter4FilterName(sFilter);
228 return pFilter;
232 std::shared_ptr<const SfxFilter> SfxFrameLoader_Impl::impl_getFilterFromServiceName_nothrow( const OUString& i_rServiceName ) const
236 ::comphelper::NamedValueCollection aQuery;
237 aQuery.put( "DocumentService", i_rServiceName );
239 const Reference< XContainerQuery > xQuery(
240 m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_aContext),
241 UNO_QUERY_THROW );
243 const SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
244 const SfxFilterFlags nMust = SfxFilterFlags::IMPORT;
245 const SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED;
247 Reference < XEnumeration > xEnum( xQuery->createSubSetEnumerationByProperties(
248 aQuery.getNamedValues() ), UNO_SET_THROW );
249 while ( xEnum->hasMoreElements() )
251 ::comphelper::NamedValueCollection aType( xEnum->nextElement() );
252 OUString sFilterName = aType.getOrDefault( "Name", OUString() );
253 if ( sFilterName.isEmpty() )
254 continue;
256 std::shared_ptr<const SfxFilter> pFilter = rMatcher.GetFilter4FilterName( sFilterName );
257 if ( !pFilter )
258 continue;
260 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
261 if ( ( ( nFlags & nMust ) == nMust )
262 && ( ( nFlags & nDont ) == SfxFilterFlags::NONE )
265 return pFilter;
269 catch( const Exception& )
271 DBG_UNHANDLED_EXCEPTION("sfx.view");
273 return nullptr;
277 OUString SfxFrameLoader_Impl::impl_askForFilter_nothrow( const Reference< XInteractionHandler >& i_rxHandler,
278 const OUString& i_rDocumentURL )
280 ENSURE_OR_THROW( i_rxHandler.is(), "invalid interaction handler" );
282 OUString sFilterName;
285 ::framework::RequestFilterSelect aRequest( i_rDocumentURL );
286 i_rxHandler->handle( aRequest.GetRequest() );
287 if( !aRequest.isAbort() )
288 sFilterName = aRequest.getFilter();
290 catch( const Exception& )
292 DBG_UNHANDLED_EXCEPTION("sfx.view");
295 return sFilterName;
298 bool lcl_getDispatchResult( const SfxPoolItem* _pResult )
300 if ( !_pResult )
301 return false;
303 // default must be set to true, because some return values
304 // can't be checked, but nonetheless indicate "success"!
305 bool bSuccess = true;
307 // On the other side some special slots return a boolean state,
308 // which can be set to FALSE.
309 const SfxBoolItem *pItem = dynamic_cast<const SfxBoolItem*>( _pResult );
310 if ( pItem )
311 bSuccess = pItem->GetValue();
313 return bSuccess;
316 bool SfxFrameLoader_Impl::impl_createNewDocWithSlotParam( const sal_uInt16 _nSlotID, const Reference< XFrame >& i_rxFrame,
317 const bool i_bHidden )
319 SfxRequest aRequest( _nSlotID, SfxCallMode::SYNCHRON, SfxGetpApp()->GetPool() );
320 aRequest.AppendItem( SfxUnoFrameItem( SID_FILLFRAME, i_rxFrame ) );
321 if ( i_bHidden )
322 aRequest.AppendItem( SfxBoolItem( SID_HIDDEN, true ) );
323 return lcl_getDispatchResult( SfxGetpApp()->ExecuteSlot( aRequest ) );
327 void SfxFrameLoader_Impl::impl_determineFilter( ::comphelper::NamedValueCollection& io_rDescriptor ) const
329 const OUString sURL = io_rDescriptor.getOrDefault( "URL", OUString() );
330 const OUString sTypeName = io_rDescriptor.getOrDefault( "TypeName", OUString() );
331 const OUString sFilterName = io_rDescriptor.getOrDefault( "FilterName", OUString() );
332 const OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", OUString() );
333 const Reference< XInteractionHandler >
334 xInteraction = io_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() );
336 const SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
337 std::shared_ptr<const SfxFilter> pFilter;
339 // get filter by its name directly ...
340 if ( !sFilterName.isEmpty() )
341 pFilter = rMatcher.GetFilter4FilterName( sFilterName );
343 // or search the preferred filter for the detected type ...
344 if ( !pFilter && !sTypeName.isEmpty() )
345 pFilter = rMatcher.GetFilter4EA( sTypeName );
347 // or use given document service for detection, too
348 if ( !pFilter && !sServiceName.isEmpty() )
349 pFilter = impl_getFilterFromServiceName_nothrow( sServiceName );
351 // or use interaction to ask user for right filter.
352 if ( !pFilter && xInteraction.is() && !sURL.isEmpty() )
354 OUString sSelectedFilter = impl_askForFilter_nothrow( xInteraction, sURL );
355 if ( !sSelectedFilter.isEmpty() )
356 pFilter = rMatcher.GetFilter4FilterName( sSelectedFilter );
359 if ( !pFilter )
360 return;
362 io_rDescriptor.put( "FilterName", pFilter->GetFilterName() );
364 // If detected filter indicates using of an own template format
365 // add property "AsTemplate" to descriptor. But suppress this step
366 // if such property already exists.
367 if ( pFilter->IsOwnTemplateFormat() && !io_rDescriptor.has( "AsTemplate" ) )
368 io_rDescriptor.put( "AsTemplate", true );
370 // The DocumentService property will finally be used to determine the document type to create, so
371 // override it with the service name as indicated by the found filter.
372 io_rDescriptor.put( "DocumentService", pFilter->GetServiceName() );
376 SfxObjectShellRef SfxFrameLoader_Impl::impl_findObjectShell( const Reference< XModel2 >& i_rxDocument )
378 for ( SfxObjectShell* pDoc = SfxObjectShell::GetFirst( nullptr, false ); pDoc;
379 pDoc = SfxObjectShell::GetNext( *pDoc, nullptr, false ) )
381 if ( i_rxDocument == pDoc->GetModel() )
383 return pDoc;
387 SAL_WARN( "sfx.view", "SfxFrameLoader_Impl::impl_findObjectShell: model is not based on SfxObjectShell - wrong frame loader usage!" );
388 return nullptr;
392 bool SfxFrameLoader_Impl::impl_determineTemplateDocument( ::comphelper::NamedValueCollection& io_rDescriptor ) const
396 const OUString sTemplateRegioName = io_rDescriptor.getOrDefault( "TemplateRegionName", OUString() );
397 const OUString sTemplateName = io_rDescriptor.getOrDefault( "TemplateName", OUString() );
398 const OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", OUString() );
399 const OUString sURL = io_rDescriptor.getOrDefault( "URL", OUString() );
401 // determine the full URL of the template to use, if any
402 OUString sTemplateURL;
403 if ( !sTemplateRegioName.isEmpty() && !sTemplateName.isEmpty() )
405 SfxDocumentTemplates aTmpFac;
406 aTmpFac.GetFull( sTemplateRegioName, sTemplateName, sTemplateURL );
408 else
410 if ( !sServiceName.isEmpty() )
411 sTemplateURL = SfxObjectFactory::GetStandardTemplate( sServiceName );
412 else
413 sTemplateURL = SfxObjectFactory::GetStandardTemplate( SfxObjectShell::GetServiceNameFromFactory( sURL ) );
416 if ( !sTemplateURL.isEmpty() )
418 // detect the filter for the template. Might still be NULL (if the template is broken, or does not
419 // exist, or some such), but this is handled by our caller the same way as if no template/URL was present.
420 std::shared_ptr<const SfxFilter> pTemplateFilter = impl_detectFilterForURL( sTemplateURL, io_rDescriptor, SfxGetpApp()->GetFilterMatcher() );
421 if ( pTemplateFilter )
423 // load the template document, but, well, "as template"
424 io_rDescriptor.put( "FilterName", pTemplateFilter->GetName() );
425 io_rDescriptor.put( "FileName", sTemplateURL );
426 io_rDescriptor.put( "AsTemplate", true );
428 // #i21583#
429 // the DocumentService property will finally be used to create the document. Thus, override any possibly
430 // present value with the document service of the template.
431 io_rDescriptor.put( "DocumentService", pTemplateFilter->GetServiceName() );
432 return true;
436 catch (...)
439 return false;
443 sal_uInt16 SfxFrameLoader_Impl::impl_findSlotParam( const OUString& i_rFactoryURL )
445 OUString sSlotParam;
446 const sal_Int32 nParamPos = i_rFactoryURL.indexOf( '?' );
447 if ( nParamPos >= 0 )
449 // currently only the "slot" parameter is supported
450 const sal_Int32 nSlotPos = i_rFactoryURL.indexOf( "slot=", nParamPos );
451 if ( nSlotPos > 0 )
452 sSlotParam = i_rFactoryURL.copy( nSlotPos + 5 );
455 if ( !sSlotParam.isEmpty() )
456 return sal_uInt16( sSlotParam.toInt32() );
458 return 0;
462 void SfxFrameLoader_Impl::impl_handleCaughtError_nothrow( const Any& i_rCaughtError, const ::comphelper::NamedValueCollection& i_rDescriptor )
466 const Reference< XInteractionHandler > xInteraction =
467 i_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() );
468 if ( !xInteraction.is() )
469 return;
470 ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( i_rCaughtError ) );
471 ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
472 pRequest->addContinuation( pApprove.get() );
474 const Reference< XInteractionHandler2 > xHandler( xInteraction, UNO_QUERY );
475 #if OSL_DEBUG_LEVEL > 0
476 const bool bHandled =
477 #endif
478 xHandler.is() && xHandler->handleInteractionRequest( pRequest.get() );
480 #if OSL_DEBUG_LEVEL > 0
481 if ( !bHandled )
482 // the interaction handler couldn't deal with this error
483 // => report it as assertion, at least (done in the DBG_UNHANDLED_EXCEPTION below)
484 ::cppu::throwException( i_rCaughtError );
485 #endif
487 catch( const Exception& )
489 DBG_UNHANDLED_EXCEPTION("sfx.view");
494 void SfxFrameLoader_Impl::impl_removeLoaderArguments( ::comphelper::NamedValueCollection& io_rDescriptor )
496 // remove the arguments which are for the loader only, and not for a call to attachResource
497 io_rDescriptor.remove( "StatusIndicator" );
498 io_rDescriptor.remove( "Model" );
502 ::comphelper::NamedValueCollection SfxFrameLoader_Impl::impl_extractViewCreationArgs( ::comphelper::NamedValueCollection& io_rDescriptor )
504 static const char* pKnownViewArgs[] = {
505 "JumpMark",
506 "PickListEntry"
509 ::comphelper::NamedValueCollection aViewArgs;
510 for (const char* pKnownViewArg : pKnownViewArgs)
512 if ( io_rDescriptor.has( pKnownViewArg ) )
514 aViewArgs.put( pKnownViewArg, io_rDescriptor.get( pKnownViewArg ) );
515 io_rDescriptor.remove( pKnownViewArg );
518 return aViewArgs;
522 SfxInterfaceId SfxFrameLoader_Impl::impl_determineEffectiveViewId_nothrow( const SfxObjectShell& i_rDocument, const ::comphelper::NamedValueCollection& i_rDescriptor )
524 SfxInterfaceId nViewId(i_rDescriptor.getOrDefault( "ViewId", sal_Int16( 0 ) ));
527 if ( nViewId == SFX_INTERFACE_NONE )
530 Reference< XViewDataSupplier > xViewDataSupplier( i_rDocument.GetModel(), UNO_QUERY );
531 Reference< XIndexAccess > xViewData;
532 if ( xViewDataSupplier.is() )
533 xViewData.set( xViewDataSupplier->getViewData() );
535 if ( !xViewData.is() || ( xViewData->getCount() == 0 ) )
536 // no view data stored together with the model
537 break;
539 // obtain the ViewID from the view data
540 Sequence< PropertyValue > aViewData;
541 if ( !( xViewData->getByIndex( 0 ) >>= aViewData ) )
542 break;
544 ::comphelper::NamedValueCollection aNamedViewData( aViewData );
545 OUString sViewId = aNamedViewData.getOrDefault( "ViewId", OUString() );
546 if ( sViewId.isEmpty() )
547 break;
549 // somewhat weird convention here ... in the view data, the ViewId is a string, effectively describing
550 // a view name. In the document load descriptor, the ViewId is in fact the numeric ID.
552 SfxViewFactory* pViewFactory = i_rDocument.GetFactory().GetViewFactoryByViewName( sViewId );
553 if ( pViewFactory )
554 nViewId = pViewFactory->GetOrdinal();
556 while ( false );
558 catch( const Exception& )
560 DBG_UNHANDLED_EXCEPTION("sfx.view");
563 if ( nViewId == SFX_INTERFACE_NONE )
564 nViewId = i_rDocument.GetFactory().GetViewFactory().GetOrdinal();
565 return nViewId;
569 Reference< XController2 > SfxFrameLoader_Impl::impl_createDocumentView( const Reference< XModel2 >& i_rModel,
570 const Reference< XFrame >& i_rFrame, const ::comphelper::NamedValueCollection& i_rViewFactoryArgs,
571 const OUString& i_rViewName )
573 // let the model create a new controller
574 const Reference< XController2 > xController( i_rModel->createViewController(
575 i_rViewName,
576 i_rViewFactoryArgs.getPropertyValues(),
577 i_rFrame
578 ), UNO_SET_THROW );
580 // introduce model/view/controller to each other
581 xController->attachModel( i_rModel.get() );
582 i_rModel->connectController( xController.get() );
583 i_rFrame->setComponent( xController->getComponentWindow(), xController.get() );
584 xController->attachFrame( i_rFrame );
585 i_rModel->setCurrentController( xController.get() );
587 return xController;
591 sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const Sequence< PropertyValue >& rArgs,
592 const Reference< XFrame >& _rTargetFrame )
594 ENSURE_OR_THROW( _rTargetFrame.is(), "illegal NULL frame" );
596 SolarMutexGuard aGuard;
598 SAL_INFO( "sfx.view", "SfxFrameLoader::load" );
600 ::comphelper::NamedValueCollection aDescriptor( rArgs );
602 // ensure the descriptor contains a referrer
603 if ( !aDescriptor.has( "Referer" ) )
604 aDescriptor.put( "Referer", OUString() );
606 // did the caller already pass a model?
607 Reference< XModel2 > xModel = aDescriptor.getOrDefault( "Model", Reference< XModel2 >() );
608 const bool bExternalModel = xModel.is();
610 // check for factory URLs to create a new doc, instead of loading one
611 const OUString sURL = aDescriptor.getOrDefault( "URL", OUString() );
612 const bool bIsFactoryURL = sURL.startsWith( "private:factory/" );
613 bool bInitNewModel = bIsFactoryURL;
614 const bool bIsDefault = bIsFactoryURL && !bExternalModel;
615 if (!aDescriptor.has("Replaceable"))
616 aDescriptor.put("Replaceable", bIsDefault);
617 if (bIsDefault)
619 const OUString sFactory = sURL.copy( sizeof( "private:factory/" ) -1 );
620 // special handling for some weird factory URLs a la private:factory/swriter?slot=21053
621 const sal_uInt16 nSlotParam = impl_findSlotParam( sFactory );
622 if ( nSlotParam != 0 )
624 return impl_createNewDocWithSlotParam( nSlotParam, _rTargetFrame, aDescriptor.getOrDefault( "Hidden", false ) );
627 const bool bDescribesValidTemplate = impl_determineTemplateDocument( aDescriptor );
628 if ( bDescribesValidTemplate )
630 // if the media descriptor allowed us to determine a template document to create the new document
631 // from, then do not init a new document model from scratch (below), but instead load the
632 // template document
633 bInitNewModel = false;
635 else
637 const OUString sServiceName = SfxObjectShell::GetServiceNameFromFactory( sFactory );
638 aDescriptor.put( "DocumentService", sServiceName );
641 else
643 // compatibility
644 aDescriptor.put( "FileName", aDescriptor.get( "URL" ) );
647 bool bLoadSuccess = false;
650 // extract view relevant arguments from the loader args
651 ::comphelper::NamedValueCollection aViewCreationArgs( impl_extractViewCreationArgs( aDescriptor ) );
653 // no model passed from outside? => create one from scratch
654 if ( !bExternalModel )
656 bool bInternalFilter = aDescriptor.getOrDefault<OUString>("FilterProvider", OUString()).isEmpty();
658 if (bInternalFilter && !bInitNewModel)
660 // Ensure that the current SfxFilter instance is loaded before
661 // going further. We don't need to do this for external
662 // filter providers.
663 impl_determineFilter(aDescriptor);
666 // create the new doc
667 const OUString sServiceName = aDescriptor.getOrDefault( "DocumentService", OUString() );
668 xModel.set( m_aContext->getServiceManager()->createInstanceWithContext(sServiceName, m_aContext), UNO_QUERY_THROW );
670 // load resp. init it
671 const Reference< XLoadable > xLoadable( xModel, UNO_QUERY_THROW );
672 if ( bInitNewModel )
674 xLoadable->initNew();
676 impl_removeLoaderArguments( aDescriptor );
677 xModel->attachResource( OUString(), aDescriptor.getPropertyValues() );
679 else
681 xLoadable->load( aDescriptor.getPropertyValues() );
684 else
686 // tell the doc its (current) load args.
687 impl_removeLoaderArguments( aDescriptor );
688 xModel->attachResource( xModel->getURL(), aDescriptor.getPropertyValues() );
691 // get the SfxObjectShell (still needed at the moment)
692 // SfxObjectShellRef is used here ( instead of ...Lock ) since the model is closed below if necessary
693 // SfxObjectShellLock would be even dangerous here, since the lifetime control should be done outside in case of success
694 const SfxObjectShellRef xDoc = impl_findObjectShell( xModel );
695 ENSURE_OR_THROW( xDoc.is(), "no SfxObjectShell for the given model" );
697 // ensure the ID of the to-be-created view is in the descriptor, if possible
698 const SfxInterfaceId nViewId = impl_determineEffectiveViewId_nothrow( *xDoc, aDescriptor );
699 const sal_Int16 nViewNo = xDoc->GetFactory().GetViewNo_Impl( nViewId, 0 );
700 const OUString sViewName( xDoc->GetFactory().GetViewFactory( nViewNo ).GetAPIViewName() );
702 // plug the document into the frame
703 Reference<XController2> xController =
704 impl_createDocumentView( xModel, _rTargetFrame, aViewCreationArgs, sViewName );
706 Reference<lang::XInitialization> xInit(xController, UNO_QUERY);
707 if (xInit.is())
709 uno::Sequence<uno::Any> aArgs; // empty for now.
710 xInit->initialize(aArgs);
713 bLoadSuccess = true;
715 catch ( Exception& )
717 const Any aError( ::cppu::getCaughtException() );
718 if ( !aDescriptor.getOrDefault( "Silent", false ) )
719 impl_handleCaughtError_nothrow( aError, aDescriptor );
722 // if loading was not successful, close the document
723 if ( !bLoadSuccess && !bExternalModel )
727 const Reference< XCloseable > xCloseable( xModel, UNO_QUERY_THROW );
728 xCloseable->close( true );
730 catch ( Exception& )
732 DBG_UNHANDLED_EXCEPTION("sfx.view");
736 return bLoadSuccess;
739 void SfxFrameLoader_Impl::cancel()
743 /* XServiceInfo */
744 OUString SAL_CALL SfxFrameLoader_Impl::getImplementationName()
746 return "com.sun.star.comp.office.FrameLoader";
749 /* XServiceInfo */
750 sal_Bool SAL_CALL SfxFrameLoader_Impl::supportsService( const OUString& sServiceName )
752 return cppu::supportsService(this, sServiceName);
755 /* XServiceInfo */
756 Sequence< OUString > SAL_CALL SfxFrameLoader_Impl::getSupportedServiceNames()
758 return { "com.sun.star.frame.SynchronousFrameLoader", "com.sun.star.frame.OfficeFrameLoader" };
763 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
764 com_sun_star_comp_office_FrameLoader_get_implementation(
765 css::uno::XComponentContext *context,
766 css::uno::Sequence<css::uno::Any> const &)
768 return cppu::acquire(new SfxFrameLoader_Impl(context));
771 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */