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 .
20 #include <config_feature_desktop.h>
21 #include <sal/log.hxx>
22 #include <tools/debug.hxx>
24 #include <sfx2/app.hxx>
25 #include <sfx2/frame.hxx>
26 #include <basic/sberrors.hxx>
28 #include <svl/svdde.hxx>
29 #include <unotools/configmgr.hxx>
30 #include <com/sun/star/frame/XFrame.hpp>
31 #include <comphelper/lok.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <com/sun/star/uri/UriReferenceFactory.hpp>
34 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
35 #include <basic/basmgr.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/weld.hxx>
38 #include <sfx2/sfxhelp.hxx>
39 #include <sfx2/progress.hxx>
40 #include <sfx2/objsh.hxx>
41 #include <sfx2/dispatch.hxx>
42 #include <sfx2/viewsh.hxx>
43 #include <sfx2/viewfrm.hxx>
44 #include <appdata.hxx>
45 #include <sfx2/module.hxx>
46 #include <sfx2/event.hxx>
47 #include <workwin.hxx>
48 #include <sfx2/sidebar/Theme.hxx>
49 #include <sfx2/tbxctrl.hxx>
50 #include <sfx2/sfxdlg.hxx>
51 #include <sfx2/stbitem.hxx>
52 #include <sfx2/dockwin.hxx>
53 #include <sidebar/ControllerFactory.hxx>
55 #include <officecfg/Office/Common.hxx>
56 #include <unotools/viewoptions.hxx>
57 #include <rtl/strbuf.hxx>
59 #include <framework/sfxhelperfunctions.hxx>
60 #include <fwkhelper.hxx>
62 #include "getbasctlfunction.hxx"
64 using namespace ::com::sun::star
;
66 static SfxApplication
* g_pSfxApplication
= nullptr;
68 #if HAVE_FEATURE_XMLHELP
69 static SfxHelp
* pSfxHelp
= nullptr;
72 SfxApplication
* SfxApplication::Get()
74 return g_pSfxApplication
;
77 void SfxApplication::SetModule(SfxToolsModule nSharedLib
, std::unique_ptr
<SfxModule
> pModule
)
79 assert(g_pSfxApplication
!= nullptr);
81 g_pSfxApplication
->pImpl
->aModules
[nSharedLib
] = std::move(pModule
);
84 SfxModule
* SfxApplication::GetModule(SfxToolsModule nSharedLib
)
86 if (!g_pSfxApplication
) // It is possible GetModule is called before SfxApplication is initialised via GetOrCreate()
88 return g_pSfxApplication
->pImpl
->aModules
[nSharedLib
].get();
92 css::uno::Reference
<css::frame::XToolbarController
> SfxWeldToolBoxControllerFactory( const css::uno::Reference
< css::frame::XFrame
>& rFrame
, weld::Toolbar
* pToolbar
, weld::Builder
* pBuilder
, const OUString
& aCommandURL
)
94 SolarMutexGuard aGuard
;
96 return sfx2::sidebar::ControllerFactory::CreateToolBoxController(
97 *pToolbar
, *pBuilder
, aCommandURL
, rFrame
, rFrame
->getController(), false);
101 SfxApplication
* SfxApplication::GetOrCreate()
103 static osl::Mutex theApplicationMutex
;
106 ::osl::MutexGuard
aGuard(theApplicationMutex
);
107 if (!g_pSfxApplication
)
109 SAL_INFO( "sfx.appl", "SfxApplication::SetApp" );
111 g_pSfxApplication
= new SfxApplication
;
113 // at the moment a bug may occur when Initialize_Impl returns FALSE,
114 // but this is only temporary because all code that may cause such
115 // a fault will be moved outside the SFX
116 g_pSfxApplication
->Initialize_Impl();
118 ::framework::SetRefreshToolbars( RefreshToolbars
);
119 ::framework::SetToolBoxControllerCreator( SfxToolBoxControllerFactory
);
120 ::framework::SetWeldToolBoxControllerCreator( SfxWeldToolBoxControllerFactory
);
121 ::framework::SetStatusBarControllerCreator( SfxStatusBarControllerFactory
);
122 ::framework::SetDockingWindowCreator( SfxDockingWindowFactory
);
123 ::framework::SetIsDockingWindowVisible( IsDockingWindowVisible
);
124 #if HAVE_FEATURE_XMLHELP
125 Application::SetHelp( pSfxHelp
);
126 bool bHelpTip
= officecfg::Office::Common::Help::Tip::get();
127 bool bExtendedHelpTip
= officecfg::Office::Common::Help::ExtendedTip::get();
128 if (!utl::ConfigManager::IsFuzzing() && bHelpTip
)
129 Help::EnableQuickHelp();
131 Help::DisableQuickHelp();
132 if (!utl::ConfigManager::IsFuzzing() && bHelpTip
&& bExtendedHelpTip
)
133 Help::EnableBalloonHelp();
135 Help::DisableBalloonHelp();
138 return g_pSfxApplication
;
141 SfxApplication::SfxApplication()
142 : pImpl( new SfxAppData_Impl
)
144 SetName( "StarOffice" );
146 SAL_INFO( "sfx.appl", "{ initialize DDE" );
148 bool bOk
= InitializeDde();
153 OStringBuffer
aStr("No DDE-Service possible. Error: ");
154 if( GetDdeService() )
155 aStr
.append(static_cast<sal_Int32
>(GetDdeService()->GetError()));
158 SAL_WARN( "sfx.appl", aStr
.getStr() );
164 #if HAVE_FEATURE_XMLHELP
165 pSfxHelp
= new SfxHelp
;
168 #if HAVE_FEATURE_SCRIPTING
169 StarBASIC::SetGlobalErrorHdl( LINK( this, SfxApplication
, GlobalBasicErrorHdl_Impl
) );
172 SAL_INFO( "sfx.appl", "} initialize DDE" );
175 SfxApplication::~SfxApplication()
177 SAL_WARN_IF(GetObjectShells_Impl().size() != 0, "sfx.appl", "Memory leak: some object shells were not removed!");
179 Broadcast( SfxHint(SfxHintId::Dying
) );
181 for (auto &module
: pImpl
->aModules
) // Clear modules
184 #if HAVE_FEATURE_XMLHELP
186 Application::SetHelp();
189 if ( !pImpl
->bDowning
)
192 g_pSfxApplication
= nullptr;
196 const OUString
& SfxApplication::GetLastDir_Impl() const
200 Internal method by which the last set directory with the method
201 <SfxApplication::SetLastDir_Impl()> in SFX is returned.
203 This is usually the most recently addressed by the
204 SfxFileDialog directory.
207 <SfxApplication::SetLastDir_Impl()>
211 return pImpl
->aLastDir
;
214 void SfxApplication::SetLastDir_Impl
216 const OUString
& rNewDir
/* Complete directory path as a string */
221 Internal Method, by which a directory path is set that was last addressed
222 (eg by the SfxFileDialog).
225 <SfxApplication::GetLastDir_Impl()>
229 pImpl
->aLastDir
= rNewDir
;
233 void SfxApplication::ResetLastDir()
235 pImpl
->aLastDir
.clear();
239 SfxDispatcher
* SfxApplication::GetDispatcher_Impl()
241 return pImpl
->pViewFrame
? pImpl
->pViewFrame
->GetDispatcher() : &*pImpl
->pAppDispat
;
245 void SfxApplication::SetViewFrame_Impl( SfxViewFrame
*pFrame
)
247 if ( pFrame
!= pImpl
->pViewFrame
)
249 SfxViewFrame
*pOldFrame
= pImpl
->pViewFrame
;
251 // DocWinActivate : both frames belong to the same TopWindow
252 // TopWinActivate : both frames belong to different TopWindows
254 bool bTaskActivate
= pOldFrame
!= pFrame
;
259 NotifyEvent( SfxViewEventHint( SfxEventHintId::DeactivateDoc
, GlobalEventConfig::GetEventName(GlobalEventId::DEACTIVATEDOC
), pOldFrame
->GetObjectShell(), pOldFrame
->GetFrame().GetController() ) );
261 pOldFrame
->DoDeactivate( bTaskActivate
, pFrame
);
263 if( pOldFrame
->GetProgress() )
264 pOldFrame
->GetProgress()->Suspend();
267 pImpl
->pViewFrame
= pFrame
;
271 pFrame
->DoActivate( bTaskActivate
);
272 if ( bTaskActivate
&& pFrame
->GetObjectShell() )
274 pFrame
->GetObjectShell()->PostActivateEvent_Impl( pFrame
);
275 NotifyEvent(SfxViewEventHint(SfxEventHintId::ActivateDoc
, GlobalEventConfig::GetEventName(GlobalEventId::ACTIVATEDOC
), pFrame
->GetObjectShell(), pFrame
->GetFrame().GetController() ) );
278 SfxProgress
*pProgress
= pFrame
->GetProgress();
281 if( pProgress
->IsSuspended() )
284 pProgress
->SetState( pProgress
->GetState() );
287 if ( pImpl
->pViewFrame
->GetViewShell() )
289 SfxDispatcher
* pDisp
= pImpl
->pViewFrame
->GetDispatcher();
291 pDisp
->Update_Impl(true);
296 // even if the frame actually didn't change, ensure its document is forwarded
297 // to SfxObjectShell::SetCurrentComponent.
298 // Otherwise, the CurrentComponent might not be correct, in case it has meanwhile
299 // been reset to some other document, by some non-SFX component. #i49133#
300 if ( pFrame
&& pFrame
->GetViewShell() )
301 pFrame
->GetViewShell()->SetCurrentDocument();
304 void SfxApplication::SetProgress_Impl
306 SfxProgress
*pProgress
309 DBG_ASSERT( ( !pImpl
->pProgress
&& pProgress
) ||
310 ( pImpl
->pProgress
&& !pProgress
),
311 "Progress activation/deactivation mismatch" );
313 if ( pImpl
->pProgress
&& pProgress
)
315 pImpl
->pProgress
->Suspend();
316 delete pImpl
->pProgress
;
319 pImpl
->pProgress
= pProgress
;
323 sal_uInt16
SfxApplication::GetFreeIndex()
325 return pImpl
->aIndexBitSet
.GetFreeIndex()+1;
329 void SfxApplication::ReleaseIndex(sal_uInt16 i
)
331 pImpl
->aIndexBitSet
.ReleaseIndex(i
-1);
335 weld::Window
* SfxApplication::GetTopWindow() const
337 SfxWorkWindow
* pWork
= GetWorkWindow_Impl( SfxViewFrame::Current() );
340 vcl::Window
* pWindow
= pWork
->GetWindow();
343 return pWindow
->GetFrameWeld();
346 SfxTbxCtrlFactory
* SfxApplication::GetTbxCtrlFactory(const std::type_info
& rSlotType
, sal_uInt16 nSlotID
) const
348 // search for a factory with the given slot id
349 for (auto& rFactory
: pImpl
->maTbxCtrlFactories
)
350 if( rFactory
.nTypeId
== rSlotType
&& rFactory
.nSlotId
== nSlotID
)
353 // if no factory exists for the given slot id, see if we
354 // have a generic factory with the correct slot type and slot id == 0
355 for (auto& rFactory
: pImpl
->maTbxCtrlFactories
)
356 if( rFactory
.nTypeId
== rSlotType
&& rFactory
.nSlotId
== 0 )
362 SfxStbCtrlFactory
* SfxApplication::GetStbCtrlFactory(const std::type_info
& rSlotType
, sal_uInt16 nSlotID
) const
364 for (auto& rFactory
: pImpl
->maStbCtrlFactories
)
365 if ( rFactory
.nTypeId
== rSlotType
&&
366 ( rFactory
.nSlotId
== 0 || rFactory
.nSlotId
== nSlotID
) )
371 std::vector
<SfxViewFrame
*>& SfxApplication::GetViewFrames_Impl() const
373 return pImpl
->maViewFrames
;
376 std::vector
<SfxViewShell
*>& SfxApplication::GetViewShells_Impl() const
378 return pImpl
->maViewShells
;
381 std::vector
<SfxObjectShell
*>& SfxApplication::GetObjectShells_Impl() const
383 return pImpl
->maObjShells
;
386 void SfxApplication::Invalidate( sal_uInt16 nId
)
388 for( SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst(); pFrame
; pFrame
= SfxViewFrame::GetNext( *pFrame
) )
389 Invalidate_Impl( pFrame
->GetBindings(), nId
);
392 #if HAVE_FEATURE_SCRIPTING
394 #ifndef DISABLE_DYNLOADING
396 typedef long (*basicide_handle_basic_error
)(void const *);
397 typedef void (*basicide_macro_organizer
)(void *, sal_Int16
);
401 extern "C" long basicide_handle_basic_error(void const*);
402 extern "C" void basicide_macro_organizer(void*, sal_Int16
);
408 IMPL_STATIC_LINK( SfxApplication
, GlobalBasicErrorHdl_Impl
, StarBASIC
*, pStarBasic
, bool )
410 #if !HAVE_FEATURE_SCRIPTING
415 if (comphelper::LibreOfficeKit::isActive())
418 std::unique_ptr
<ErrorInfo
> pErrorInfo
= ErrorInfo::GetErrorInfo(StarBASIC::GetErrorCode());
419 if (ErrorStringFactory::CreateString(pErrorInfo
.get(), aError
))
421 const SfxViewFrame
* pViewFrame
= SfxViewFrame::Current();
422 std::shared_ptr
<weld::MessageDialog
> xBox
;
423 xBox
.reset(Application::CreateMessageDialog(
424 pViewFrame
->GetFrameWeld(),
425 VclMessageType::Error
,
429 xBox
->runAsync(xBox
, [](sal_Int32
/*nResult*/) {});
434 #ifndef DISABLE_DYNLOADING
435 basicide_handle_basic_error pSymbol
= reinterpret_cast<basicide_handle_basic_error
>(sfx2::getBasctlFunction("basicide_handle_basic_error"));
437 // call basicide_handle_basic_error in basctl
438 bool bRet
= pSymbol( pStarBasic
);
442 bool bRet
= basicide_handle_basic_error( pStarBasic
);
451 bool SfxApplication::IsXScriptURL( const OUString
& rScriptURL
)
455 #if !HAVE_FEATURE_SCRIPTING
458 css::uno::Reference
< css::uno::XComponentContext
> xContext
=
459 ::comphelper::getProcessComponentContext();
461 css::uno::Reference
< css::uri::XUriReferenceFactory
>
462 xFactory
= css::uri::UriReferenceFactory::create( xContext
);
466 css::uno::Reference
< css::uri::XVndSunStarScriptUrl
>
467 xUrl( xFactory
->parse( rScriptURL
), css::uno::UNO_QUERY
);
474 catch (const css::uno::RuntimeException
&)
476 // ignore, will just return FALSE
483 SfxApplication::ChooseScript(weld::Window
*pParent
)
487 #if HAVE_FEATURE_SCRIPTING
488 SfxAbstractDialogFactory
* pFact
= SfxAbstractDialogFactory::Create();
489 SAL_INFO( "sfx.appl", "create selector dialog");
491 const SfxViewFrame
* pViewFrame
= SfxViewFrame::Current();
492 const SfxFrame
* pFrame
= pViewFrame
? &pViewFrame
->GetFrame() : nullptr;
493 uno::Reference
< frame::XFrame
> xFrame( pFrame
? pFrame
->GetFrameInterface() : uno::Reference
< frame::XFrame
>() );
495 ScopedVclPtr
<AbstractScriptSelectorDialog
> pDlg(pFact
->CreateScriptSelectorDialog(pParent
, xFrame
));
497 SAL_INFO( "sfx.appl", "done, now exec it");
499 sal_uInt16 nRet
= pDlg
->Execute();
501 SAL_INFO( "sfx.appl", "has returned");
503 if ( nRet
== RET_OK
)
505 aScriptURL
= pDlg
->GetScriptURL();
513 void SfxApplication::MacroOrganizer(weld::Window
* pParent
, sal_Int16 nTabId
)
515 #if !HAVE_FEATURE_SCRIPTING
520 #ifndef DISABLE_DYNLOADING
521 basicide_macro_organizer pSymbol
= reinterpret_cast<basicide_macro_organizer
>(sfx2::getBasctlFunction("basicide_macro_organizer"));
523 // call basicide_macro_organizer in basctl
524 pSymbol(pParent
, nTabId
);
528 basicide_macro_organizer(pParent
, nTabId
);
535 ErrCode
SfxApplication::CallBasic( const OUString
& rCode
, BasicManager
* pMgr
, SbxArray
* pArgs
, SbxValue
* pRet
)
537 #if !HAVE_FEATURE_SCRIPTING
542 return ERRCODE_BASIC_CANNOT_LOAD
;
544 (void) ERRCODE_BASIC_CANNOT_LOAD
; // So that the !HAVE_FEATURE_SCRIPTING case isn't broken again by IWYU
545 return pMgr
->ExecuteMacro( rCode
, pArgs
, pRet
);
549 sfx2::sidebar::Theme
& SfxApplication::GetSidebarTheme()
551 if (!pImpl
->m_pSidebarTheme
.is())
553 pImpl
->m_pSidebarTheme
.set(new sfx2::sidebar::Theme
);
554 pImpl
->m_pSidebarTheme
->InitializeTheme();
556 return *pImpl
->m_pSidebarTheme
;
559 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */