LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / view / sfxbasecontroller.cxx
blob12bb93c475d1f0fe7a9b706a84d9d3f7f9c58088
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 .
20 #include <time.h>
21 #include <sfx2/sfxbasecontroller.hxx>
22 #include <com/sun/star/awt/XWindowPeer.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/interfacecontainer2.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 <tools/diagnose_ex.h>
63 #include <comphelper/namedvaluecollection.hxx>
64 #include <comphelper/sequence.hxx>
65 #include <toolkit/helper/convert.hxx>
66 #include <framework/titlehelper.hxx>
67 #include <comphelper/processfactory.hxx>
68 #include <vcl/svapp.hxx>
69 #include <tools/svborder.hxx>
71 #include <sfx2/event.hxx>
72 #include <sfx2/viewfac.hxx>
73 #include <sfx2/strings.hrc>
74 #include <sfxbasecontroller_internal.hxx>
76 #include <unordered_map>
78 #include <com/sun/star/ui/XSidebarProvider.hpp>
79 #include <sidebar/UnoSidebar.hxx>
81 #define TIMEOUT_START_RESCHEDULE 10L /* 10th s */
83 using namespace ::com::sun::star;
84 using ::com::sun::star::uno::Reference;
85 using ::com::sun::star::uno::RuntimeException;
86 using ::com::sun::star::uno::UNO_QUERY_THROW;
87 using ::com::sun::star::lang::DisposedException;
88 using ::com::sun::star::awt::XWindow;
89 using ::com::sun::star::frame::XController;
90 using ::com::sun::star::frame::XDispatchProvider;
91 using ::com::sun::star::document::XViewDataSupplier;
92 using ::com::sun::star::container::XIndexAccess;
93 using ::com::sun::star::beans::PropertyValue;
94 using ::com::sun::star::beans::StringPair;
95 using ::com::sun::star::uno::Sequence;
96 using ::com::sun::star::uno::UNO_QUERY;
97 using ::com::sun::star::uno::Exception;
98 using ::com::sun::star::frame::XFrame;
99 using ::com::sun::star::frame::XFrameActionListener;
100 using ::com::sun::star::util::XCloseListener;
101 using ::com::sun::star::task::XStatusIndicator;
102 using ::com::sun::star::frame::XTitle;
103 using ::com::sun::star::ui::XSidebarProvider;
106 typedef std::unordered_map< SfxGroupId, sal_Int16 > GroupHashMap;
108 sal_Int16 MapGroupIDToCommandGroup( SfxGroupId nGroupID )
110 static GroupHashMap s_aHashMap
112 { SfxGroupId::Intern , frame::CommandGroup::INTERNAL },
113 { SfxGroupId::Application , frame::CommandGroup::APPLICATION },
114 { SfxGroupId::Document , frame::CommandGroup::DOCUMENT },
115 { SfxGroupId::View , frame::CommandGroup::VIEW },
116 { SfxGroupId::Edit , frame::CommandGroup::EDIT },
117 { SfxGroupId::Macro , frame::CommandGroup::MACRO },
118 { SfxGroupId::Options , frame::CommandGroup::OPTIONS },
119 { SfxGroupId::Math , frame::CommandGroup::MATH },
120 { SfxGroupId::Navigator , frame::CommandGroup::NAVIGATOR },
121 { SfxGroupId::Insert , frame::CommandGroup::INSERT },
122 { SfxGroupId::Format , frame::CommandGroup::FORMAT },
123 { SfxGroupId::Template , frame::CommandGroup::TEMPLATE },
124 { SfxGroupId::Text , frame::CommandGroup::TEXT },
125 { SfxGroupId::Frame , frame::CommandGroup::FRAME },
126 { SfxGroupId::Graphic , frame::CommandGroup::GRAPHIC },
127 { SfxGroupId::Table , frame::CommandGroup::TABLE },
128 { SfxGroupId::Enumeration , frame::CommandGroup::ENUMERATION },
129 { SfxGroupId::Data , frame::CommandGroup::DATA },
130 { SfxGroupId::Special , frame::CommandGroup::SPECIAL },
131 { SfxGroupId::Image , frame::CommandGroup::IMAGE },
132 { SfxGroupId::Chart , frame::CommandGroup::CHART },
133 { SfxGroupId::Explorer , frame::CommandGroup::EXPLORER },
134 { SfxGroupId::Connector , frame::CommandGroup::CONNECTOR },
135 { SfxGroupId::Modify , frame::CommandGroup::MODIFY },
136 { SfxGroupId::Drawing , frame::CommandGroup::DRAWING },
137 { SfxGroupId::Controls , frame::CommandGroup::CONTROLS },
141 GroupHashMap::const_iterator pIter = s_aHashMap.find( nGroupID );
142 if ( pIter != s_aHashMap.end() )
143 return pIter->second;
144 else
145 return frame::CommandGroup::INTERNAL;
148 sal_uInt32 Get10ThSec()
150 sal_uInt32 n10Ticks = 10 * static_cast<sal_uInt32>(clock());
151 return n10Ticks / CLOCKS_PER_SEC;
154 static sal_Int32 m_nInReschedule = 0; /// static counter for rescheduling
156 static void reschedule()
158 if ( m_nInReschedule == 0 )
160 ++m_nInReschedule;
161 Application::Reschedule();
162 --m_nInReschedule;
166 namespace {
168 class SfxStatusIndicator : public ::cppu::WeakImplHelper< task::XStatusIndicator, lang::XEventListener >
170 Reference < XController > xOwner;
171 Reference < task::XStatusIndicator > xProgress;
172 SfxWorkWindow* pWorkWindow;
173 tools::Long _nStartTime;
174 public:
175 SfxStatusIndicator(SfxBaseController* pController, SfxWorkWindow* pWork)
176 : xOwner( pController )
177 , pWorkWindow( pWork )
178 , _nStartTime(0)
180 osl_atomic_increment(&m_refCount);
181 Reference< lang::XComponent > xComponent = pController;
182 if (xComponent.is())
183 xComponent->addEventListener(this);
184 osl_atomic_decrement(&m_refCount);
187 virtual void SAL_CALL start(const OUString& aText, sal_Int32 nRange) override;
188 virtual void SAL_CALL end() override;
189 virtual void SAL_CALL setText(const OUString& aText) override;
190 virtual void SAL_CALL setValue(sal_Int32 nValue) override;
191 virtual void SAL_CALL reset() override;
193 virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
198 void SAL_CALL SfxStatusIndicator::start(const OUString& aText, sal_Int32 nRange)
200 SolarMutexGuard aGuard;
201 if ( xOwner.is() )
203 if ( !xProgress.is() )
204 xProgress = pWorkWindow->GetStatusIndicator();
206 if ( xProgress.is() )
207 xProgress->start( aText, nRange );
209 _nStartTime = Get10ThSec();
210 reschedule();
214 void SAL_CALL SfxStatusIndicator::end()
216 SolarMutexGuard aGuard;
217 if ( xOwner.is() )
219 if ( !xProgress.is() )
220 xProgress = pWorkWindow->GetStatusIndicator();
222 if ( xProgress.is() )
223 xProgress->end();
225 reschedule();
229 void SAL_CALL SfxStatusIndicator::setText(const OUString& aText)
231 SolarMutexGuard aGuard;
232 if ( xOwner.is() )
234 if ( !xProgress.is() )
235 xProgress = pWorkWindow->GetStatusIndicator();
237 if ( xProgress.is() )
238 xProgress->setText( aText );
240 reschedule();
244 void SAL_CALL SfxStatusIndicator::setValue( sal_Int32 nValue )
246 SolarMutexGuard aGuard;
247 if ( xOwner.is() )
249 if ( !xProgress.is() )
250 xProgress = pWorkWindow->GetStatusIndicator();
252 if ( xProgress.is() )
253 xProgress->setValue( nValue );
255 bool bReschedule = (( Get10ThSec() - _nStartTime ) > TIMEOUT_START_RESCHEDULE );
256 if ( bReschedule )
257 reschedule();
261 void SAL_CALL SfxStatusIndicator::reset()
263 SolarMutexGuard aGuard;
264 if ( xOwner.is() )
266 if ( !xProgress.is() )
267 xProgress = pWorkWindow->GetStatusIndicator();
269 if ( xProgress.is() )
270 xProgress->reset();
272 reschedule();
276 void SAL_CALL SfxStatusIndicator::disposing( const lang::EventObject& /*Source*/ )
278 SolarMutexGuard aGuard;
279 xOwner = nullptr;
280 xProgress.clear();
284 // declaration IMPL_SfxBaseController_ListenerHelper
286 namespace {
288 class IMPL_SfxBaseController_ListenerHelper : public ::cppu::WeakImplHelper< frame::XFrameActionListener >
290 public:
291 explicit IMPL_SfxBaseController_ListenerHelper( SfxBaseController* pController ) ;
293 virtual void SAL_CALL frameAction( const frame::FrameActionEvent& aEvent ) override ;
294 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) override ;
296 private:
298 SfxBaseController* m_pController ;
300 } ; // class IMPL_SfxBaseController_ListenerContainer
302 class IMPL_SfxBaseController_CloseListenerHelper : public ::cppu::WeakImplHelper< util::XCloseListener >
304 public:
305 explicit IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController* pController ) ;
307 virtual void SAL_CALL queryClosing( const lang::EventObject& aEvent, sal_Bool bDeliverOwnership ) override ;
308 virtual void SAL_CALL notifyClosing( const lang::EventObject& aEvent ) override ;
309 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) override ;
311 private:
313 SfxBaseController* m_pController;
315 } ; // class IMPL_SfxBaseController_ListenerContainer
319 IMPL_SfxBaseController_CloseListenerHelper::IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController* pController )
320 : m_pController ( pController )
324 void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::disposing( const lang::EventObject& /*aEvent*/ )
328 void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::queryClosing( const lang::EventObject& /*aEvent*/, sal_Bool /*bDeliverOwnership*/ )
330 SolarMutexGuard aGuard;
331 SfxViewShell* pShell = m_pController->GetViewShell_Impl();
332 if (pShell)
334 bool bCanClose = pShell->PrepareClose( false );
335 if ( !bCanClose )
337 throw util::CloseVetoException("Controller disagree ...",static_cast< ::cppu::OWeakObject*>(this));
342 void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::notifyClosing( const lang::EventObject& /*aEvent*/ )
347 // declaration IMPL_SfxBaseController_DataContainer
350 struct IMPL_SfxBaseController_DataContainer
352 Reference< XFrame > m_xFrame ;
353 Reference< XFrameActionListener > m_xListener ;
354 Reference< XCloseListener > m_xCloseListener ;
355 ::sfx2::UserInputInterception m_aUserInputInterception;
356 ::comphelper::OMultiTypeInterfaceContainerHelper2 m_aListenerContainer ;
357 ::comphelper::OInterfaceContainerHelper2 m_aInterceptorContainer ;
358 Reference< XStatusIndicator > m_xIndicator ;
359 SfxViewShell* m_pViewShell ;
360 SfxBaseController* m_pController ;
361 bool m_bDisposing ;
362 bool m_bSuspendState ;
363 Reference< XTitle > m_xTitleHelper ;
364 Sequence< PropertyValue > m_aCreationArgs ;
366 IMPL_SfxBaseController_DataContainer( ::osl::Mutex& aMutex ,
367 SfxViewShell* pViewShell ,
368 SfxBaseController* pController )
369 : m_xListener ( new IMPL_SfxBaseController_ListenerHelper( pController ) )
370 , m_xCloseListener ( new IMPL_SfxBaseController_CloseListenerHelper( pController ) )
371 , m_aUserInputInterception ( *pController, aMutex )
372 , m_aListenerContainer ( aMutex )
373 , m_aInterceptorContainer ( aMutex )
374 , m_pViewShell ( pViewShell )
375 , m_pController ( pController )
376 , m_bDisposing ( false )
377 , m_bSuspendState ( false )
381 } ; // struct IMPL_SfxBaseController_DataContainer
384 // IMPL_SfxBaseController_ListenerHelper constructor
387 IMPL_SfxBaseController_ListenerHelper::IMPL_SfxBaseController_ListenerHelper( SfxBaseController* pController )
388 : m_pController ( pController )
392 void SAL_CALL IMPL_SfxBaseController_ListenerHelper::frameAction( const frame::FrameActionEvent& aEvent )
394 SolarMutexGuard aGuard;
395 if (
396 ( m_pController != nullptr ) &&
397 ( aEvent.Frame == m_pController->getFrame() ) &&
398 ( m_pController->GetViewShell_Impl() && m_pController->GetViewShell_Impl()->GetWindow() != nullptr )
401 if ( aEvent.Action == frame::FrameAction_FRAME_UI_ACTIVATED )
403 if ( !m_pController->GetViewShell_Impl()->GetUIActiveIPClient_Impl() )
404 m_pController->GetViewShell_Impl()->GetViewFrame()->MakeActive_Impl( false );
406 else if ( aEvent.Action == frame::FrameAction_CONTEXT_CHANGED )
408 m_pController->GetViewShell_Impl()->GetViewFrame()->GetBindings().ContextChanged_Impl();
414 // IMPL_SfxBaseController_ListenerHelper -> XEventListener
417 void SAL_CALL IMPL_SfxBaseController_ListenerHelper::disposing( const lang::EventObject& /*aEvent*/ )
419 SolarMutexGuard aGuard;
420 if ( m_pController && m_pController->getFrame().is() )
421 m_pController->getFrame()->removeFrameActionListener( this ) ;
424 SfxBaseController::SfxBaseController( SfxViewShell* pViewShell )
425 : m_pData ( new IMPL_SfxBaseController_DataContainer( m_aMutex, pViewShell, this ))
427 m_pData->m_pViewShell->SetController( this );
431 // SfxBaseController -> destructor
434 SfxBaseController::~SfxBaseController()
439 // SfxBaseController -> XController2
442 Reference< XWindow > SAL_CALL SfxBaseController::getComponentWindow()
444 SolarMutexGuard aGuard;
445 if ( !m_pData->m_pViewShell )
446 throw DisposedException();
448 return Reference< XWindow >( GetViewFrame_Impl().GetFrame().GetWindow().GetComponentInterface(), UNO_QUERY_THROW );
451 OUString SAL_CALL SfxBaseController::getViewControllerName()
453 SolarMutexGuard aGuard;
454 if ( !m_pData->m_pViewShell || !m_pData->m_pViewShell->GetObjectShell() )
455 throw DisposedException();
457 const SfxObjectFactory& rDocFac( m_pData->m_pViewShell->GetObjectShell()->GetFactory() );
458 sal_uInt16 nViewNo = rDocFac.GetViewNo_Impl( GetViewFrame_Impl().GetCurViewId(), rDocFac.GetViewFactoryCount() );
459 OSL_ENSURE( nViewNo < rDocFac.GetViewFactoryCount(), "SfxBaseController::getViewControllerName: view ID not found in view factories!" );
461 OUString sViewName;
462 if ( nViewNo < rDocFac.GetViewFactoryCount() )
463 sViewName = rDocFac.GetViewFactory( nViewNo ).GetAPIViewName();
465 return sViewName;
468 Sequence< PropertyValue > SAL_CALL SfxBaseController::getCreationArguments()
470 SolarMutexGuard aGuard;
471 if ( !m_pData->m_pViewShell || !m_pData->m_pViewShell->GetObjectShell() )
472 throw DisposedException();
474 return m_pData->m_aCreationArgs;
477 void SfxBaseController::SetCreationArguments_Impl( const Sequence< PropertyValue >& i_rCreationArgs )
479 OSL_ENSURE( !m_pData->m_aCreationArgs.hasElements(), "SfxBaseController::SetCreationArguments_Impl: not intended to be called twice!" );
480 m_pData->m_aCreationArgs = i_rCreationArgs;
483 SfxViewFrame& SfxBaseController::GetViewFrame_Impl() const
485 ENSURE_OR_THROW( m_pData->m_pViewShell, "not to be called without a view shell" );
486 SfxViewFrame* pActFrame = m_pData->m_pViewShell->GetFrame();
487 ENSURE_OR_THROW( pActFrame, "a view shell without a view frame is pretty pathological" );
488 return *pActFrame;
492 Reference<XSidebarProvider> SAL_CALL SfxBaseController::getSidebar()
494 SfxViewFrame& rViewFrame = GetViewFrame_Impl();
495 SfxFrame& rFrame = rViewFrame.GetFrame();
497 Reference<XSidebarProvider> rSidebar = new SfxUnoSidebar(rFrame.GetFrameInterface());
498 return rSidebar;
502 // SfxBaseController -> XController2 -> XController
505 void SAL_CALL SfxBaseController::attachFrame( const Reference< frame::XFrame >& xFrame )
507 Reference< frame::XFrame > xTemp( getFrame() ) ;
509 SolarMutexGuard aGuard;
510 if ( xTemp.is() )
512 xTemp->removeFrameActionListener( m_pData->m_xListener ) ;
513 Reference < util::XCloseBroadcaster > xCloseable( xTemp, uno::UNO_QUERY );
514 if ( xCloseable.is() )
515 xCloseable->removeCloseListener( m_pData->m_xCloseListener );
518 m_pData->m_xFrame = xFrame;
520 if ( !xFrame.is() )
521 return;
523 xFrame->addFrameActionListener( m_pData->m_xListener ) ;
524 Reference < util::XCloseBroadcaster > xCloseable( xFrame, uno::UNO_QUERY );
525 if ( xCloseable.is() )
526 xCloseable->addCloseListener( m_pData->m_xCloseListener );
528 if ( m_pData->m_pViewShell )
530 ConnectSfxFrame_Impl( E_CONNECT );
531 ShowInfoBars( );
533 // attaching the frame to the controller is the last step in the creation of a new view, so notify this
534 SfxViewEventHint aHint( SfxEventHintId::ViewCreated, GlobalEventConfig::GetEventName( GlobalEventId::VIEWCREATED ), m_pData->m_pViewShell->GetObjectShell(), Reference< frame::XController2 >( this ) );
535 SfxGetpApp()->NotifyEvent( aHint );
540 // SfxBaseController -> XController
543 sal_Bool SAL_CALL SfxBaseController::attachModel( const Reference< frame::XModel >& xModel )
545 if ( m_pData->m_pViewShell && xModel.is() && xModel != m_pData->m_pViewShell->GetObjectShell()->GetModel() )
547 // don't allow to reattach a model!
548 OSL_FAIL("Can't reattach model!");
549 return false;
552 Reference < util::XCloseBroadcaster > xCloseable( xModel, uno::UNO_QUERY );
553 if ( xCloseable.is() )
554 xCloseable->addCloseListener( m_pData->m_xCloseListener );
555 return true;
559 // SfxBaseController -> XController
562 sal_Bool SAL_CALL SfxBaseController::suspend( sal_Bool bSuspend )
564 SolarMutexGuard aGuard;
566 // ignore duplicate calls, which doesn't change anything real
567 if (bool(bSuspend) == m_pData->m_bSuspendState)
568 return true;
570 if ( bSuspend )
572 if ( !m_pData->m_pViewShell )
574 m_pData->m_bSuspendState = true;
575 return true;
578 if ( !m_pData->m_pViewShell->PrepareClose() )
579 return false;
581 if ( getFrame().is() )
582 getFrame()->removeFrameActionListener( m_pData->m_xListener ) ;
583 SfxViewFrame* pActFrame = m_pData->m_pViewShell->GetFrame() ;
585 // More Views on the same document?
586 SfxObjectShell* pDocShell = m_pData->m_pViewShell->GetObjectShell() ;
587 bool bOther = false ;
589 for ( const SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell ); !bOther && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell ) )
590 bOther = (pFrame != pActFrame);
592 bool bRet = bOther || pDocShell->PrepareClose();
593 if ( bRet )
595 ConnectSfxFrame_Impl( E_DISCONNECT );
596 m_pData->m_bSuspendState = true;
599 return bRet;
601 else
603 if ( getFrame().is() )
604 getFrame()->addFrameActionListener( m_pData->m_xListener ) ;
606 if ( m_pData->m_pViewShell )
608 ConnectSfxFrame_Impl( E_RECONNECT );
611 m_pData->m_bSuspendState = false;
612 return true ;
617 // SfxBaseController -> XController
620 uno::Any SfxBaseController::getViewData()
622 uno::Any aAny;
623 SolarMutexGuard aGuard;
624 if ( m_pData->m_pViewShell )
626 OUString sData;
627 m_pData->m_pViewShell->WriteUserData( sData ) ;
628 aAny <<= sData ;
631 return aAny ;
635 // SfxBaseController -> XController
638 void SAL_CALL SfxBaseController::restoreViewData( const uno::Any& aValue )
640 SolarMutexGuard aGuard;
641 if ( m_pData->m_pViewShell )
643 OUString sData;
644 aValue >>= sData ;
645 m_pData->m_pViewShell->ReadUserData( sData ) ;
650 // SfxBaseController -> XController
653 Reference< frame::XFrame > SAL_CALL SfxBaseController::getFrame()
655 SolarMutexGuard aGuard;
656 return m_pData->m_xFrame;
660 // SfxBaseController -> XController
663 Reference< frame::XModel > SAL_CALL SfxBaseController::getModel()
665 SolarMutexGuard aGuard;
666 return m_pData->m_pViewShell ? m_pData->m_pViewShell->GetObjectShell()->GetModel() : Reference < frame::XModel > () ;
670 // SfxBaseController -> XDispatchProvider
673 Reference< frame::XDispatch > SAL_CALL SfxBaseController::queryDispatch( const util::URL& aURL ,
674 const OUString& sTargetFrameName,
675 sal_Int32 eSearchFlags )
677 SolarMutexGuard aGuard;
678 Reference< frame::XDispatch > xDisp;
679 if ( m_pData->m_pViewShell )
681 SfxViewFrame* pAct = m_pData->m_pViewShell->GetViewFrame() ;
682 if ( !m_pData->m_bDisposing )
684 if ( sTargetFrameName == "_beamer" )
686 SfxViewFrame *pFrame = m_pData->m_pViewShell->GetViewFrame();
687 if ( eSearchFlags & frame::FrameSearchFlag::CREATE )
688 pFrame->SetChildWindow( SID_BROWSER, true );
689 SfxChildWindow* pChildWin = pFrame->GetChildWindow( SID_BROWSER );
690 Reference < frame::XFrame > xFrame;
691 if ( pChildWin )
692 xFrame = pChildWin->GetFrame();
693 if ( xFrame.is() )
694 xFrame->setName( sTargetFrameName );
696 Reference< XDispatchProvider > xProv( xFrame, uno::UNO_QUERY );
697 if ( xProv.is() )
698 return xProv->queryDispatch( aURL, sTargetFrameName, frame::FrameSearchFlag::SELF );
701 if ( aURL.Protocol == ".uno:" )
703 OUString aMasterCommand = SfxOfficeDispatch::GetMasterUnoCommand( aURL );
704 bool bMasterCommand( !aMasterCommand.isEmpty() );
706 pAct = m_pData->m_pViewShell->GetViewFrame() ;
707 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct );
709 const SfxSlot* pSlot( nullptr );
710 if ( bMasterCommand )
711 pSlot = rSlotPool.GetUnoSlot( aMasterCommand );
712 else
713 pSlot = rSlotPool.GetUnoSlot( aURL.Path );
714 if ( pSlot && ( !pAct->GetFrame().IsInPlace() || !pSlot->IsMode( SfxSlotMode::CONTAINER ) ) )
715 return pAct->GetBindings().GetDispatch( pSlot, aURL, bMasterCommand );
716 else
718 // try to find parent SfxViewFrame
719 Reference< frame::XFrame > xParentFrame;
720 Reference< frame::XFrame > xOwnFrame = pAct->GetFrame().GetFrameInterface();
721 if ( xOwnFrame.is() )
722 xParentFrame = xOwnFrame->getCreator();
724 if ( xParentFrame.is() )
726 // TODO/LATER: in future probably SfxViewFrame hierarchy should be the same as XFrame hierarchy
727 // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame();
729 // search the related SfxViewFrame
730 SfxViewFrame* pParentFrame = nullptr;
731 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst();
732 pFrame;
733 pFrame = SfxViewFrame::GetNext( *pFrame ) )
735 if ( pFrame->GetFrame().GetFrameInterface() == xParentFrame )
737 pParentFrame = pFrame;
738 break;
742 if ( pParentFrame )
744 SfxSlotPool& rFrameSlotPool = SfxSlotPool::GetSlotPool( pParentFrame );
745 const SfxSlot* pSlot2( nullptr );
746 if ( bMasterCommand )
747 pSlot2 = rFrameSlotPool.GetUnoSlot( aMasterCommand );
748 else
749 pSlot2 = rFrameSlotPool.GetUnoSlot( aURL.Path );
751 if ( pSlot2 )
752 return pParentFrame->GetBindings().GetDispatch( pSlot2, aURL, bMasterCommand );
757 else if ( aURL.Protocol == "slot:" )
759 sal_uInt16 nId = static_cast<sal_uInt16>(aURL.Path.toInt32());
761 pAct = m_pData->m_pViewShell->GetViewFrame() ;
762 if (nId >= SID_VERB_START && nId <= SID_VERB_END)
764 const SfxSlot* pSlot = m_pData->m_pViewShell->GetVerbSlot_Impl(nId);
765 if ( pSlot )
766 return pAct->GetBindings().GetDispatch( pSlot, aURL, false );
769 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct );
770 const SfxSlot* pSlot = rSlotPool.GetSlot( nId );
771 if ( pSlot && ( !pAct->GetFrame().IsInPlace() || !pSlot->IsMode( SfxSlotMode::CONTAINER ) ) )
772 return pAct->GetBindings().GetDispatch( pSlot, aURL, false );
773 else
775 // try to find parent SfxViewFrame
776 Reference< frame::XFrame > xParentFrame;
777 Reference< frame::XFrame > xOwnFrame = pAct->GetFrame().GetFrameInterface();
778 if ( xOwnFrame.is() )
779 xParentFrame = xOwnFrame->getCreator();
781 if ( xParentFrame.is() )
783 // TODO/LATER: in future probably SfxViewFrame hierarchy should be the same as XFrame hierarchy
784 // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame();
786 // search the related SfxViewFrame
787 SfxViewFrame* pParentFrame = nullptr;
788 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst();
789 pFrame;
790 pFrame = SfxViewFrame::GetNext( *pFrame ) )
792 if ( pFrame->GetFrame().GetFrameInterface() == xParentFrame )
794 pParentFrame = pFrame;
795 break;
799 if ( pParentFrame )
801 SfxSlotPool& rSlotPool2 = SfxSlotPool::GetSlotPool( pParentFrame );
802 const SfxSlot* pSlot2 = rSlotPool2.GetUnoSlot( aURL.Path );
803 if ( pSlot2 )
804 return pParentFrame->GetBindings().GetDispatch( pSlot2, aURL, false );
809 else if( sTargetFrameName == "_self" || sTargetFrameName.isEmpty() )
811 // check for already loaded URL ... but with additional jumpmark!
812 Reference< frame::XModel > xModel = getModel();
813 if( xModel.is() && !aURL.Mark.isEmpty() )
815 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct );
816 const SfxSlot* pSlot = rSlotPool.GetSlot( SID_JUMPTOMARK );
817 if( !aURL.Main.isEmpty() && aURL.Main == xModel->getURL() && pSlot )
818 return Reference< frame::XDispatch >( new SfxOfficeDispatch( pAct->GetBindings(), pAct->GetDispatcher(), pSlot, aURL) );
824 return xDisp;
828 // SfxBaseController -> XDispatchProvider
831 uno::Sequence< Reference< frame::XDispatch > > SAL_CALL SfxBaseController::queryDispatches( const uno::Sequence< frame::DispatchDescriptor >& seqDescripts )
833 // Create return list - which must have same size then the given descriptor
834 // It's not allowed to pack it!
835 sal_Int32 nCount = seqDescripts.getLength();
836 uno::Sequence< Reference< frame::XDispatch > > lDispatcher( nCount );
838 std::transform(seqDescripts.begin(), seqDescripts.end(), lDispatcher.getArray(),
839 [this](const frame::DispatchDescriptor& rDesc) -> Reference< frame::XDispatch > {
840 return queryDispatch(rDesc.FeatureURL, rDesc.FrameName, rDesc.SearchFlags); });
842 return lDispatcher;
846 // SfxBaseController -> XControllerBorder
849 frame::BorderWidths SAL_CALL SfxBaseController::getBorder()
851 frame::BorderWidths aResult;
853 SolarMutexGuard aGuard;
854 if ( m_pData->m_pViewShell )
856 SvBorder aBorder = m_pData->m_pViewShell->GetBorderPixel();
857 aResult.Left = aBorder.Left();
858 aResult.Top = aBorder.Top();
859 aResult.Right = aBorder.Right();
860 aResult.Bottom = aBorder.Bottom();
863 return aResult;
866 void SAL_CALL SfxBaseController::addBorderResizeListener( const Reference< frame::XBorderResizeListener >& xListener )
868 m_pData->m_aListenerContainer.addInterface( cppu::UnoType<frame::XBorderResizeListener>::get(),
869 xListener );
872 void SAL_CALL SfxBaseController::removeBorderResizeListener( const Reference< frame::XBorderResizeListener >& xListener )
874 m_pData->m_aListenerContainer.removeInterface( cppu::UnoType<frame::XBorderResizeListener>::get(),
875 xListener );
878 awt::Rectangle SAL_CALL SfxBaseController::queryBorderedArea( const awt::Rectangle& aPreliminaryRectangle )
880 SolarMutexGuard aGuard;
881 if ( m_pData->m_pViewShell )
883 tools::Rectangle aTmpRect = VCLRectangle( aPreliminaryRectangle );
884 m_pData->m_pViewShell->QueryObjAreaPixel( aTmpRect );
885 return AWTRectangle( aTmpRect );
888 return aPreliminaryRectangle;
891 void SfxBaseController::BorderWidthsChanged_Impl()
893 ::comphelper::OInterfaceContainerHelper2* pContainer = m_pData->m_aListenerContainer.getContainer(
894 cppu::UnoType<frame::XBorderResizeListener>::get());
895 if ( !pContainer )
896 return;
898 frame::BorderWidths aBWidths = getBorder();
899 Reference< uno::XInterface > xThis( static_cast< ::cppu::OWeakObject* >(this), uno::UNO_QUERY );
901 ::comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
902 while (pIterator.hasMoreElements())
906 static_cast<frame::XBorderResizeListener*>(pIterator.next())->borderWidthsChanged( xThis, aBWidths );
908 catch (const RuntimeException&)
910 pIterator.remove();
916 // SfxBaseController -> XComponent
919 void SAL_CALL SfxBaseController::dispose()
921 SolarMutexGuard aGuard;
922 Reference< XController > xKeepAlive( this );
923 m_pData->m_bDisposing = true ;
925 lang::EventObject aEventObject;
926 aEventObject.Source = *this ;
927 m_pData->m_aListenerContainer.disposeAndClear( aEventObject ) ;
929 if ( m_pData->m_pController && m_pData->m_pController->getFrame().is() )
930 m_pData->m_pController->getFrame()->removeFrameActionListener( m_pData->m_xListener ) ;
932 if ( !m_pData->m_pViewShell )
933 return;
935 SfxViewFrame* pFrame = m_pData->m_pViewShell->GetViewFrame() ;
936 if ( pFrame && pFrame->GetViewShell() == m_pData->m_pViewShell )
937 pFrame->GetFrame().SetIsClosing_Impl();
938 m_pData->m_pViewShell->DisconnectAllClients();
940 if ( !pFrame )
941 return;
943 lang::EventObject aObject;
944 aObject.Source = *this ;
946 SfxObjectShell* pDoc = pFrame->GetObjectShell() ;
947 SfxViewFrame *pView = SfxViewFrame::GetFirst(pDoc);
948 while( pView )
950 // if there is another ViewFrame or currently the ViewShell in my ViewFrame is switched (PagePreview)
951 if ( pView != pFrame || pView->GetViewShell() != m_pData->m_pViewShell )
952 break;
953 pView = SfxViewFrame::GetNext( *pView, pDoc );
956 SfxGetpApp()->NotifyEvent( SfxViewEventHint(SfxEventHintId::CloseView, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEVIEW ), pDoc, Reference< frame::XController2 >( this ) ) );
957 if ( !pView )
958 SfxGetpApp()->NotifyEvent( SfxEventHint(SfxEventHintId::CloseDoc, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC ), pDoc) );
960 Reference< frame::XModel > xModel = pDoc->GetModel();
961 Reference < util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
962 if ( xModel.is() )
964 xModel->disconnectController( this );
965 if ( xCloseable.is() )
966 xCloseable->removeCloseListener( m_pData->m_xCloseListener );
969 Reference < frame::XFrame > aXFrame;
970 attachFrame( aXFrame );
972 m_pData->m_xListener->disposing( aObject );
973 SfxViewShell *pShell = m_pData->m_pViewShell;
974 m_pData->m_pViewShell = nullptr;
975 if ( pFrame->GetViewShell() == pShell )
977 // Enter registrations only allowed if we are the owner!
978 if ( pFrame->GetFrame().OwnsBindings_Impl() )
979 pFrame->GetBindings().ENTERREGISTRATIONS();
980 pFrame->GetFrame().SetFrameInterface_Impl( aXFrame );
981 pFrame->GetFrame().DoClose_Impl();
986 // SfxBaseController -> XComponent
989 void SAL_CALL SfxBaseController::addEventListener( const Reference< lang::XEventListener >& aListener )
991 m_pData->m_aListenerContainer.addInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
995 // SfxBaseController -> XComponent
998 void SAL_CALL SfxBaseController::removeEventListener( const Reference< lang::XEventListener >& aListener )
1000 m_pData->m_aListenerContainer.removeInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
1003 void SfxBaseController::ReleaseShell_Impl()
1005 SolarMutexGuard aGuard;
1006 if ( !m_pData->m_pViewShell )
1007 return;
1009 SfxObjectShell* pDoc = m_pData->m_pViewShell->GetObjectShell() ;
1010 Reference< frame::XModel > xModel = pDoc->GetModel();
1011 Reference < util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
1012 if ( xModel.is() )
1014 xModel->disconnectController( this );
1015 if ( xCloseable.is() )
1016 xCloseable->removeCloseListener( m_pData->m_xCloseListener );
1018 m_pData->m_pViewShell = nullptr;
1020 Reference < frame::XFrame > aXFrame;
1021 attachFrame( aXFrame );
1024 void SfxBaseController::CopyLokViewCallbackFromFrameCreator()
1026 if (!m_pData->m_pViewShell)
1027 return;
1028 SfxLokCallbackInterface* pCallback = nullptr;
1029 if (m_pData->m_xFrame)
1030 if (auto xCreator = m_pData->m_xFrame->getCreator())
1031 if (auto parentVS = SfxViewShell::Get(xCreator->getController()))
1032 pCallback = parentVS->getLibreOfficeKitViewCallback();
1033 m_pData->m_pViewShell->setLibreOfficeKitViewCallback(pCallback);
1036 SfxViewShell* SfxBaseController::GetViewShell_Impl() const
1038 return m_pData->m_pViewShell;
1041 Reference< task::XStatusIndicator > SAL_CALL SfxBaseController::getStatusIndicator( )
1043 SolarMutexGuard aGuard;
1044 if ( m_pData->m_pViewShell && !m_pData->m_xIndicator.is() )
1045 m_pData->m_xIndicator = new SfxStatusIndicator( this, m_pData->m_pViewShell->GetViewFrame()->GetFrame().GetWorkWindow_Impl() );
1046 return m_pData->m_xIndicator;
1049 void SAL_CALL SfxBaseController::registerContextMenuInterceptor( const Reference< ui::XContextMenuInterceptor >& xInterceptor )
1052 m_pData->m_aInterceptorContainer.addInterface( xInterceptor );
1054 SolarMutexGuard aGuard;
1055 if ( m_pData->m_pViewShell )
1056 m_pData->m_pViewShell->AddContextMenuInterceptor_Impl( xInterceptor );
1059 void SAL_CALL SfxBaseController::releaseContextMenuInterceptor( const Reference< ui::XContextMenuInterceptor >& xInterceptor )
1062 m_pData->m_aInterceptorContainer.removeInterface( xInterceptor );
1064 SolarMutexGuard aGuard;
1065 if ( m_pData->m_pViewShell )
1066 m_pData->m_pViewShell->RemoveContextMenuInterceptor_Impl( xInterceptor );
1069 void SAL_CALL SfxBaseController::addKeyHandler( const Reference< awt::XKeyHandler >& xHandler )
1071 SolarMutexGuard aGuard;
1072 m_pData->m_aUserInputInterception.addKeyHandler( xHandler );
1075 void SAL_CALL SfxBaseController::removeKeyHandler( const Reference< awt::XKeyHandler >& xHandler )
1077 SolarMutexGuard aGuard;
1078 m_pData->m_aUserInputInterception.removeKeyHandler( xHandler );
1081 void SAL_CALL SfxBaseController::addMouseClickHandler( const Reference< awt::XMouseClickHandler >& xHandler )
1083 SolarMutexGuard aGuard;
1084 m_pData->m_aUserInputInterception.addMouseClickHandler( xHandler );
1087 void SAL_CALL SfxBaseController::removeMouseClickHandler( const Reference< awt::XMouseClickHandler >& xHandler )
1089 SolarMutexGuard aGuard;
1090 m_pData->m_aUserInputInterception.removeMouseClickHandler( xHandler );
1093 uno::Sequence< sal_Int16 > SAL_CALL SfxBaseController::getSupportedCommandGroups()
1095 SolarMutexGuard aGuard;
1097 std::vector< sal_Int16 > aGroupList;
1098 SfxViewFrame* pViewFrame = m_pData->m_pViewShell ? m_pData->m_pViewShell->GetFrame() : nullptr;
1099 SfxSlotPool* pSlotPool = pViewFrame ? &SfxSlotPool::GetSlotPool(pViewFrame) : &SFX_SLOTPOOL();
1100 const SfxSlotMode nMode( SfxSlotMode::TOOLBOXCONFIG|SfxSlotMode::ACCELCONFIG|SfxSlotMode::MENUCONFIG );
1102 // Select Group ( Group 0 is internal )
1103 for ( sal_uInt16 i=0; i<pSlotPool->GetGroupCount(); i++ )
1105 pSlotPool->SeekGroup( i );
1106 const SfxSlot* pSfxSlot = pSlotPool->FirstSlot();
1107 while ( pSfxSlot )
1109 if ( pSfxSlot->GetMode() & nMode )
1111 sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() );
1112 aGroupList.push_back( nCommandGroup );
1113 break;
1115 pSfxSlot = pSlotPool->NextSlot();
1119 return comphelper::containerToSequence( aGroupList );
1122 uno::Sequence< frame::DispatchInformation > SAL_CALL SfxBaseController::getConfigurableDispatchInformation( sal_Int16 nCmdGroup )
1124 std::vector< frame::DispatchInformation > aCmdVector;
1126 SolarMutexGuard aGuard;
1127 if ( m_pData->m_pViewShell )
1129 const SfxSlotMode nMode( SfxSlotMode::TOOLBOXCONFIG|SfxSlotMode::ACCELCONFIG|SfxSlotMode::MENUCONFIG );
1131 SfxViewFrame* pViewFrame( m_pData->m_pViewShell->GetFrame() );
1132 SfxSlotPool* pSlotPool
1133 = pViewFrame ? &SfxSlotPool::GetSlotPool(pViewFrame) : &SFX_SLOTPOOL();
1134 for ( sal_uInt16 i=0; i<pSlotPool->GetGroupCount(); i++ )
1136 pSlotPool->SeekGroup( i );
1137 const SfxSlot* pSfxSlot = pSlotPool->FirstSlot();
1138 if ( pSfxSlot )
1140 sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() );
1141 if ( nCommandGroup == nCmdGroup )
1143 while ( pSfxSlot )
1145 if ( pSfxSlot->GetMode() & nMode )
1147 frame::DispatchInformation aCmdInfo;
1148 aCmdInfo.Command = ".uno:" + OUString::createFromAscii( pSfxSlot->GetUnoName() );
1149 aCmdInfo.GroupId = nCommandGroup;
1150 aCmdVector.push_back( aCmdInfo );
1152 pSfxSlot = pSlotPool->NextSlot();
1159 return comphelper::containerToSequence( aCmdVector );
1162 bool SfxBaseController::HandleEvent_Impl( NotifyEvent const & rEvent )
1164 return m_pData->m_aUserInputInterception.handleNotifyEvent( rEvent );
1167 bool SfxBaseController::HasKeyListeners_Impl() const
1169 return m_pData->m_aUserInputInterception.hasKeyHandlers();
1172 bool SfxBaseController::HasMouseClickListeners_Impl() const
1174 return m_pData->m_aUserInputInterception.hasMouseClickListeners();
1177 void SfxBaseController::ConnectSfxFrame_Impl( const ConnectSfxFrame i_eConnect )
1179 ENSURE_OR_THROW( m_pData->m_pViewShell, "not to be called without a view shell" );
1180 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1181 ENSURE_OR_THROW( pViewFrame, "a view shell without a view frame is pretty pathological" );
1183 const bool bConnect = ( i_eConnect != E_DISCONNECT );
1185 // disable window and dispatcher
1186 pViewFrame->Enable( bConnect );
1187 pViewFrame->GetDispatcher()->Lock( !bConnect );
1189 if ( bConnect )
1191 if ( i_eConnect == E_CONNECT )
1193 if ( ( m_pData->m_pViewShell->GetObjectShell() != nullptr )
1194 && ( m_pData->m_pViewShell->GetObjectShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1197 SfxViewFrame* pViewFrm = m_pData->m_pViewShell->GetViewFrame();
1198 if ( !pViewFrm->GetFrame().IsInPlace() )
1200 // for outplace embedded objects, we want the layout manager to keep the content window
1201 // size constant, if possible
1204 Reference< beans::XPropertySet > xFrameProps( m_pData->m_xFrame, uno::UNO_QUERY_THROW );
1205 Reference< beans::XPropertySet > xLayouterProps(
1206 xFrameProps->getPropertyValue("LayoutManager"), uno::UNO_QUERY_THROW );
1207 xLayouterProps->setPropertyValue("PreserveContentSize", uno::makeAny( true ) );
1209 catch (const uno::Exception&)
1211 DBG_UNHANDLED_EXCEPTION("sfx.view");
1217 // upon DISCONNECT, we did *not* pop the shells from the stack (this is done elsewhere), so upon
1218 // RECONNECT, we're not allowed to push them
1219 if ( i_eConnect != E_RECONNECT )
1221 pViewFrame->GetDispatcher()->Push( *m_pData->m_pViewShell );
1222 m_pData->m_pViewShell->PushSubShells_Impl();
1223 pViewFrame->GetDispatcher()->Flush();
1226 vcl::Window* pEditWin = m_pData->m_pViewShell->GetWindow();
1227 if ( pEditWin )
1228 pEditWin->Show();
1230 if ( SfxViewFrame::Current() == pViewFrame )
1231 pViewFrame->GetDispatcher()->Update_Impl( true );
1233 vcl::Window* pFrameWin = &pViewFrame->GetWindow();
1234 if ( pFrameWin != &pViewFrame->GetFrame().GetWindow() )
1235 pFrameWin->Show();
1237 if ( i_eConnect == E_CONNECT )
1239 css::uno::Reference<css::frame::XModel3> xModel(getModel(), css::uno::UNO_QUERY_THROW);
1240 ::comphelper::NamedValueCollection aDocumentArgs( xModel->getArgs2( { "PluginMode" } ) );
1242 const sal_Int16 nPluginMode = aDocumentArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) );
1243 const bool bHasPluginMode = ( nPluginMode != 0 );
1245 SfxFrame& rFrame = pViewFrame->GetFrame();
1246 SfxObjectShell& rDoc = *m_pData->m_pViewShell->GetObjectShell();
1247 if ( !rFrame.IsMarkedHidden_Impl() )
1249 if ( rDoc.IsHelpDocument() || ( nPluginMode == 2 ) )
1250 pViewFrame->GetDispatcher()->HideUI();
1251 else
1252 pViewFrame->GetDispatcher()->HideUI( false );
1254 if ( rFrame.IsInPlace() )
1255 pViewFrame->LockAdjustPosSizePixel();
1257 if ( nPluginMode == 3 )
1258 rFrame.GetWorkWindow_Impl()->SetInternalDockingAllowed( false );
1260 if ( !rFrame.IsInPlace() )
1261 pViewFrame->GetDispatcher()->Update_Impl();
1262 pViewFrame->Show();
1263 rFrame.GetWindow().Show();
1264 if ( !rFrame.IsInPlace() || ( nPluginMode == 3 ) )
1265 pViewFrame->MakeActive_Impl( rFrame.GetFrameInterface()->isActive() );
1267 if ( rFrame.IsInPlace() )
1269 pViewFrame->UnlockAdjustPosSizePixel();
1270 // force resize for OLE server to fix layout problems of writer and math
1271 // see i53651
1272 if ( nPluginMode == 3 )
1273 pViewFrame->Resize( true );
1276 else
1278 DBG_ASSERT( !rFrame.IsInPlace() && !bHasPluginMode, "Special modes not compatible with hidden mode!" );
1279 rFrame.GetWindow().Show();
1282 // UpdateTitle now, hidden TopFrames have otherwise no Name!
1283 pViewFrame->UpdateTitle();
1285 if ( !rFrame.IsInPlace() )
1286 pViewFrame->Resize( true );
1288 ::comphelper::NamedValueCollection aViewArgs(getCreationArguments());
1290 // sometimes we want to avoid adding to the recent documents
1291 bool bAllowPickListEntry = aViewArgs.getOrDefault("PickListEntry", true);
1292 m_pData->m_pViewShell->GetObjectShell()->AvoidRecentDocs(!bAllowPickListEntry);
1294 // if there's a JumpMark given, then, well, jump to it
1295 const OUString sJumpMark = aViewArgs.getOrDefault( "JumpMark", OUString() );
1296 const bool bHasJumpMark = !sJumpMark.isEmpty();
1297 OSL_ENSURE( ( !m_pData->m_pViewShell->GetObjectShell()->IsLoading() )
1298 || ( sJumpMark.isEmpty() ),
1299 "SfxBaseController::ConnectSfxFrame_Impl: so this code wasn't dead?" );
1300 // Before CWS autorecovery, there was code which postponed jumping to the Mark to a later time
1301 // (SfxObjectShell::PositionView_Impl), but it seems this branch was never used, since this method
1302 // here is never called before the load process finished. At least not with a non-empty jump mark
1303 if ( !sJumpMark.isEmpty() )
1304 m_pData->m_pViewShell->JumpToMark( sJumpMark );
1306 // if no plugin mode and no jump mark was supplied, check whether the document itself can provide view data, and
1307 // if so, forward it to the view/shell.
1308 if ( !bHasPluginMode && !bHasJumpMark )
1310 // Note that this might not be the ideal place here. Restoring view data should, IMO, be the
1311 // responsibility of the loader, not an implementation detail buried here deep within the controller's
1312 // implementation.
1313 // What I think should be done to replace the below code:
1314 // - change SfxBaseController::restoreViewData to also accept a PropertyValue[] (it currently accepts
1315 // a string only), and forward it to its ViewShell's ReadUserDataSequence
1316 // - change the frame loader so that when a new document is loaded (as opposed to an existing
1317 // document being loaded into a new frame), the model's view data is examine the very same
1318 // way as below, and the proper view data is set via XController::restoreViewData
1319 // - extend SfxViewFrame::SwitchToViewShell_Impl. Currently, it cares for the case where a non-PrintPreview
1320 // view is exchanged, and sets the old view's data at the model. It should also care for the other
1321 // way, were the PrintPreview view is left: in this case, the new view should also be initialized
1322 // with the model's view data
1325 Reference< XViewDataSupplier > xViewDataSupplier( getModel(), UNO_QUERY_THROW );
1326 Reference< XIndexAccess > xViewData( xViewDataSupplier->getViewData() );
1328 // find the view data item whose ViewId matches the ID of the view we're just connecting to
1329 const SfxObjectFactory& rDocFactory( rDoc.GetFactory() );
1330 const sal_Int32 nCount = xViewData.is() ? xViewData->getCount() : 0;
1331 sal_Int32 nViewDataIndex = 0;
1332 for ( sal_Int32 i=0; i<nCount; ++i )
1334 const ::comphelper::NamedValueCollection aViewData( xViewData->getByIndex(i) );
1335 OUString sViewId( aViewData.getOrDefault( "ViewId", OUString() ) );
1336 if ( sViewId.isEmpty() )
1337 continue;
1339 const SfxViewFactory* pViewFactory = rDocFactory.GetViewFactoryByViewName( sViewId );
1340 if ( pViewFactory == nullptr )
1341 continue;
1343 if ( pViewFactory->GetOrdinal() == pViewFrame->GetCurViewId() )
1345 nViewDataIndex = i;
1346 break;
1349 if (nViewDataIndex < nCount || !xViewData.is())
1351 Sequence< PropertyValue > aViewData;
1352 if (xViewData.is())
1354 OSL_VERIFY(xViewData->getByIndex(nViewDataIndex) >>= aViewData);
1356 if (aViewData.hasElements() || !xViewData.is())
1358 // Tolerate empty xViewData, ReadUserDataSequence() has side effects.
1359 m_pData->m_pViewShell->ReadUserDataSequence( aViewData );
1363 catch (const Exception&)
1365 DBG_UNHANDLED_EXCEPTION("sfx.view");
1371 // invalidate slot corresponding to the view shell
1372 const sal_uInt16 nViewNo = m_pData->m_pViewShell->GetObjectShell()->GetFactory().GetViewNo_Impl( pViewFrame->GetCurViewId(), USHRT_MAX );
1373 DBG_ASSERT( nViewNo != USHRT_MAX, "view shell id not found" );
1374 if ( nViewNo != USHRT_MAX )
1375 pViewFrame->GetBindings().Invalidate( nViewNo + SID_VIEWSHELL0 );
1378 void SfxBaseController::ShowInfoBars( )
1380 if ( !m_pData->m_pViewShell )
1381 return;
1383 // CMIS verifications
1384 Reference< document::XCmisDocument > xCmisDoc( m_pData->m_pViewShell->GetObjectShell()->GetModel(), uno::UNO_QUERY );
1385 if ( !xCmisDoc.is( ) || !xCmisDoc->canCheckOut( ) )
1386 return;
1388 const uno::Sequence< document::CmisProperty> aCmisProperties = xCmisDoc->getCmisProperties( );
1390 if ( !(xCmisDoc->isVersionable( ) && aCmisProperties.hasElements( )) )
1391 return;
1393 // Loop over the CMIS Properties to find cmis:isVersionSeriesCheckedOut
1394 // and find if it is a Google Drive file.
1395 bool bIsGoogleFile = false;
1396 bool bCheckedOut = false;
1397 for ( const auto& rCmisProp : aCmisProperties )
1399 if ( rCmisProp.Id == "cmis:isVersionSeriesCheckedOut" ) {
1400 uno::Sequence< sal_Bool > bTmp;
1401 rCmisProp.Value >>= bTmp;
1402 bCheckedOut = bTmp[0];
1404 // if it is a Google Drive file, we don't need the checkout bar,
1405 // still need the checkout feature for the version dialog.
1406 if ( rCmisProp.Name == "title" )
1407 bIsGoogleFile = true;
1410 if ( bCheckedOut || bIsGoogleFile )
1411 return;
1413 // Get the Frame and show the InfoBar if not checked out
1414 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1415 auto pInfoBar = pViewFrame->AppendInfoBar("checkout", "", SfxResId(STR_NONCHECKEDOUT_DOCUMENT),
1416 InfobarType::WARNING);
1417 if (pInfoBar)
1419 weld::Button &rBtn = pInfoBar->addButton();
1420 rBtn.set_label(SfxResId(STR_CHECKOUT));
1421 rBtn.connect_clicked(LINK(this, SfxBaseController, CheckOutHandler));
1425 IMPL_LINK_NOARG ( SfxBaseController, CheckOutHandler, weld::Button&, void )
1427 if ( m_pData->m_pViewShell )
1428 m_pData->m_pViewShell->GetObjectShell()->CheckOut( );
1432 Reference< frame::XTitle > SfxBaseController::impl_getTitleHelper ()
1434 SolarMutexGuard aGuard;
1436 if ( ! m_pData->m_xTitleHelper.is ())
1438 Reference< frame::XModel > xModel = getModel ();
1439 Reference< frame::XUntitledNumbers > xUntitledProvider(xModel , uno::UNO_QUERY );
1441 m_pData->m_xTitleHelper = new ::framework::TitleHelper(::comphelper::getProcessComponentContext(),
1442 Reference< frame::XController >(this), xUntitledProvider);
1445 return m_pData->m_xTitleHelper;
1449 // frame::XTitle
1450 OUString SAL_CALL SfxBaseController::getTitle()
1452 return impl_getTitleHelper()->getTitle ();
1456 // frame::XTitle
1457 void SAL_CALL SfxBaseController::setTitle(const OUString& sTitle)
1459 impl_getTitleHelper()->setTitle (sTitle);
1463 // frame::XTitleChangeBroadcaster
1464 void SAL_CALL SfxBaseController::addTitleChangeListener(const Reference< frame::XTitleChangeListener >& xListener)
1466 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY);
1467 if (xBroadcaster.is ())
1468 xBroadcaster->addTitleChangeListener (xListener);
1472 // frame::XTitleChangeBroadcaster
1473 void SAL_CALL SfxBaseController::removeTitleChangeListener(const Reference< frame::XTitleChangeListener >& xListener)
1475 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY);
1476 if (xBroadcaster.is ())
1477 xBroadcaster->removeTitleChangeListener (xListener);
1480 void SfxBaseController::initialize( const css::uno::Sequence< css::uno::Any >& /*aArguments*/ )
1484 void SAL_CALL SfxBaseController::appendInfobar(const OUString& sId, const OUString& sPrimaryMessage,
1485 const OUString& sSecondaryMessage,
1486 sal_Int32 aInfobarType,
1487 const Sequence<StringPair>& actionButtons,
1488 sal_Bool bShowCloseButton)
1490 SolarMutexGuard aGuard;
1492 if (aInfobarType < static_cast<sal_Int32>(InfobarType::INFO)
1493 || aInfobarType > static_cast<sal_Int32>(InfobarType::DANGER))
1494 throw lang::IllegalArgumentException("Undefined InfobarType: "
1495 + OUString::number(aInfobarType),
1496 static_cast<::cppu::OWeakObject*>(this), 0);
1497 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1498 if (pViewFrame->HasInfoBarWithID(sId))
1499 throw lang::IllegalArgumentException("Infobar with ID '" + sId + "' already existing.",
1500 static_cast<::cppu::OWeakObject*>(this), 0);
1502 auto pInfoBar
1503 = pViewFrame->AppendInfoBar(sId, sPrimaryMessage, sSecondaryMessage,
1504 static_cast<InfobarType>(aInfobarType), bShowCloseButton);
1505 if (!pInfoBar)
1506 throw uno::RuntimeException("Could not create Infobar");
1508 auto vActionButtons = comphelper::sequenceToContainer<std::vector<StringPair>>(actionButtons);
1509 for (auto& actionButton : vActionButtons)
1511 if (actionButton.First.isEmpty() || actionButton.Second.isEmpty())
1512 continue;
1513 weld::Button& rBtn = pInfoBar->addButton(&actionButton.Second);
1514 rBtn.set_label(actionButton.First);
1518 void SAL_CALL SfxBaseController::updateInfobar(const OUString& sId, const OUString& sPrimaryMessage,
1519 const OUString& sSecondaryMessage,
1520 sal_Int32 aInfobarType)
1522 SolarMutexGuard aGuard;
1524 if (aInfobarType < static_cast<sal_Int32>(InfobarType::INFO)
1525 || aInfobarType > static_cast<sal_Int32>(InfobarType::DANGER))
1526 throw lang::IllegalArgumentException("Undefined InfobarType: "
1527 + OUString::number(aInfobarType),
1528 static_cast<::cppu::OWeakObject*>(this), 0);
1529 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1530 if (!pViewFrame->HasInfoBarWithID(sId))
1531 throw css::container::NoSuchElementException("Infobar with ID '" + sId + "' not found.");
1533 pViewFrame->UpdateInfoBar(sId, sPrimaryMessage, sSecondaryMessage,
1534 static_cast<InfobarType>(aInfobarType));
1537 void SAL_CALL SfxBaseController::removeInfobar(const OUString& sId)
1539 SolarMutexGuard aGuard;
1541 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1542 if (!pViewFrame->HasInfoBarWithID(sId))
1543 throw css::container::NoSuchElementException("Infobar with ID '" + sId + "' not found.");
1544 pViewFrame->RemoveInfoBar(sId);
1547 sal_Bool SAL_CALL SfxBaseController::hasInfobar(const OUString& sId)
1549 SolarMutexGuard aGuard;
1550 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1551 return pViewFrame->HasInfoBarWithID(sId);
1554 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */