bump product version to 5.0.4.1
[LibreOffice.git] / sfx2 / source / view / frmload.cxx
blob2cc886a823c5b81dae662d3ae9d2b4ca6f56c652
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 <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/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>
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>
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;
104 namespace {
106 class SfxFrameLoader_Impl : public ::cppu::WeakImplHelper2< css::frame::XSynchronousFrameLoader, css::lang::XServiceInfo >
108 css::uno::Reference < css::uno::XComponentContext > m_aContext;
110 public:
111 explicit SfxFrameLoader_Impl( const css::uno::Reference < css::uno::XComponentContext >& _rxContext );
113 virtual OUString SAL_CALL getImplementationName()
114 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
116 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
117 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
119 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
120 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
123 // XSynchronousFrameLoader
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;
128 protected:
129 virtual ~SfxFrameLoader_Impl();
131 private:
132 const SfxFilter* impl_getFilterFromServiceName_nothrow(
133 const OUString& i_rServiceName
134 ) const;
136 static OUString impl_askForFilter_nothrow(
137 const css::uno::Reference< css::task::XInteractionHandler >& i_rxHandler,
138 const OUString& i_rDocumentURL
141 const SfxFilter* impl_detectFilterForURL(
142 const OUString& _rURL,
143 const ::comphelper::NamedValueCollection& i_rDescriptor,
144 const SfxFilterMatcher& rMatcher
145 ) const;
147 static bool impl_createNewDocWithSlotParam(
148 const sal_uInt16 _nSlotID,
149 const css::uno::Reference< css::frame::XFrame >& i_rxFrame,
150 const bool i_bHidden
153 void impl_determineFilter(
154 ::comphelper::NamedValueCollection& io_rDescriptor
155 ) const;
157 bool impl_determineTemplateDocument(
158 ::comphelper::NamedValueCollection& io_rDescriptor
159 ) const;
161 static sal_uInt16 impl_findSlotParam(
162 const OUString& i_rFactoryURL
165 static SfxObjectShellRef impl_findObjectShell(
166 const css::uno::Reference< css::frame::XModel2 >& i_rxDocument
169 static void impl_handleCaughtError_nothrow(
170 const css::uno::Any& i_rCaughtError,
171 const ::comphelper::NamedValueCollection& i_rDescriptor
174 static void impl_removeLoaderArguments(
175 ::comphelper::NamedValueCollection& io_rDescriptor
178 static sal_Int16 impl_determineEffectiveViewId_nothrow(
179 const SfxObjectShell& i_rDocument,
180 const ::comphelper::NamedValueCollection& i_rDescriptor
183 static ::comphelper::NamedValueCollection
184 impl_extractViewCreationArgs(
185 ::comphelper::NamedValueCollection& io_rDescriptor
188 static 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
197 SfxFrameLoader_Impl::SfxFrameLoader_Impl( const Reference< css::uno::XComponentContext >& _rxContext )
198 :m_aContext( _rxContext )
202 SfxFrameLoader_Impl::~SfxFrameLoader_Impl()
207 const SfxFilter* SfxFrameLoader_Impl::impl_detectFilterForURL( const OUString& sURL,
208 const ::comphelper::NamedValueCollection& i_rDescriptor, const SfxFilterMatcher& rMatcher ) const
210 OUString sFilter;
213 if ( sURL.isEmpty() )
214 return 0;
216 Reference< XTypeDetection > xDetect(
217 m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_aContext),
218 UNO_QUERY_THROW);
220 ::comphelper::NamedValueCollection aNewArgs;
221 aNewArgs.put( "URL", sURL );
223 if ( i_rDescriptor.has( "InteractionHandler" ) )
224 aNewArgs.put( "InteractionHandler", i_rDescriptor.get( "InteractionHandler" ) );
225 if ( i_rDescriptor.has( "StatusIndicator" ) )
226 aNewArgs.put( "StatusIndicator", i_rDescriptor.get( "StatusIndicator" ) );
228 Sequence< PropertyValue > aQueryArgs( aNewArgs.getPropertyValues() );
229 OUString sType = xDetect->queryTypeByDescriptor( aQueryArgs, sal_True );
230 if ( !sType.isEmpty() )
232 const SfxFilter* pFilter = rMatcher.GetFilter4EA( sType );
233 if ( pFilter )
234 sFilter = pFilter->GetName();
237 catch ( const RuntimeException& )
239 throw;
241 catch( const Exception& )
243 DBG_UNHANDLED_EXCEPTION();
244 sFilter.clear();
247 const SfxFilter* pFilter = 0;
248 if (!sFilter.isEmpty())
249 pFilter = rMatcher.GetFilter4FilterName(sFilter);
250 return pFilter;
254 const SfxFilter* SfxFrameLoader_Impl::impl_getFilterFromServiceName_nothrow( const OUString& i_rServiceName ) const
258 ::comphelper::NamedValueCollection aQuery;
259 aQuery.put( "DocumentService", i_rServiceName );
261 const Reference< XContainerQuery > xQuery(
262 m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_aContext),
263 UNO_QUERY_THROW );
265 const SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
266 const SfxFilterFlags nMust = SfxFilterFlags::IMPORT;
267 const SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED;
269 Reference < XEnumeration > xEnum( xQuery->createSubSetEnumerationByProperties(
270 aQuery.getNamedValues() ), UNO_SET_THROW );
271 while ( xEnum->hasMoreElements() )
273 ::comphelper::NamedValueCollection aType( xEnum->nextElement() );
274 OUString sFilterName = aType.getOrDefault( "Name", OUString() );
275 if ( sFilterName.isEmpty() )
276 continue;
278 const SfxFilter* pFilter = rMatcher.GetFilter4FilterName( sFilterName );
279 if ( !pFilter )
280 continue;
282 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
283 if ( ( ( nFlags & nMust ) == nMust )
284 && ( ( nFlags & nDont ) == SfxFilterFlags::NONE )
287 return pFilter;
291 catch( const Exception& )
293 DBG_UNHANDLED_EXCEPTION();
295 return NULL;
299 OUString SfxFrameLoader_Impl::impl_askForFilter_nothrow( const Reference< XInteractionHandler >& i_rxHandler,
300 const OUString& i_rDocumentURL )
302 ENSURE_OR_THROW( i_rxHandler.is(), "invalid interaction handler" );
304 OUString sFilterName;
307 ::framework::RequestFilterSelect aRequest( i_rDocumentURL );
308 i_rxHandler->handle( aRequest.GetRequest() );
309 if( !aRequest.isAbort() )
310 sFilterName = aRequest.getFilter();
312 catch( const Exception& )
314 DBG_UNHANDLED_EXCEPTION();
317 return sFilterName;
321 namespace
323 bool lcl_getDispatchResult( const SfxPoolItem* _pResult )
325 if ( !_pResult )
326 return false;
328 // default must be set to true, because some return values
329 // can't be checked, but nonetheless indicate "success"!
330 bool bSuccess = true;
332 // On the other side some special slots return a boolean state,
333 // which can be set to FALSE.
334 const SfxBoolItem *pItem = PTR_CAST( SfxBoolItem, _pResult );
335 if ( pItem )
336 bSuccess = pItem->GetValue();
338 return bSuccess;
343 bool SfxFrameLoader_Impl::impl_createNewDocWithSlotParam( const sal_uInt16 _nSlotID, const Reference< XFrame >& i_rxFrame,
344 const bool i_bHidden )
346 SfxRequest aRequest( _nSlotID, SfxCallMode::SYNCHRON, SfxGetpApp()->GetPool() );
347 aRequest.AppendItem( SfxUnoFrameItem( SID_FILLFRAME, i_rxFrame ) );
348 if ( i_bHidden )
349 aRequest.AppendItem( SfxBoolItem( SID_HIDDEN, true ) );
350 return lcl_getDispatchResult( SfxGetpApp()->ExecuteSlot( aRequest ) );
354 void SfxFrameLoader_Impl::impl_determineFilter( ::comphelper::NamedValueCollection& io_rDescriptor ) const
356 const OUString sURL = io_rDescriptor.getOrDefault( "URL", OUString() );
357 const OUString sTypeName = io_rDescriptor.getOrDefault( "TypeName", OUString() );
358 const OUString sFilterName = io_rDescriptor.getOrDefault( "FilterName", OUString() );
359 const OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", OUString() );
360 const Reference< XInteractionHandler >
361 xInteraction = io_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() );
363 const SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
364 const SfxFilter* pFilter = NULL;
366 // get filter by its name directly ...
367 if ( !sFilterName.isEmpty() )
368 pFilter = rMatcher.GetFilter4FilterName( sFilterName );
370 // or search the preferred filter for the detected type ...
371 if ( !pFilter && !sTypeName.isEmpty() )
372 pFilter = rMatcher.GetFilter4EA( sTypeName );
374 // or use given document service for detection, too
375 if ( !pFilter && !sServiceName.isEmpty() )
376 pFilter = impl_getFilterFromServiceName_nothrow( sServiceName );
378 // or use interaction to ask user for right filter.
379 if ( !pFilter && xInteraction.is() && !sURL.isEmpty() )
381 OUString sSelectedFilter = impl_askForFilter_nothrow( xInteraction, sURL );
382 if ( !sSelectedFilter.isEmpty() )
383 pFilter = rMatcher.GetFilter4FilterName( sSelectedFilter );
386 if ( pFilter )
388 io_rDescriptor.put( "FilterName", OUString( pFilter->GetFilterName() ) );
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 if ( pFilter->IsOwnTemplateFormat() && !io_rDescriptor.has( "AsTemplate" ) )
394 io_rDescriptor.put( "AsTemplate", true );
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 io_rDescriptor.put( "DocumentService", OUString( pFilter->GetServiceName() ) );
403 SfxObjectShellRef SfxFrameLoader_Impl::impl_findObjectShell( const Reference< XModel2 >& i_rxDocument )
405 for ( SfxObjectShell* pDoc = SfxObjectShell::GetFirst( NULL, false ); pDoc; pDoc = SfxObjectShell::GetNext( *pDoc, NULL, false ) )
407 if ( i_rxDocument == pDoc->GetModel() )
409 return pDoc;
413 SAL_WARN( "sfx.view", "SfxFrameLoader_Impl::impl_findObjectShell: model is not based on SfxObjectShell - wrong frame loader usage!" );
414 return NULL;
418 bool SfxFrameLoader_Impl::impl_determineTemplateDocument( ::comphelper::NamedValueCollection& io_rDescriptor ) const
422 const OUString sTemplateRegioName = io_rDescriptor.getOrDefault( "TemplateRegionName", OUString() );
423 const OUString sTemplateName = io_rDescriptor.getOrDefault( "TemplateName", OUString() );
424 const OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", OUString() );
425 const OUString sURL = io_rDescriptor.getOrDefault( "URL", OUString() );
427 // determine the full URL of the template to use, if any
428 OUString sTemplateURL;
429 if ( !sTemplateRegioName.isEmpty() && !sTemplateName.isEmpty() )
431 SfxDocumentTemplates aTmpFac;
432 aTmpFac.GetFull( sTemplateRegioName, sTemplateName, sTemplateURL );
434 else
436 if ( !sServiceName.isEmpty() )
437 sTemplateURL = SfxObjectFactory::GetStandardTemplate( sServiceName );
438 else
439 sTemplateURL = SfxObjectFactory::GetStandardTemplate( SfxObjectShell::GetServiceNameFromFactory( sURL ) );
442 if ( !sTemplateURL.isEmpty() )
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 const SfxFilter* pTemplateFilter = impl_detectFilterForURL( sTemplateURL, io_rDescriptor, SfxGetpApp()->GetFilterMatcher() );
447 if ( pTemplateFilter )
449 // load the template document, but, well, "as template"
450 io_rDescriptor.put( "FilterName", OUString( pTemplateFilter->GetName() ) );
451 io_rDescriptor.put( "FileName", OUString( sTemplateURL ) );
452 io_rDescriptor.put( "AsTemplate", sal_True );
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 io_rDescriptor.put( "DocumentService", OUString( pTemplateFilter->GetServiceName() ) );
458 return true;
462 catch (...)
465 return false;
469 sal_uInt16 SfxFrameLoader_Impl::impl_findSlotParam( const OUString& i_rFactoryURL )
471 OUString sSlotParam;
472 const sal_Int32 nParamPos = i_rFactoryURL.indexOf( '?' );
473 if ( nParamPos >= 0 )
475 // currently only the "slot" parameter is supported
476 const sal_Int32 nSlotPos = i_rFactoryURL.indexOf( "slot=", nParamPos );
477 if ( nSlotPos > 0 )
478 sSlotParam = i_rFactoryURL.copy( nSlotPos + 5 );
481 if ( !sSlotParam.isEmpty() )
482 return sal_uInt16( sSlotParam.toInt32() );
484 return 0;
488 void SfxFrameLoader_Impl::impl_handleCaughtError_nothrow( const Any& i_rCaughtError, const ::comphelper::NamedValueCollection& i_rDescriptor )
492 const Reference< XInteractionHandler > xInteraction =
493 i_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() );
494 if ( !xInteraction.is() )
495 return;
496 ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( i_rCaughtError ) );
497 ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
498 pRequest->addContinuation( pApprove.get() );
500 const Reference< XInteractionHandler2 > xHandler( xInteraction, UNO_QUERY );
501 #if OSL_DEBUG_LEVEL > 0
502 const bool bHandled =
503 #endif
504 xHandler.is() && xHandler->handleInteractionRequest( pRequest.get() );
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
513 catch( const Exception& )
515 DBG_UNHANDLED_EXCEPTION();
520 void SfxFrameLoader_Impl::impl_removeLoaderArguments( ::comphelper::NamedValueCollection& io_rDescriptor )
522 // remove the arguments which are for the loader only, and not for a call to attachResource
523 io_rDescriptor.remove( "StatusIndicator" );
524 io_rDescriptor.remove( "Model" );
528 ::comphelper::NamedValueCollection SfxFrameLoader_Impl::impl_extractViewCreationArgs( ::comphelper::NamedValueCollection& io_rDescriptor )
530 const sal_Char* pKnownViewArgs[] = {
531 "JumpMark"
534 ::comphelper::NamedValueCollection aViewArgs;
535 for ( size_t i=0; i < sizeof( pKnownViewArgs ) / sizeof( pKnownViewArgs[0] ); ++i )
537 if ( io_rDescriptor.has( pKnownViewArgs[i] ) )
539 aViewArgs.put( pKnownViewArgs[i], io_rDescriptor.get( pKnownViewArgs[i] ) );
540 io_rDescriptor.remove( pKnownViewArgs[i] );
543 return aViewArgs;
547 sal_Int16 SfxFrameLoader_Impl::impl_determineEffectiveViewId_nothrow( const SfxObjectShell& i_rDocument, const ::comphelper::NamedValueCollection& i_rDescriptor )
549 sal_Int16 nViewId = i_rDescriptor.getOrDefault( "ViewId", sal_Int16( 0 ) );
552 if ( nViewId == 0 ) do
554 Reference< XViewDataSupplier > xViewDataSupplier( i_rDocument.GetModel(), UNO_QUERY );
555 Reference< XIndexAccess > xViewData;
556 if ( xViewDataSupplier.is() )
557 xViewData.set( xViewDataSupplier->getViewData() );
559 if ( !xViewData.is() || ( xViewData->getCount() == 0 ) )
560 // no view data stored together with the model
561 break;
563 // obtain the ViewID from the view data
564 Sequence< PropertyValue > aViewData;
565 if ( !( xViewData->getByIndex( 0 ) >>= aViewData ) )
566 break;
568 ::comphelper::NamedValueCollection aNamedViewData( aViewData );
569 OUString sViewId = aNamedViewData.getOrDefault( "ViewId", OUString() );
570 if ( sViewId.isEmpty() )
571 break;
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.
576 SfxViewFactory* pViewFactory = i_rDocument.GetFactory().GetViewFactoryByViewName( sViewId );
577 if ( pViewFactory )
578 nViewId = sal_Int16( pViewFactory->GetOrdinal() );
580 while ( false );
582 catch( const Exception& )
584 DBG_UNHANDLED_EXCEPTION();
587 if ( nViewId == 0 )
588 nViewId = i_rDocument.GetFactory().GetViewFactory( 0 ).GetOrdinal();
589 return nViewId;
593 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 )
597 // let the model create a new controller
598 const Reference< XController2 > xController( i_rModel->createViewController(
599 i_rViewName,
600 i_rViewFactoryArgs.getPropertyValues(),
601 i_rFrame
602 ), UNO_SET_THROW );
604 // introduce model/view/controller to each other
605 xController->attachModel( i_rModel.get() );
606 i_rModel->connectController( xController.get() );
607 i_rFrame->setComponent( xController->getComponentWindow(), xController.get() );
608 xController->attachFrame( i_rFrame );
609 i_rModel->setCurrentController( xController.get() );
611 return xController;
615 sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const Sequence< PropertyValue >& rArgs,
616 const Reference< XFrame >& _rTargetFrame )
617 throw( RuntimeException, std::exception )
619 ENSURE_OR_THROW( _rTargetFrame.is(), "illegal NULL frame" );
621 SolarMutexGuard aGuard;
623 SAL_INFO( "sfx.view", "SfxFrameLoader::load" );
625 ::comphelper::NamedValueCollection aDescriptor( rArgs );
627 // ensure the descriptor contains a referrer
628 if ( !aDescriptor.has( "Referer" ) )
629 aDescriptor.put( "Referer", OUString() );
631 // did the caller already pass a model?
632 Reference< XModel2 > xModel = aDescriptor.getOrDefault( "Model", Reference< XModel2 >() );
633 const bool bExternalModel = xModel.is();
635 // check for factory URLs to create a new doc, instead of loading one
636 const OUString sURL = aDescriptor.getOrDefault( "URL", OUString() );
637 const bool bIsFactoryURL = sURL.startsWith( "private:factory/" );
638 bool bInitNewModel = bIsFactoryURL;
639 if ( bIsFactoryURL && !bExternalModel )
641 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 const sal_uInt16 nSlotParam = impl_findSlotParam( sFactory );
644 if ( nSlotParam != 0 )
646 return impl_createNewDocWithSlotParam( nSlotParam, _rTargetFrame, aDescriptor.getOrDefault( "Hidden", false ) );
649 const bool bDescribesValidTemplate = impl_determineTemplateDocument( aDescriptor );
650 if ( bDescribesValidTemplate )
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 bInitNewModel = false;
657 else
659 const OUString sServiceName = SfxObjectShell::GetServiceNameFromFactory( sFactory );
660 aDescriptor.put( "DocumentService", sServiceName );
663 else
665 // compatibility
666 aDescriptor.put( "FileName", aDescriptor.get( "URL" ) );
669 bool bLoadSuccess = false;
672 // extract view releant arguments from the loader args
673 ::comphelper::NamedValueCollection aViewCreationArgs( impl_extractViewCreationArgs( aDescriptor ) );
675 // no model passed from outside? => create one from scratch
676 if ( !xModel.is() )
678 bool bInternalFilter = aDescriptor.getOrDefault<OUString>("FilterProvider", OUString()).isEmpty();
680 if (bInternalFilter && !bInitNewModel)
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 impl_determineFilter(aDescriptor);
688 // create the new doc
689 const OUString sServiceName = aDescriptor.getOrDefault( "DocumentService", OUString() );
690 xModel.set( m_aContext->getServiceManager()->createInstanceWithContext(sServiceName, m_aContext), UNO_QUERY_THROW );
692 // load resp. init it
693 const Reference< XLoadable > xLoadable( xModel, UNO_QUERY_THROW );
694 if ( bInitNewModel )
696 xLoadable->initNew();
698 impl_removeLoaderArguments( aDescriptor );
699 xModel->attachResource( OUString(), aDescriptor.getPropertyValues() );
701 else
703 xLoadable->load( aDescriptor.getPropertyValues() );
706 else
708 // tell the doc its (current) load args.
709 impl_removeLoaderArguments( aDescriptor );
710 xModel->attachResource( xModel->getURL(), aDescriptor.getPropertyValues() );
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 const SfxObjectShellRef xDoc = impl_findObjectShell( xModel );
717 ENSURE_OR_THROW( xDoc.Is(), "no SfxObjectShell for the given model" );
719 // ensure the ID of the to-be-created view is in the descriptor, if possible
720 const sal_Int16 nViewId = impl_determineEffectiveViewId_nothrow( *xDoc, aDescriptor );
721 const sal_Int16 nViewNo = xDoc->GetFactory().GetViewNo_Impl( nViewId, 0 );
722 const OUString sViewName( xDoc->GetFactory().GetViewFactory( nViewNo ).GetAPIViewName() );
724 // plug the document into the frame
725 Reference<XController2> xController =
726 impl_createDocumentView( xModel, _rTargetFrame, aViewCreationArgs, sViewName );
728 Reference<lang::XInitialization> xInit(xController, UNO_QUERY);
729 if (xInit.is())
731 uno::Sequence<uno::Any> aArgs; // empty for now.
732 xInit->initialize(aArgs);
735 bLoadSuccess = true;
737 catch ( Exception& )
739 const Any aError( ::cppu::getCaughtException() );
740 if ( !aDescriptor.getOrDefault( "Silent", sal_False ) )
741 impl_handleCaughtError_nothrow( aError, aDescriptor );
744 // if loading was not successful, close the document
745 if ( !bLoadSuccess && !bExternalModel )
749 const Reference< XCloseable > xCloseable( xModel, UNO_QUERY_THROW );
750 xCloseable->close( sal_True );
752 catch ( Exception& )
754 DBG_UNHANDLED_EXCEPTION();
758 return bLoadSuccess;
761 void SfxFrameLoader_Impl::cancel() throw( RuntimeException, std::exception )
765 /* XServiceInfo */
766 OUString SAL_CALL SfxFrameLoader_Impl::getImplementationName() throw( RuntimeException, std::exception )
768 return OUString("com.sun.star.comp.office.FrameLoader");
771 /* XServiceInfo */
772 sal_Bool SAL_CALL SfxFrameLoader_Impl::supportsService( const OUString& sServiceName ) throw( RuntimeException, std::exception )
774 return cppu::supportsService(this, sServiceName);
777 /* XServiceInfo */
778 Sequence< OUString > SAL_CALL SfxFrameLoader_Impl::getSupportedServiceNames() throw( RuntimeException, std::exception )
780 Sequence< OUString > seqServiceNames( 2 );
781 seqServiceNames.getArray() [0] = "com.sun.star.frame.SynchronousFrameLoader";
782 seqServiceNames.getArray() [1] = "com.sun.star.frame.OfficeFrameLoader";
783 return seqServiceNames ;
788 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
789 com_sun_star_comp_office_FrameLoader_get_implementation(
790 css::uno::XComponentContext *context,
791 css::uno::Sequence<css::uno::Any> const &)
793 return cppu::acquire(new SfxFrameLoader_Impl(context));
796 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */