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 <sfx2/sfxbasecontroller.hxx>
22 #include <com/sun/star/awt/XVclWindowPeer.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/util/XCloseable.hpp>
25 #include <com/sun/star/util/XCloseBroadcaster.hpp>
26 #include <com/sun/star/util/XCloseListener.hpp>
27 #include <com/sun/star/util/CloseVetoException.hpp>
28 #include <com/sun/star/document/XCmisDocument.hpp>
29 #include <com/sun/star/document/XViewDataSupplier.hpp>
30 #include <cppuhelper/implbase.hxx>
31 #include <com/sun/star/frame/FrameActionEvent.hpp>
32 #include <com/sun/star/frame/FrameAction.hpp>
33 #include <com/sun/star/frame/FrameSearchFlag.hpp>
34 #include <com/sun/star/frame/CommandGroup.hpp>
35 #include <com/sun/star/frame/XFrame.hpp>
36 #include <com/sun/star/frame/XBorderResizeListener.hpp>
37 #include <com/sun/star/frame/XUntitledNumbers.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/lang/EventObject.hpp>
40 #include <com/sun/star/lang/XEventListener.hpp>
41 #include <com/sun/star/lang/XComponent.hpp>
42 #include <com/sun/star/container/XIndexAccess.hpp>
43 #include <comphelper/interfacecontainer3.hxx>
44 #include <comphelper/multicontainer2.hxx>
45 #include <sfx2/viewsh.hxx>
46 #include <sfx2/docfac.hxx>
47 #include <sfx2/viewfrm.hxx>
48 #include <sfx2/objsh.hxx>
49 #include <sfx2/app.hxx>
50 #include <sfx2/msgpool.hxx>
51 #include <sfx2/dispatch.hxx>
52 #include <sfx2/userinputinterception.hxx>
54 #include <unoctitm.hxx>
55 #include <sfx2/childwin.hxx>
56 #include <sfx2/sfxsids.hrc>
57 #include <sfx2/sfxresid.hxx>
58 #include <workwin.hxx>
59 #include <sfx2/infobar.hxx>
61 #include <osl/mutex.hxx>
62 #include <comphelper/diagnose_ex.hxx>
63 #include <comphelper/namedvaluecollection.hxx>
64 #include <comphelper/sequence.hxx>
65 #include <toolkit/helper/vclunohelper.hxx>
66 #include <framework/titlehelper.hxx>
67 #include <comphelper/processfactory.hxx>
68 #include <vcl/svapp.hxx>
69 #include <vcl/unohelp.hxx>
70 #include <tools/svborder.hxx>
72 #include <sfx2/event.hxx>
73 #include <sfx2/viewfac.hxx>
74 #include <sfx2/strings.hrc>
75 #include <sfxbasecontroller_internal.hxx>
77 #include <unordered_map>
79 #include <com/sun/star/ui/XSidebarProvider.hpp>
80 #include <sidebar/UnoSidebar.hxx>
82 #define TIMEOUT_START_RESCHEDULE 10L /* 10th s */
84 using namespace ::com::sun::star
;
85 using ::com::sun::star::uno::Reference
;
86 using ::com::sun::star::uno::RuntimeException
;
87 using ::com::sun::star::uno::UNO_QUERY_THROW
;
88 using ::com::sun::star::lang::DisposedException
;
89 using ::com::sun::star::awt::XWindow
;
90 using ::com::sun::star::frame::XController
;
91 using ::com::sun::star::frame::XDispatchProvider
;
92 using ::com::sun::star::document::XViewDataSupplier
;
93 using ::com::sun::star::container::XIndexAccess
;
94 using ::com::sun::star::beans::PropertyValue
;
95 using ::com::sun::star::beans::StringPair
;
96 using ::com::sun::star::uno::Sequence
;
97 using ::com::sun::star::uno::UNO_QUERY
;
98 using ::com::sun::star::uno::Exception
;
99 using ::com::sun::star::frame::XFrame
;
100 using ::com::sun::star::frame::XFrameActionListener
;
101 using ::com::sun::star::util::XCloseListener
;
102 using ::com::sun::star::task::XStatusIndicator
;
103 using ::com::sun::star::frame::XTitle
;
104 using ::com::sun::star::ui::XSidebarProvider
;
107 typedef std::unordered_map
< SfxGroupId
, sal_Int16
> GroupHashMap
;
109 sal_Int16
MapGroupIDToCommandGroup( SfxGroupId nGroupID
)
111 static GroupHashMap s_aHashMap
113 { SfxGroupId::Intern
, frame::CommandGroup::INTERNAL
},
114 { SfxGroupId::Application
, frame::CommandGroup::APPLICATION
},
115 { SfxGroupId::Document
, frame::CommandGroup::DOCUMENT
},
116 { SfxGroupId::View
, frame::CommandGroup::VIEW
},
117 { SfxGroupId::Edit
, frame::CommandGroup::EDIT
},
118 { SfxGroupId::Macro
, frame::CommandGroup::MACRO
},
119 { SfxGroupId::Options
, frame::CommandGroup::OPTIONS
},
120 { SfxGroupId::Math
, frame::CommandGroup::MATH
},
121 { SfxGroupId::Navigator
, frame::CommandGroup::NAVIGATOR
},
122 { SfxGroupId::Insert
, frame::CommandGroup::INSERT
},
123 { SfxGroupId::Format
, frame::CommandGroup::FORMAT
},
124 { SfxGroupId::Template
, frame::CommandGroup::TEMPLATE
},
125 { SfxGroupId::Text
, frame::CommandGroup::TEXT
},
126 { SfxGroupId::Frame
, frame::CommandGroup::FRAME
},
127 { SfxGroupId::Graphic
, frame::CommandGroup::GRAPHIC
},
128 { SfxGroupId::Table
, frame::CommandGroup::TABLE
},
129 { SfxGroupId::Enumeration
, frame::CommandGroup::ENUMERATION
},
130 { SfxGroupId::Data
, frame::CommandGroup::DATA
},
131 { SfxGroupId::Special
, frame::CommandGroup::SPECIAL
},
132 { SfxGroupId::Image
, frame::CommandGroup::IMAGE
},
133 { SfxGroupId::Chart
, frame::CommandGroup::CHART
},
134 { SfxGroupId::Explorer
, frame::CommandGroup::EXPLORER
},
135 { SfxGroupId::Connector
, frame::CommandGroup::CONNECTOR
},
136 { SfxGroupId::Modify
, frame::CommandGroup::MODIFY
},
137 { SfxGroupId::Drawing
, frame::CommandGroup::DRAWING
},
138 { SfxGroupId::Controls
, frame::CommandGroup::CONTROLS
},
142 GroupHashMap::const_iterator pIter
= s_aHashMap
.find( nGroupID
);
143 if ( pIter
!= s_aHashMap
.end() )
144 return pIter
->second
;
146 return frame::CommandGroup::INTERNAL
;
149 sal_uInt32
Get10ThSec()
151 sal_uInt32 n10Ticks
= 10 * static_cast<sal_uInt32
>(clock());
152 return n10Ticks
/ CLOCKS_PER_SEC
;
155 static sal_Int32 m_nInReschedule
= 0; /// static counter for rescheduling
157 static void reschedule()
159 if ( m_nInReschedule
== 0 )
162 Application::Reschedule();
169 class SfxStatusIndicator
: public ::cppu::WeakImplHelper
< task::XStatusIndicator
, lang::XEventListener
>
171 Reference
< XController
> xOwner
;
172 Reference
< task::XStatusIndicator
> xProgress
;
173 SfxWorkWindow
* pWorkWindow
;
174 tools::Long _nStartTime
;
176 SfxStatusIndicator(SfxBaseController
* pController
, SfxWorkWindow
* pWork
)
177 : xOwner( pController
)
178 , pWorkWindow( pWork
)
181 osl_atomic_increment(&m_refCount
);
182 Reference
< lang::XComponent
> xComponent
= pController
;
184 xComponent
->addEventListener(this);
185 osl_atomic_decrement(&m_refCount
);
188 virtual void SAL_CALL
start(const OUString
& aText
, sal_Int32 nRange
) override
;
189 virtual void SAL_CALL
end() override
;
190 virtual void SAL_CALL
setText(const OUString
& aText
) override
;
191 virtual void SAL_CALL
setValue(sal_Int32 nValue
) override
;
192 virtual void SAL_CALL
reset() override
;
194 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) override
;
199 void SAL_CALL
SfxStatusIndicator::start(const OUString
& aText
, sal_Int32 nRange
)
201 SolarMutexGuard aGuard
;
204 if ( !xProgress
.is() )
205 xProgress
= pWorkWindow
->GetStatusIndicator();
207 if ( xProgress
.is() )
208 xProgress
->start( aText
, nRange
);
210 _nStartTime
= Get10ThSec();
215 void SAL_CALL
SfxStatusIndicator::end()
217 SolarMutexGuard aGuard
;
220 if ( !xProgress
.is() )
221 xProgress
= pWorkWindow
->GetStatusIndicator();
223 if ( xProgress
.is() )
230 void SAL_CALL
SfxStatusIndicator::setText(const OUString
& aText
)
232 SolarMutexGuard aGuard
;
235 if ( !xProgress
.is() )
236 xProgress
= pWorkWindow
->GetStatusIndicator();
238 if ( xProgress
.is() )
239 xProgress
->setText( aText
);
245 void SAL_CALL
SfxStatusIndicator::setValue( sal_Int32 nValue
)
247 SolarMutexGuard aGuard
;
250 if ( !xProgress
.is() )
251 xProgress
= pWorkWindow
->GetStatusIndicator();
253 if ( xProgress
.is() )
254 xProgress
->setValue( nValue
);
256 bool bReschedule
= (( Get10ThSec() - _nStartTime
) > TIMEOUT_START_RESCHEDULE
);
262 void SAL_CALL
SfxStatusIndicator::reset()
264 SolarMutexGuard aGuard
;
267 if ( !xProgress
.is() )
268 xProgress
= pWorkWindow
->GetStatusIndicator();
270 if ( xProgress
.is() )
277 void SAL_CALL
SfxStatusIndicator::disposing( const lang::EventObject
& /*Source*/ )
279 SolarMutexGuard aGuard
;
285 // declaration IMPL_SfxBaseController_ListenerHelper
289 class IMPL_SfxBaseController_ListenerHelper
: public ::cppu::WeakImplHelper
< frame::XFrameActionListener
>
292 explicit IMPL_SfxBaseController_ListenerHelper( SfxBaseController
* pController
) ;
294 virtual void SAL_CALL
frameAction( const frame::FrameActionEvent
& aEvent
) override
;
295 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) override
;
299 SfxBaseController
* m_pController
;
301 } ; // class IMPL_SfxBaseController_ListenerContainer
303 class IMPL_SfxBaseController_CloseListenerHelper
: public ::cppu::WeakImplHelper
< util::XCloseListener
>
306 explicit IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController
* pController
) ;
308 virtual void SAL_CALL
queryClosing( const lang::EventObject
& aEvent
, sal_Bool bDeliverOwnership
) override
;
309 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& aEvent
) override
;
310 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) override
;
314 SfxBaseController
* m_pController
;
316 } ; // class IMPL_SfxBaseController_ListenerContainer
320 IMPL_SfxBaseController_CloseListenerHelper::IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController
* pController
)
321 : m_pController ( pController
)
325 void SAL_CALL
IMPL_SfxBaseController_CloseListenerHelper::disposing( const lang::EventObject
& /*aEvent*/ )
329 void SAL_CALL
IMPL_SfxBaseController_CloseListenerHelper::queryClosing( const lang::EventObject
& /*aEvent*/, sal_Bool
/*bDeliverOwnership*/ )
331 SolarMutexGuard aGuard
;
332 SfxViewShell
* pShell
= m_pController
->GetViewShell_Impl();
335 bool bCanClose
= pShell
->PrepareClose( false );
338 throw util::CloseVetoException(u
"Controller disagree ..."_ustr
,getXWeak());
343 void SAL_CALL
IMPL_SfxBaseController_CloseListenerHelper::notifyClosing( const lang::EventObject
& /*aEvent*/ )
348 // declaration IMPL_SfxBaseController_DataContainer
351 struct IMPL_SfxBaseController_DataContainer
353 Reference
< XFrame
> m_xFrame
;
354 Reference
< XFrameActionListener
> m_xListener
;
355 Reference
< XCloseListener
> m_xCloseListener
;
356 ::sfx2::UserInputInterception m_aUserInputInterception
;
357 ::comphelper::OMultiTypeInterfaceContainerHelper2 m_aListenerContainer
;
358 ::comphelper::OInterfaceContainerHelper3
<ui::XContextMenuInterceptor
> m_aInterceptorContainer
;
359 rtl::Reference
< SfxStatusIndicator
> m_xIndicator
;
360 SfxViewShell
* m_pViewShell
;
361 SfxBaseController
* m_pController
;
363 bool m_bSuspendState
;
364 rtl::Reference
< ::framework::TitleHelper
> m_xTitleHelper
;
365 Sequence
< PropertyValue
> m_aCreationArgs
;
367 IMPL_SfxBaseController_DataContainer( ::osl::Mutex
& aMutex
,
368 SfxViewShell
* pViewShell
,
369 SfxBaseController
* pController
)
370 : m_xListener ( new IMPL_SfxBaseController_ListenerHelper( pController
) )
371 , m_xCloseListener ( new IMPL_SfxBaseController_CloseListenerHelper( pController
) )
372 , m_aUserInputInterception ( *pController
, aMutex
)
373 , m_aListenerContainer ( aMutex
)
374 , m_aInterceptorContainer ( aMutex
)
375 , m_pViewShell ( pViewShell
)
376 , m_pController ( pController
)
377 , m_bDisposing ( false )
378 , m_bSuspendState ( false )
382 } ; // struct IMPL_SfxBaseController_DataContainer
385 // IMPL_SfxBaseController_ListenerHelper constructor
388 IMPL_SfxBaseController_ListenerHelper::IMPL_SfxBaseController_ListenerHelper( SfxBaseController
* pController
)
389 : m_pController ( pController
)
393 void SAL_CALL
IMPL_SfxBaseController_ListenerHelper::frameAction( const frame::FrameActionEvent
& aEvent
)
395 SolarMutexGuard aGuard
;
397 ( m_pController
!= nullptr ) &&
398 ( aEvent
.Frame
== m_pController
->getFrame() ) &&
399 ( m_pController
->GetViewShell_Impl() && m_pController
->GetViewShell_Impl()->GetWindow() != nullptr )
402 if ( aEvent
.Action
== frame::FrameAction_FRAME_UI_ACTIVATED
)
404 if ( !m_pController
->GetViewShell_Impl()->GetUIActiveIPClient_Impl() )
405 m_pController
->GetViewShell_Impl()->GetViewFrame().MakeActive_Impl( false );
407 else if ( aEvent
.Action
== frame::FrameAction_CONTEXT_CHANGED
)
409 m_pController
->GetViewShell_Impl()->GetViewFrame().GetBindings().ContextChanged_Impl();
415 // IMPL_SfxBaseController_ListenerHelper -> XEventListener
418 void SAL_CALL
IMPL_SfxBaseController_ListenerHelper::disposing( const lang::EventObject
& /*aEvent*/ )
420 SolarMutexGuard aGuard
;
421 if ( m_pController
&& m_pController
->getFrame().is() )
422 m_pController
->getFrame()->removeFrameActionListener( this ) ;
425 SfxBaseController::SfxBaseController( SfxViewShell
* pViewShell
)
426 : m_pData ( new IMPL_SfxBaseController_DataContainer( m_aMutex
, pViewShell
, this ))
428 m_pData
->m_pViewShell
->SetController( this );
432 // SfxBaseController -> destructor
435 SfxBaseController::~SfxBaseController()
440 // SfxBaseController -> XController2
443 Reference
< XWindow
> SAL_CALL
SfxBaseController::getComponentWindow()
445 SolarMutexGuard aGuard
;
446 if ( !m_pData
->m_pViewShell
)
447 throw DisposedException();
449 return Reference
< XWindow
>( GetViewFrame_Impl().GetFrame().GetWindow().GetComponentInterface(), UNO_QUERY_THROW
);
452 OUString SAL_CALL
SfxBaseController::getViewControllerName()
454 SolarMutexGuard aGuard
;
455 if ( !m_pData
->m_pViewShell
|| !m_pData
->m_pViewShell
->GetObjectShell() )
456 throw DisposedException();
458 const SfxObjectFactory
& rDocFac( m_pData
->m_pViewShell
->GetObjectShell()->GetFactory() );
459 sal_uInt16 nViewNo
= rDocFac
.GetViewNo_Impl( GetViewFrame_Impl().GetCurViewId(), rDocFac
.GetViewFactoryCount() );
460 OSL_ENSURE( nViewNo
< rDocFac
.GetViewFactoryCount(), "SfxBaseController::getViewControllerName: view ID not found in view factories!" );
463 if ( nViewNo
< rDocFac
.GetViewFactoryCount() )
464 sViewName
= rDocFac
.GetViewFactory( nViewNo
).GetAPIViewName();
469 Sequence
< PropertyValue
> SAL_CALL
SfxBaseController::getCreationArguments()
471 SolarMutexGuard aGuard
;
472 if ( !m_pData
->m_pViewShell
|| !m_pData
->m_pViewShell
->GetObjectShell() )
473 throw DisposedException();
475 return m_pData
->m_aCreationArgs
;
478 void SfxBaseController::SetCreationArguments_Impl( const Sequence
< PropertyValue
>& i_rCreationArgs
)
480 OSL_ENSURE( !m_pData
->m_aCreationArgs
.hasElements(), "SfxBaseController::SetCreationArguments_Impl: not intended to be called twice!" );
481 m_pData
->m_aCreationArgs
= i_rCreationArgs
;
484 SfxViewFrame
& SfxBaseController::GetViewFrame_Impl() const
486 ENSURE_OR_THROW( m_pData
->m_pViewShell
, "not to be called without a view shell" );
487 SfxViewFrame
* pActFrame
= m_pData
->m_pViewShell
->GetFrame();
488 ENSURE_OR_THROW( pActFrame
, "a view shell without a view frame is pretty pathological" );
493 Reference
<XSidebarProvider
> SAL_CALL
SfxBaseController::getSidebar()
495 SfxViewFrame
& rViewFrame
= GetViewFrame_Impl();
496 SfxFrame
& rFrame
= rViewFrame
.GetFrame();
498 Reference
<XSidebarProvider
> rSidebar
= new SfxUnoSidebar(rFrame
.GetFrameInterface());
503 // SfxBaseController -> XController2 -> XController
506 void SAL_CALL
SfxBaseController::attachFrame( const Reference
< frame::XFrame
>& xFrame
)
508 Reference
< frame::XFrame
> xTemp( getFrame() ) ;
510 SolarMutexGuard aGuard
;
513 xTemp
->removeFrameActionListener( m_pData
->m_xListener
) ;
514 Reference
< util::XCloseBroadcaster
> xCloseable( xTemp
, uno::UNO_QUERY
);
515 if ( xCloseable
.is() )
516 xCloseable
->removeCloseListener( m_pData
->m_xCloseListener
);
519 m_pData
->m_xFrame
= xFrame
;
524 xFrame
->addFrameActionListener( m_pData
->m_xListener
) ;
525 Reference
< util::XCloseBroadcaster
> xCloseable( xFrame
, uno::UNO_QUERY
);
526 if ( xCloseable
.is() )
527 xCloseable
->addCloseListener( m_pData
->m_xCloseListener
);
529 if ( m_pData
->m_pViewShell
)
531 ConnectSfxFrame_Impl( E_CONNECT
);
534 // attaching the frame to the controller is the last step in the creation of a new view, so notify this
535 SfxViewEventHint
aHint( SfxEventHintId::ViewCreated
, GlobalEventConfig::GetEventName( GlobalEventId::VIEWCREATED
), m_pData
->m_pViewShell
->GetObjectShell(), Reference
< frame::XController2
>( this ) );
536 SfxGetpApp()->NotifyEvent( aHint
);
541 // SfxBaseController -> XController
544 sal_Bool SAL_CALL
SfxBaseController::attachModel( const Reference
< frame::XModel
>& xModel
)
546 if ( m_pData
->m_pViewShell
&& xModel
.is() && xModel
!= m_pData
->m_pViewShell
->GetObjectShell()->GetModel() )
548 // don't allow to reattach a model!
549 OSL_FAIL("Can't reattach model!");
553 Reference
< util::XCloseBroadcaster
> xCloseable( xModel
, uno::UNO_QUERY
);
554 if ( xCloseable
.is() )
555 xCloseable
->addCloseListener( m_pData
->m_xCloseListener
);
560 // SfxBaseController -> XController
563 sal_Bool SAL_CALL
SfxBaseController::suspend( sal_Bool bSuspend
)
565 SolarMutexGuard aGuard
;
567 // ignore duplicate calls, which doesn't change anything real
568 if (bool(bSuspend
) == m_pData
->m_bSuspendState
)
573 if ( !m_pData
->m_pViewShell
)
575 m_pData
->m_bSuspendState
= true;
579 if ( !m_pData
->m_pViewShell
->PrepareClose() )
582 if ( getFrame().is() )
583 getFrame()->removeFrameActionListener( m_pData
->m_xListener
) ;
584 SfxViewFrame
* pActFrame
= m_pData
->m_pViewShell
->GetFrame() ;
586 // More Views on the same document?
587 SfxObjectShell
* pDocShell
= m_pData
->m_pViewShell
->GetObjectShell() ;
588 bool bOther
= false ;
590 for ( const SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst( pDocShell
); !bOther
&& pFrame
; pFrame
= SfxViewFrame::GetNext( *pFrame
, pDocShell
) )
591 bOther
= (pFrame
!= pActFrame
);
593 bool bRet
= bOther
|| pDocShell
->PrepareClose();
596 ConnectSfxFrame_Impl( E_DISCONNECT
);
597 m_pData
->m_bSuspendState
= true;
604 if ( getFrame().is() )
605 getFrame()->addFrameActionListener( m_pData
->m_xListener
) ;
607 if ( m_pData
->m_pViewShell
)
609 ConnectSfxFrame_Impl( E_RECONNECT
);
612 m_pData
->m_bSuspendState
= false;
618 // SfxBaseController -> XController
621 uno::Any
SfxBaseController::getViewData()
624 SolarMutexGuard aGuard
;
625 if ( m_pData
->m_pViewShell
)
628 m_pData
->m_pViewShell
->WriteUserData( sData
) ;
636 // SfxBaseController -> XController
639 void SAL_CALL
SfxBaseController::restoreViewData( const uno::Any
& aValue
)
641 SolarMutexGuard aGuard
;
642 if ( m_pData
->m_pViewShell
)
646 m_pData
->m_pViewShell
->ReadUserData( sData
) ;
651 // SfxBaseController -> XController
654 Reference
< frame::XFrame
> SAL_CALL
SfxBaseController::getFrame()
656 SolarMutexGuard aGuard
;
657 return m_pData
->m_xFrame
;
661 // SfxBaseController -> XController
664 Reference
< frame::XModel
> SAL_CALL
SfxBaseController::getModel()
666 SolarMutexGuard aGuard
;
667 return m_pData
->m_pViewShell
? m_pData
->m_pViewShell
->GetObjectShell()->GetModel() : Reference
< frame::XModel
> () ;
671 // SfxBaseController -> XDispatchProvider
673 static css::uno::Reference
<css::frame::XDispatch
>
674 GetSlotDispatchWithFallback(SfxViewFrame
* pViewFrame
, const css::util::URL
& aURL
,
675 const OUString
& sActCommand
, bool bMasterCommand
, const SfxSlot
* pSlot
)
679 if (pSlot
&& (!pViewFrame
->GetFrame().IsInPlace() || !pSlot
->IsMode(SfxSlotMode::CONTAINER
)))
680 return pViewFrame
->GetBindings().GetDispatch(pSlot
, aURL
, bMasterCommand
);
682 // try to find parent SfxViewFrame
683 if (const auto& xOwnFrame
= pViewFrame
->GetFrame().GetFrameInterface())
685 if (const auto xParentFrame
= xOwnFrame
->getCreator())
687 // TODO/LATER: in future probably SfxViewFrame hierarchy should be the same as XFrame hierarchy
688 // SfxViewFrame* pParentFrame = pViewFrame->GetParentViewFrame();
690 // search the related SfxViewFrame
691 SfxViewFrame
* pParentFrame
= nullptr;
692 for (SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst(); pFrame
;
693 pFrame
= SfxViewFrame::GetNext(*pFrame
))
695 if (pFrame
->GetFrame().GetFrameInterface() == xParentFrame
)
697 pParentFrame
= pFrame
;
704 const SfxSlotPool
& rFrameSlotPool
= SfxSlotPool::GetSlotPool(pParentFrame
);
705 if (const SfxSlot
* pSlot2
= rFrameSlotPool
.GetUnoSlot(sActCommand
))
706 return pParentFrame
->GetBindings().GetDispatch(pSlot2
, aURL
, bMasterCommand
);
714 Reference
< frame::XDispatch
> SAL_CALL
SfxBaseController::queryDispatch( const util::URL
& aURL
,
715 const OUString
& sTargetFrameName
,
716 sal_Int32 eSearchFlags
)
718 SolarMutexGuard aGuard
;
720 if (!m_pData
->m_bDisposing
&& m_pData
->m_pViewShell
)
722 SfxViewFrame
& rAct
= m_pData
->m_pViewShell
->GetViewFrame() ;
723 if ( sTargetFrameName
== "_beamer" )
725 if ( eSearchFlags
& frame::FrameSearchFlag::CREATE
)
726 rAct
.SetChildWindow( SID_BROWSER
, true );
727 if (SfxChildWindow
* pChildWin
= rAct
.GetChildWindow(SID_BROWSER
))
729 if (Reference
<frame::XFrame
> xFrame
{ pChildWin
->GetFrame() })
731 xFrame
->setName(sTargetFrameName
);
732 if (Reference
<XDispatchProvider
> xProv
{ xFrame
, uno::UNO_QUERY
})
733 return xProv
->queryDispatch(aURL
, sTargetFrameName
, frame::FrameSearchFlag::SELF
);
738 if ( aURL
.Protocol
== ".uno:" )
740 OUString aActCommand
= SfxOfficeDispatch::GetMasterUnoCommand(aURL
);
741 bool bMasterCommand(!aActCommand
.isEmpty());
743 aActCommand
= aURL
.Path
;
744 const SfxSlot
* pSlot
= SfxSlotPool::GetSlotPool(&rAct
).GetUnoSlot(aActCommand
);
745 return GetSlotDispatchWithFallback(&rAct
, aURL
, aActCommand
, bMasterCommand
, pSlot
);
747 else if ( aURL
.Protocol
== "slot:" )
749 sal_uInt16 nId
= static_cast<sal_uInt16
>(aURL
.Path
.toInt32());
751 if (nId
>= SID_VERB_START
&& nId
<= SID_VERB_END
)
753 const SfxSlot
* pSlot
= m_pData
->m_pViewShell
->GetVerbSlot_Impl(nId
);
755 return rAct
.GetBindings().GetDispatch( pSlot
, aURL
, false );
758 const SfxSlot
* pSlot
= SfxSlotPool::GetSlotPool(&rAct
).GetSlot(nId
);
759 return GetSlotDispatchWithFallback(&rAct
, aURL
, aURL
.Path
, false, pSlot
);
761 else if( sTargetFrameName
== "_self" || sTargetFrameName
.isEmpty() )
763 // check for already loaded URL ... but with additional jumpmark!
764 Reference
< frame::XModel
> xModel
= getModel();
765 if( xModel
.is() && !aURL
.Mark
.isEmpty() )
767 SfxSlotPool
& rSlotPool
= SfxSlotPool::GetSlotPool( &rAct
);
768 const SfxSlot
* pSlot
= rSlotPool
.GetSlot( SID_JUMPTOMARK
);
769 if( !aURL
.Main
.isEmpty() && aURL
.Main
== xModel
->getURL() && pSlot
)
770 return Reference
< frame::XDispatch
>( new SfxOfficeDispatch( rAct
.GetBindings(), rAct
.GetDispatcher(), pSlot
, aURL
) );
779 // SfxBaseController -> XDispatchProvider
782 uno::Sequence
< Reference
< frame::XDispatch
> > SAL_CALL
SfxBaseController::queryDispatches( const uno::Sequence
< frame::DispatchDescriptor
>& seqDescripts
)
784 // Create return list - which must have same size then the given descriptor
785 // It's not allowed to pack it!
786 sal_Int32 nCount
= seqDescripts
.getLength();
787 uno::Sequence
< Reference
< frame::XDispatch
> > lDispatcher( nCount
);
789 std::transform(seqDescripts
.begin(), seqDescripts
.end(), lDispatcher
.getArray(),
790 [this](const frame::DispatchDescriptor
& rDesc
) -> Reference
< frame::XDispatch
> {
791 return queryDispatch(rDesc
.FeatureURL
, rDesc
.FrameName
, rDesc
.SearchFlags
); });
797 // SfxBaseController -> XControllerBorder
800 frame::BorderWidths SAL_CALL
SfxBaseController::getBorder()
802 frame::BorderWidths aResult
;
804 SolarMutexGuard aGuard
;
805 if ( m_pData
->m_pViewShell
)
807 SvBorder aBorder
= m_pData
->m_pViewShell
->GetBorderPixel();
808 aResult
.Left
= aBorder
.Left();
809 aResult
.Top
= aBorder
.Top();
810 aResult
.Right
= aBorder
.Right();
811 aResult
.Bottom
= aBorder
.Bottom();
817 void SAL_CALL
SfxBaseController::addBorderResizeListener( const Reference
< frame::XBorderResizeListener
>& xListener
)
819 m_pData
->m_aListenerContainer
.addInterface( cppu::UnoType
<frame::XBorderResizeListener
>::get(),
823 void SAL_CALL
SfxBaseController::removeBorderResizeListener( const Reference
< frame::XBorderResizeListener
>& xListener
)
825 m_pData
->m_aListenerContainer
.removeInterface( cppu::UnoType
<frame::XBorderResizeListener
>::get(),
829 awt::Rectangle SAL_CALL
SfxBaseController::queryBorderedArea( const awt::Rectangle
& aPreliminaryRectangle
)
831 SolarMutexGuard aGuard
;
832 if ( m_pData
->m_pViewShell
)
834 tools::Rectangle aTmpRect
= vcl::unohelper::ConvertToVCLRect(aPreliminaryRectangle
);
835 m_pData
->m_pViewShell
->QueryObjAreaPixel( aTmpRect
);
836 return vcl::unohelper::ConvertToAWTRect(aTmpRect
);
839 return aPreliminaryRectangle
;
842 void SfxBaseController::BorderWidthsChanged_Impl()
844 ::comphelper::OInterfaceContainerHelper2
* pContainer
= m_pData
->m_aListenerContainer
.getContainer(
845 cppu::UnoType
<frame::XBorderResizeListener
>::get());
849 frame::BorderWidths aBWidths
= getBorder();
850 Reference
< uno::XInterface
> xThis( getXWeak() );
852 ::comphelper::OInterfaceIteratorHelper2
pIterator(*pContainer
);
853 while (pIterator
.hasMoreElements())
857 static_cast<frame::XBorderResizeListener
*>(pIterator
.next())->borderWidthsChanged( xThis
, aBWidths
);
859 catch (const RuntimeException
&)
867 // SfxBaseController -> XComponent
870 void SAL_CALL
SfxBaseController::dispose()
872 SolarMutexGuard aGuard
;
873 Reference
< XController
> xKeepAlive( this );
874 m_pData
->m_bDisposing
= true ;
876 lang::EventObject aEventObject
;
877 aEventObject
.Source
= *this ;
878 m_pData
->m_aListenerContainer
.disposeAndClear( aEventObject
) ;
880 if ( m_pData
->m_pController
&& m_pData
->m_pController
->getFrame().is() )
881 m_pData
->m_pController
->getFrame()->removeFrameActionListener( m_pData
->m_xListener
) ;
883 if ( !m_pData
->m_pViewShell
)
886 SfxViewFrame
& rFrame
= m_pData
->m_pViewShell
->GetViewFrame() ;
887 if (rFrame
.GetViewShell() == m_pData
->m_pViewShell
)
888 rFrame
.GetFrame().SetIsClosing_Impl();
889 m_pData
->m_pViewShell
->DisconnectAllClients();
891 lang::EventObject aObject
;
892 aObject
.Source
= *this ;
894 SfxObjectShell
* pDoc
= rFrame
.GetObjectShell() ;
895 SfxViewFrame
*pView
= SfxViewFrame::GetFirst(pDoc
);
898 // if there is another ViewFrame or currently the ViewShell in my ViewFrame is switched (PagePreview)
899 if ( pView
!= &rFrame
|| pView
->GetViewShell() != m_pData
->m_pViewShell
)
901 pView
= SfxViewFrame::GetNext( *pView
, pDoc
);
904 SfxGetpApp()->NotifyEvent( SfxViewEventHint(SfxEventHintId::CloseView
, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEVIEW
), pDoc
, Reference
< frame::XController2
>( this ) ) );
906 SfxGetpApp()->NotifyEvent( SfxEventHint(SfxEventHintId::CloseDoc
, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC
), pDoc
) );
908 Reference
< frame::XModel
> xModel
= pDoc
->GetModel();
909 Reference
< util::XCloseable
> xCloseable( xModel
, uno::UNO_QUERY
);
912 xModel
->disconnectController( this );
913 if ( xCloseable
.is() )
914 xCloseable
->removeCloseListener( m_pData
->m_xCloseListener
);
917 Reference
< frame::XFrame
> aXFrame
;
918 attachFrame( aXFrame
);
920 m_pData
->m_xListener
->disposing( aObject
);
921 SfxViewShell
*pShell
= m_pData
->m_pViewShell
;
922 m_pData
->m_pViewShell
= nullptr;
923 if (rFrame
.GetViewShell() == pShell
)
925 // Enter registrations only allowed if we are the owner!
926 if ( rFrame
.GetFrame().OwnsBindings_Impl() )
927 rFrame
.GetBindings().ENTERREGISTRATIONS();
928 rFrame
.GetFrame().SetFrameInterface_Impl( aXFrame
);
929 rFrame
.GetFrame().DoClose_Impl();
934 // SfxBaseController -> XComponent
937 void SAL_CALL
SfxBaseController::addEventListener( const Reference
< lang::XEventListener
>& aListener
)
939 m_pData
->m_aListenerContainer
.addInterface( cppu::UnoType
<lang::XEventListener
>::get(), aListener
);
943 // SfxBaseController -> XComponent
946 void SAL_CALL
SfxBaseController::removeEventListener( const Reference
< lang::XEventListener
>& aListener
)
948 m_pData
->m_aListenerContainer
.removeInterface( cppu::UnoType
<lang::XEventListener
>::get(), aListener
);
951 void SfxBaseController::ReleaseShell_Impl()
953 SolarMutexGuard aGuard
;
954 if ( !m_pData
->m_pViewShell
)
957 SfxObjectShell
* pDoc
= m_pData
->m_pViewShell
->GetObjectShell() ;
958 Reference
< frame::XModel
> xModel
= pDoc
->GetModel();
959 Reference
< util::XCloseable
> xCloseable( xModel
, uno::UNO_QUERY
);
962 xModel
->disconnectController( this );
963 if ( xCloseable
.is() )
964 xCloseable
->removeCloseListener( m_pData
->m_xCloseListener
);
966 m_pData
->m_pViewShell
= nullptr;
968 Reference
< frame::XFrame
> aXFrame
;
969 attachFrame( aXFrame
);
972 void SfxBaseController::CopyLokViewCallbackFromFrameCreator()
974 if (!m_pData
->m_pViewShell
)
976 SfxLokCallbackInterface
* pCallback
= nullptr;
977 if (m_pData
->m_xFrame
)
978 if (auto xCreator
= m_pData
->m_xFrame
->getCreator())
979 if (auto parentVS
= SfxViewShell::Get(xCreator
->getController()))
980 pCallback
= parentVS
->getLibreOfficeKitViewCallback();
981 m_pData
->m_pViewShell
->setLibreOfficeKitViewCallback(pCallback
);
984 SfxViewShell
* SfxBaseController::GetViewShell_Impl() const
986 return m_pData
->m_pViewShell
;
989 Reference
< task::XStatusIndicator
> SAL_CALL
SfxBaseController::getStatusIndicator( )
991 SolarMutexGuard aGuard
;
992 if ( m_pData
->m_pViewShell
&& !m_pData
->m_xIndicator
.is() )
993 m_pData
->m_xIndicator
= new SfxStatusIndicator( this, m_pData
->m_pViewShell
->GetViewFrame().GetFrame().GetWorkWindow_Impl() );
994 return m_pData
->m_xIndicator
;
997 void SAL_CALL
SfxBaseController::registerContextMenuInterceptor( const Reference
< ui::XContextMenuInterceptor
>& xInterceptor
)
1000 m_pData
->m_aInterceptorContainer
.addInterface( xInterceptor
);
1002 SolarMutexGuard aGuard
;
1003 if ( m_pData
->m_pViewShell
)
1004 m_pData
->m_pViewShell
->AddContextMenuInterceptor_Impl( xInterceptor
);
1007 void SAL_CALL
SfxBaseController::releaseContextMenuInterceptor( const Reference
< ui::XContextMenuInterceptor
>& xInterceptor
)
1010 m_pData
->m_aInterceptorContainer
.removeInterface( xInterceptor
);
1012 SolarMutexGuard aGuard
;
1013 if ( m_pData
->m_pViewShell
)
1014 m_pData
->m_pViewShell
->RemoveContextMenuInterceptor_Impl( xInterceptor
);
1017 void SAL_CALL
SfxBaseController::addKeyHandler( const Reference
< awt::XKeyHandler
>& xHandler
)
1019 SolarMutexGuard aGuard
;
1020 m_pData
->m_aUserInputInterception
.addKeyHandler( xHandler
);
1023 void SAL_CALL
SfxBaseController::removeKeyHandler( const Reference
< awt::XKeyHandler
>& xHandler
)
1025 SolarMutexGuard aGuard
;
1026 m_pData
->m_aUserInputInterception
.removeKeyHandler( xHandler
);
1029 void SAL_CALL
SfxBaseController::addMouseClickHandler( const Reference
< awt::XMouseClickHandler
>& xHandler
)
1031 SolarMutexGuard aGuard
;
1032 m_pData
->m_aUserInputInterception
.addMouseClickHandler( xHandler
);
1035 void SAL_CALL
SfxBaseController::removeMouseClickHandler( const Reference
< awt::XMouseClickHandler
>& xHandler
)
1037 SolarMutexGuard aGuard
;
1038 m_pData
->m_aUserInputInterception
.removeMouseClickHandler( xHandler
);
1041 uno::Sequence
< sal_Int16
> SAL_CALL
SfxBaseController::getSupportedCommandGroups()
1043 SolarMutexGuard aGuard
;
1045 std::vector
< sal_Int16
> aGroupList
;
1046 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
? m_pData
->m_pViewShell
->GetFrame() : nullptr;
1047 SfxSlotPool
* pSlotPool
= pViewFrame
? &SfxSlotPool::GetSlotPool(pViewFrame
) : &SFX_SLOTPOOL();
1048 const SfxSlotMode
nMode( SfxSlotMode::TOOLBOXCONFIG
|SfxSlotMode::ACCELCONFIG
|SfxSlotMode::MENUCONFIG
);
1050 // Select Group ( Group 0 is internal )
1051 for ( sal_uInt16 i
=0; i
<pSlotPool
->GetGroupCount(); i
++ )
1053 pSlotPool
->SeekGroup( i
);
1054 const SfxSlot
* pSfxSlot
= pSlotPool
->FirstSlot();
1057 if ( pSfxSlot
->GetMode() & nMode
)
1059 sal_Int16 nCommandGroup
= MapGroupIDToCommandGroup( pSfxSlot
->GetGroupId() );
1060 aGroupList
.push_back( nCommandGroup
);
1063 pSfxSlot
= pSlotPool
->NextSlot();
1067 return comphelper::containerToSequence( aGroupList
);
1070 uno::Sequence
< frame::DispatchInformation
> SAL_CALL
SfxBaseController::getConfigurableDispatchInformation( sal_Int16 nCmdGroup
)
1072 std::vector
< frame::DispatchInformation
> aCmdVector
;
1074 SolarMutexGuard aGuard
;
1075 if ( m_pData
->m_pViewShell
)
1077 const SfxSlotMode
nMode( SfxSlotMode::TOOLBOXCONFIG
|SfxSlotMode::ACCELCONFIG
|SfxSlotMode::MENUCONFIG
);
1079 SfxViewFrame
* pViewFrame( m_pData
->m_pViewShell
->GetFrame() );
1080 SfxSlotPool
* pSlotPool
1081 = pViewFrame
? &SfxSlotPool::GetSlotPool(pViewFrame
) : &SFX_SLOTPOOL();
1082 for ( sal_uInt16 i
=0; i
<pSlotPool
->GetGroupCount(); i
++ )
1084 pSlotPool
->SeekGroup( i
);
1085 const SfxSlot
* pSfxSlot
= pSlotPool
->FirstSlot();
1088 sal_Int16 nCommandGroup
= MapGroupIDToCommandGroup( pSfxSlot
->GetGroupId() );
1089 if ( nCommandGroup
== nCmdGroup
)
1093 if ( pSfxSlot
->GetMode() & nMode
)
1095 frame::DispatchInformation aCmdInfo
;
1096 aCmdInfo
.Command
= pSfxSlot
->GetCommand();
1097 aCmdInfo
.GroupId
= nCommandGroup
;
1098 aCmdVector
.push_back( aCmdInfo
);
1100 pSfxSlot
= pSlotPool
->NextSlot();
1107 return comphelper::containerToSequence( aCmdVector
);
1110 bool SfxBaseController::HandleEvent_Impl( NotifyEvent
const & rEvent
)
1112 return m_pData
->m_aUserInputInterception
.handleNotifyEvent( rEvent
);
1115 bool SfxBaseController::HasKeyListeners_Impl() const
1117 return m_pData
->m_aUserInputInterception
.hasKeyHandlers();
1120 bool SfxBaseController::HasMouseClickListeners_Impl() const
1122 return m_pData
->m_aUserInputInterception
.hasMouseClickListeners();
1125 void SfxBaseController::ConnectSfxFrame_Impl( const ConnectSfxFrame i_eConnect
)
1127 ENSURE_OR_THROW( m_pData
->m_pViewShell
, "not to be called without a view shell" );
1128 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1129 ENSURE_OR_THROW( pViewFrame
, "a view shell without a view frame is pretty pathological" );
1131 const bool bConnect
= ( i_eConnect
!= E_DISCONNECT
);
1133 // disable window and dispatcher
1134 pViewFrame
->Enable( bConnect
);
1135 pViewFrame
->GetDispatcher()->Lock( !bConnect
);
1139 if ( i_eConnect
== E_CONNECT
)
1141 if ( ( m_pData
->m_pViewShell
->GetObjectShell() != nullptr )
1142 && ( m_pData
->m_pViewShell
->GetObjectShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED
)
1145 SfxViewFrame
& rViewFrm
= m_pData
->m_pViewShell
->GetViewFrame();
1146 if ( !rViewFrm
.GetFrame().IsInPlace() )
1148 // for outplace embedded objects, we want the layout manager to keep the content window
1149 // size constant, if possible
1152 Reference
< beans::XPropertySet
> xFrameProps( m_pData
->m_xFrame
, uno::UNO_QUERY_THROW
);
1153 Reference
< beans::XPropertySet
> xLayouterProps(
1154 xFrameProps
->getPropertyValue(u
"LayoutManager"_ustr
), uno::UNO_QUERY_THROW
);
1155 xLayouterProps
->setPropertyValue(u
"PreserveContentSize"_ustr
, uno::Any( true ) );
1157 catch (const uno::Exception
&)
1159 DBG_UNHANDLED_EXCEPTION("sfx.view");
1165 // upon DISCONNECT, we did *not* pop the shells from the stack (this is done elsewhere), so upon
1166 // RECONNECT, we're not allowed to push them
1167 if ( i_eConnect
!= E_RECONNECT
)
1169 pViewFrame
->GetDispatcher()->Push( *m_pData
->m_pViewShell
);
1170 m_pData
->m_pViewShell
->PushSubShells_Impl();
1171 pViewFrame
->GetDispatcher()->Flush();
1174 vcl::Window
* pEditWin
= m_pData
->m_pViewShell
->GetWindow();
1178 if ( SfxViewFrame::Current() == pViewFrame
)
1179 pViewFrame
->GetDispatcher()->Update_Impl( true );
1181 vcl::Window
* pFrameWin
= &pViewFrame
->GetWindow();
1182 if ( pFrameWin
!= &pViewFrame
->GetFrame().GetWindow() )
1185 if ( i_eConnect
== E_CONNECT
)
1187 css::uno::Reference
<css::frame::XModel3
> xModel(getModel(), css::uno::UNO_QUERY_THROW
);
1188 const sal_Int16 nPluginMode
= ::comphelper::NamedValueCollection::getOrDefault( xModel
->getArgs2( { u
"PluginMode"_ustr
} ), u
"PluginMode", sal_Int16( 0 ) );
1189 const bool bHasPluginMode
= ( nPluginMode
!= 0 );
1191 SfxFrame
& rFrame
= pViewFrame
->GetFrame();
1192 SfxObjectShell
& rDoc
= *m_pData
->m_pViewShell
->GetObjectShell();
1193 if ( !rFrame
.IsMarkedHidden_Impl() )
1195 if ( rDoc
.IsHelpDocument() || ( nPluginMode
== 2 ) )
1196 pViewFrame
->GetDispatcher()->HideUI();
1198 pViewFrame
->GetDispatcher()->HideUI( false );
1200 if ( rFrame
.IsInPlace() )
1201 pViewFrame
->LockAdjustPosSizePixel();
1203 if ( nPluginMode
== 3 )
1204 rFrame
.GetWorkWindow_Impl()->SetInternalDockingAllowed( false );
1206 if ( !rFrame
.IsInPlace() )
1207 pViewFrame
->GetDispatcher()->Update_Impl();
1209 rFrame
.GetWindow().Show();
1210 if ( !rFrame
.IsInPlace() || ( nPluginMode
== 3 ) )
1211 pViewFrame
->MakeActive_Impl( rFrame
.GetFrameInterface()->isActive() );
1213 if ( rFrame
.IsInPlace() )
1215 pViewFrame
->UnlockAdjustPosSizePixel();
1216 // force resize for OLE server to fix layout problems of writer and math
1218 if ( nPluginMode
== 3 )
1219 pViewFrame
->Resize( true );
1224 DBG_ASSERT( !rFrame
.IsInPlace() && !bHasPluginMode
, "Special modes not compatible with hidden mode!" );
1225 rFrame
.GetWindow().Show();
1228 // UpdateTitle now, hidden TopFrames have otherwise no Name!
1229 pViewFrame
->UpdateTitle();
1231 if ( !rFrame
.IsInPlace() )
1232 pViewFrame
->Resize( true );
1234 ::comphelper::NamedValueCollection
aViewArgs(getCreationArguments());
1236 // sometimes we want to avoid adding to the recent documents
1237 bool bAllowPickListEntry
= aViewArgs
.getOrDefault(u
"PickListEntry"_ustr
, true);
1238 m_pData
->m_pViewShell
->GetObjectShell()->AvoidRecentDocs(!bAllowPickListEntry
);
1240 // if there's a JumpMark given, then, well, jump to it
1241 const OUString sJumpMark
= aViewArgs
.getOrDefault( u
"JumpMark"_ustr
, OUString() );
1242 const bool bHasJumpMark
= !sJumpMark
.isEmpty();
1243 OSL_ENSURE( ( !m_pData
->m_pViewShell
->GetObjectShell()->IsLoading() )
1244 || ( sJumpMark
.isEmpty() ),
1245 "SfxBaseController::ConnectSfxFrame_Impl: so this code wasn't dead?" );
1246 // Before CWS autorecovery, there was code which postponed jumping to the Mark to a later time
1247 // (SfxObjectShell::PositionView_Impl), but it seems this branch was never used, since this method
1248 // here is never called before the load process finished. At least not with a non-empty jump mark
1249 if ( !sJumpMark
.isEmpty() )
1250 m_pData
->m_pViewShell
->JumpToMark( sJumpMark
);
1252 // if no plugin mode and no jump mark was supplied, check whether the document itself can provide view data, and
1253 // if so, forward it to the view/shell.
1254 if ( !bHasPluginMode
&& !bHasJumpMark
)
1256 // Note that this might not be the ideal place here. Restoring view data should, IMO, be the
1257 // responsibility of the loader, not an implementation detail buried here deep within the controller's
1259 // What I think should be done to replace the below code:
1260 // - change SfxBaseController::restoreViewData to also accept a PropertyValue[] (it currently accepts
1261 // a string only), and forward it to its ViewShell's ReadUserDataSequence
1262 // - change the frame loader so that when a new document is loaded (as opposed to an existing
1263 // document being loaded into a new frame), the model's view data is examine the very same
1264 // way as below, and the proper view data is set via XController::restoreViewData
1265 // - extend SfxViewFrame::SwitchToViewShell_Impl. Currently, it cares for the case where a non-PrintPreview
1266 // view is exchanged, and sets the old view's data at the model. It should also care for the other
1267 // way, were the PrintPreview view is left: in this case, the new view should also be initialized
1268 // with the model's view data
1271 Reference
< XViewDataSupplier
> xViewDataSupplier( getModel(), UNO_QUERY_THROW
);
1272 Reference
< XIndexAccess
> xViewData( xViewDataSupplier
->getViewData() );
1274 // find the view data item whose ViewId matches the ID of the view we're just connecting to
1275 const SfxObjectFactory
& rDocFactory( rDoc
.GetFactory() );
1276 const sal_Int32 nCount
= xViewData
.is() ? xViewData
->getCount() : 0;
1277 sal_Int32 nViewDataIndex
= 0;
1278 for ( sal_Int32 i
=0; i
<nCount
; ++i
)
1280 const ::comphelper::NamedValueCollection
aViewData( xViewData
->getByIndex(i
) );
1281 OUString
sViewId( aViewData
.getOrDefault( u
"ViewId"_ustr
, OUString() ) );
1282 if ( sViewId
.isEmpty() )
1285 const SfxViewFactory
* pViewFactory
= rDocFactory
.GetViewFactoryByViewName( sViewId
);
1286 if ( pViewFactory
== nullptr )
1289 if ( pViewFactory
->GetOrdinal() == pViewFrame
->GetCurViewId() )
1295 if (nViewDataIndex
< nCount
|| !xViewData
.is())
1297 Sequence
< PropertyValue
> aViewData
;
1300 OSL_VERIFY(xViewData
->getByIndex(nViewDataIndex
) >>= aViewData
);
1302 if (aViewData
.hasElements() || !xViewData
.is())
1304 // Tolerate empty xViewData, ReadUserDataSequence() has side effects.
1305 m_pData
->m_pViewShell
->ReadUserDataSequence( aViewData
);
1309 catch (const Exception
&)
1311 DBG_UNHANDLED_EXCEPTION("sfx.view");
1317 // invalidate slot corresponding to the view shell
1318 const sal_uInt16 nViewNo
= m_pData
->m_pViewShell
->GetObjectShell()->GetFactory().GetViewNo_Impl( pViewFrame
->GetCurViewId(), USHRT_MAX
);
1319 DBG_ASSERT( nViewNo
!= USHRT_MAX
, "view shell id not found" );
1320 if ( nViewNo
!= USHRT_MAX
)
1321 pViewFrame
->GetBindings().Invalidate( nViewNo
+ SID_VIEWSHELL0
);
1324 void SfxBaseController::ShowInfoBars( )
1326 if ( !m_pData
->m_pViewShell
)
1329 // CMIS verifications
1330 Reference
< document::XCmisDocument
> xCmisDoc( m_pData
->m_pViewShell
->GetObjectShell()->GetModel(), uno::UNO_QUERY
);
1331 if ( !xCmisDoc
.is( ) || !xCmisDoc
->canCheckOut( ) )
1334 const uno::Sequence
< document::CmisProperty
> aCmisProperties
= xCmisDoc
->getCmisProperties( );
1336 if ( !(xCmisDoc
->isVersionable( ) && aCmisProperties
.hasElements( )) )
1339 // Loop over the CMIS Properties to find cmis:isVersionSeriesCheckedOut
1340 // and find if it is a Google Drive file.
1341 bool bIsGoogleFile
= false;
1342 bool bCheckedOut
= false;
1343 for ( const auto& rCmisProp
: aCmisProperties
)
1345 if ( rCmisProp
.Id
== "cmis:isVersionSeriesCheckedOut" ) {
1346 uno::Sequence
< sal_Bool
> bTmp
;
1347 rCmisProp
.Value
>>= bTmp
;
1348 bCheckedOut
= bTmp
[0];
1350 // if it is a Google Drive file, we don't need the checkout bar,
1351 // still need the checkout feature for the version dialog.
1352 if ( rCmisProp
.Name
== "title" )
1353 bIsGoogleFile
= true;
1356 if ( bCheckedOut
|| bIsGoogleFile
)
1359 // Get the Frame and show the InfoBar if not checked out
1360 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1361 auto pInfoBar
= pViewFrame
->AppendInfoBar(u
"checkout"_ustr
, u
""_ustr
, SfxResId(STR_NONCHECKEDOUT_DOCUMENT
),
1362 InfobarType::WARNING
);
1365 weld::Button
&rBtn
= pInfoBar
->addButton();
1366 rBtn
.set_label(SfxResId(STR_CHECKOUT
));
1367 rBtn
.connect_clicked(LINK(this, SfxBaseController
, CheckOutHandler
));
1371 IMPL_LINK_NOARG ( SfxBaseController
, CheckOutHandler
, weld::Button
&, void )
1373 if ( m_pData
->m_pViewShell
)
1374 m_pData
->m_pViewShell
->GetObjectShell()->CheckOut( );
1378 Reference
< frame::XTitle
> SfxBaseController::impl_getTitleHelper ()
1380 SolarMutexGuard aGuard
;
1382 if ( ! m_pData
->m_xTitleHelper
.is ())
1384 Reference
< frame::XModel
> xModel
= getModel ();
1385 Reference
< frame::XUntitledNumbers
> xUntitledProvider(xModel
, uno::UNO_QUERY
);
1387 m_pData
->m_xTitleHelper
= new ::framework::TitleHelper(::comphelper::getProcessComponentContext(),
1388 Reference
< frame::XController
>(this), xUntitledProvider
);
1391 return m_pData
->m_xTitleHelper
;
1396 OUString SAL_CALL
SfxBaseController::getTitle()
1398 return impl_getTitleHelper()->getTitle ();
1403 void SAL_CALL
SfxBaseController::setTitle(const OUString
& sTitle
)
1405 impl_getTitleHelper()->setTitle (sTitle
);
1409 // frame::XTitleChangeBroadcaster
1410 void SAL_CALL
SfxBaseController::addTitleChangeListener(const Reference
< frame::XTitleChangeListener
>& xListener
)
1412 Reference
< frame::XTitleChangeBroadcaster
> xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY
);
1413 if (xBroadcaster
.is ())
1414 xBroadcaster
->addTitleChangeListener (xListener
);
1418 // frame::XTitleChangeBroadcaster
1419 void SAL_CALL
SfxBaseController::removeTitleChangeListener(const Reference
< frame::XTitleChangeListener
>& xListener
)
1421 Reference
< frame::XTitleChangeBroadcaster
> xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY
);
1422 if (xBroadcaster
.is ())
1423 xBroadcaster
->removeTitleChangeListener (xListener
);
1426 void SfxBaseController::initialize( const css::uno::Sequence
< css::uno::Any
>& /*aArguments*/ )
1430 void SAL_CALL
SfxBaseController::appendInfobar(const OUString
& sId
, const OUString
& sPrimaryMessage
,
1431 const OUString
& sSecondaryMessage
,
1432 sal_Int32 aInfobarType
,
1433 const Sequence
<StringPair
>& actionButtons
,
1434 sal_Bool bShowCloseButton
)
1436 SolarMutexGuard aGuard
;
1438 if (aInfobarType
< static_cast<sal_Int32
>(InfobarType::INFO
)
1439 || aInfobarType
> static_cast<sal_Int32
>(InfobarType::DANGER
))
1440 throw lang::IllegalArgumentException("Undefined InfobarType: "
1441 + OUString::number(aInfobarType
),
1443 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1444 if (pViewFrame
->HasInfoBarWithID(sId
))
1445 throw lang::IllegalArgumentException("Infobar with ID '" + sId
+ "' already existing.",
1449 = pViewFrame
->AppendInfoBar(sId
, sPrimaryMessage
, sSecondaryMessage
,
1450 static_cast<InfobarType
>(aInfobarType
), bShowCloseButton
);
1452 throw uno::RuntimeException(u
"Could not create Infobar"_ustr
);
1454 for (const StringPair
& actionButton
: actionButtons
)
1456 if (actionButton
.First
.isEmpty() || actionButton
.Second
.isEmpty())
1458 weld::Button
& rBtn
= pInfoBar
->addButton(&actionButton
.Second
);
1459 rBtn
.set_label(actionButton
.First
);
1463 void SAL_CALL
SfxBaseController::updateInfobar(const OUString
& sId
, const OUString
& sPrimaryMessage
,
1464 const OUString
& sSecondaryMessage
,
1465 sal_Int32 aInfobarType
)
1467 SolarMutexGuard aGuard
;
1469 if (aInfobarType
< static_cast<sal_Int32
>(InfobarType::INFO
)
1470 || aInfobarType
> static_cast<sal_Int32
>(InfobarType::DANGER
))
1471 throw lang::IllegalArgumentException("Undefined InfobarType: "
1472 + OUString::number(aInfobarType
),
1474 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1475 if (!pViewFrame
->HasInfoBarWithID(sId
))
1476 throw css::container::NoSuchElementException("Infobar with ID '" + sId
+ "' not found.");
1478 pViewFrame
->UpdateInfoBar(sId
, sPrimaryMessage
, sSecondaryMessage
,
1479 static_cast<InfobarType
>(aInfobarType
));
1482 void SAL_CALL
SfxBaseController::removeInfobar(const OUString
& sId
)
1484 SolarMutexGuard aGuard
;
1486 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1487 if (!pViewFrame
->HasInfoBarWithID(sId
))
1488 throw css::container::NoSuchElementException("Infobar with ID '" + sId
+ "' not found.");
1489 pViewFrame
->RemoveInfoBar(sId
);
1492 sal_Bool SAL_CALL
SfxBaseController::hasInfobar(const OUString
& sId
)
1494 SolarMutexGuard aGuard
;
1495 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1496 return pViewFrame
->HasInfoBarWithID(sId
);
1499 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */