734 lines
21 KiB
C++
734 lines
21 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <com/sun/star/embed/VerbDescriptor.hpp>
|
|
#include <com/sun/star/embed/VerbAttributes.hpp>
|
|
#include <officecfg/Office/Common.hxx>
|
|
#include <rtl/ustring.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <osl/diagnose.h>
|
|
#include <svl/itempool.hxx>
|
|
#include <svl/setitem.hxx>
|
|
#include <svl/voiditem.hxx>
|
|
#include <svl/undo.hxx>
|
|
#include <svtools/asynclink.hxx>
|
|
#include <unotools/configmgr.hxx>
|
|
#include <comphelper/lok.hxx>
|
|
#include <sfx2/shell.hxx>
|
|
#include <sfx2/bindings.hxx>
|
|
#include <sfx2/dispatch.hxx>
|
|
#include <sfx2/viewfrm.hxx>
|
|
#include <sfx2/objface.hxx>
|
|
#include <sfx2/objsh.hxx>
|
|
#include <sfx2/viewsh.hxx>
|
|
#include <sfx2/request.hxx>
|
|
#include <sfx2/sfxsids.hrc>
|
|
#include <statcach.hxx>
|
|
#include <sidebar/ContextChangeBroadcaster.hxx>
|
|
#include <com/sun/star/ui/dialogs/XSLTFilterDialog.hpp>
|
|
#include <tools/debug.hxx>
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
#include <desktop/crashreport.hxx>
|
|
|
|
using namespace com::sun::star;
|
|
|
|
struct SfxShell_Impl: public SfxBroadcaster
|
|
{
|
|
OUString aObjectName; // Name of Sbx-Objects
|
|
// Maps the Which() field to a pointer to a SfxPoolItem
|
|
std::map<sal_uInt16, std::unique_ptr<SfxPoolItem>>
|
|
m_Items; // Data exchange on Item level
|
|
SfxViewShell* pViewSh; // SfxViewShell if Shell is
|
|
// ViewFrame/ViewShell/SubShell list
|
|
SfxViewFrame* pFrame; // Frame, if <UI-active>
|
|
SfxRepeatTarget* pRepeatTarget; // SbxObjectRef xParent;
|
|
bool bActive;
|
|
SfxDisableFlags nDisableFlags;
|
|
std::unique_ptr<svtools::AsynchronLink> pExecuter;
|
|
std::unique_ptr<svtools::AsynchronLink> pUpdater;
|
|
std::vector<std::unique_ptr<SfxSlot> > aSlotArr;
|
|
|
|
css::uno::Sequence < css::embed::VerbDescriptor > aVerbList;
|
|
::sfx2::sidebar::ContextChangeBroadcaster maContextChangeBroadcaster;
|
|
|
|
SfxShell_Impl()
|
|
: pViewSh(nullptr)
|
|
, pFrame(nullptr)
|
|
, pRepeatTarget(nullptr)
|
|
, bActive(false)
|
|
, nDisableFlags(SfxDisableFlags::NONE)
|
|
{
|
|
}
|
|
|
|
virtual ~SfxShell_Impl() override { pExecuter.reset(); pUpdater.reset();}
|
|
};
|
|
|
|
|
|
void SfxShell::EmptyExecStub(SfxShell *, SfxRequest &)
|
|
{
|
|
}
|
|
|
|
void SfxShell::EmptyStateStub(SfxShell *, SfxItemSet &)
|
|
{
|
|
}
|
|
|
|
SfxShell::SfxShell()
|
|
: pImpl(new SfxShell_Impl),
|
|
pPool(nullptr),
|
|
pUndoMgr(nullptr)
|
|
{
|
|
}
|
|
|
|
SfxShell::SfxShell( SfxViewShell *pViewSh )
|
|
: pImpl(new SfxShell_Impl),
|
|
pPool(nullptr),
|
|
pUndoMgr(nullptr)
|
|
{
|
|
pImpl->pViewSh = pViewSh;
|
|
}
|
|
|
|
SfxShell::~SfxShell()
|
|
{
|
|
}
|
|
|
|
void SfxShell::SetName( const OUString &rName )
|
|
{
|
|
pImpl->aObjectName = rName;
|
|
}
|
|
|
|
const OUString& SfxShell::GetName() const
|
|
{
|
|
return pImpl->aObjectName;
|
|
}
|
|
|
|
SfxDispatcher* SfxShell::GetDispatcher() const
|
|
{
|
|
return pImpl->pFrame ? pImpl->pFrame->GetDispatcher() : nullptr;
|
|
}
|
|
|
|
SfxViewShell* SfxShell::GetViewShell() const
|
|
{
|
|
return pImpl->pViewSh;
|
|
}
|
|
|
|
SfxViewFrame* SfxShell::GetFrame() const
|
|
{
|
|
if ( pImpl->pFrame )
|
|
return pImpl->pFrame;
|
|
if ( pImpl->pViewSh )
|
|
return &pImpl->pViewSh->GetViewFrame();
|
|
return nullptr;
|
|
}
|
|
|
|
const SfxPoolItem* SfxShell::GetItem
|
|
(
|
|
sal_uInt16 nSlotId // Slot-Id of the querying <SfxPoolItem>s
|
|
) const
|
|
{
|
|
auto const it = pImpl->m_Items.find( nSlotId );
|
|
if (it != pImpl->m_Items.end())
|
|
return it->second.get();
|
|
return nullptr;
|
|
}
|
|
|
|
void SfxShell::PutItem
|
|
(
|
|
const SfxPoolItem& rItem /* Instance, of which a copy is created,
|
|
which is stored in the SfxShell in a list. */
|
|
)
|
|
{
|
|
DBG_ASSERT( !rItem.isSetItem(), "SetItems aren't allowed here" );
|
|
DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
|
|
"items with Which-Ids aren't allowed here" );
|
|
|
|
// MSC made a mess here of WNT/W95, beware of changes
|
|
SfxPoolItem *pItem = rItem.Clone();
|
|
SfxPoolItemHint aItemHint( pItem );
|
|
sal_uInt16 nWhich = rItem.Which();
|
|
|
|
auto const it = pImpl->m_Items.find(nWhich);
|
|
if (it != pImpl->m_Items.end())
|
|
{
|
|
// Replace Item
|
|
it->second = std::unique_ptr<SfxPoolItem>(pItem);
|
|
|
|
// if active, notify Bindings
|
|
SfxDispatcher *pDispat = GetDispatcher();
|
|
if ( pDispat )
|
|
{
|
|
SfxBindings* pBindings = pDispat->GetBindings();
|
|
pBindings->Broadcast( aItemHint );
|
|
sal_uInt16 nSlotId = nWhich; //pItem->GetSlotId();
|
|
SfxStateCache* pCache = pBindings->GetStateCache( nSlotId );
|
|
if ( pCache )
|
|
{
|
|
pCache->SetState( SfxItemState::DEFAULT, pItem, true );
|
|
pCache->SetCachedState( true );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
Broadcast( aItemHint );
|
|
pImpl->m_Items.insert(std::make_pair(nWhich, std::unique_ptr<SfxPoolItem>(pItem)));
|
|
}
|
|
}
|
|
|
|
SfxInterface* SfxShell::GetInterface() const
|
|
{
|
|
return GetStaticInterface();
|
|
}
|
|
|
|
SfxUndoManager* SfxShell::GetUndoManager()
|
|
{
|
|
return pUndoMgr;
|
|
}
|
|
|
|
void SfxShell::SetUndoManager( SfxUndoManager *pNewUndoMgr )
|
|
{
|
|
OSL_ENSURE( ( pUndoMgr == nullptr ) || ( pNewUndoMgr == nullptr ) || ( pUndoMgr == pNewUndoMgr ),
|
|
"SfxShell::SetUndoManager: exchanging one non-NULL manager with another non-NULL manager? Suspicious!" );
|
|
// there's at least one client of our UndoManager - the DocumentUndoManager at the SfxBaseModel - which
|
|
// caches the UndoManager, and registers itself as listener. If exchanging non-NULL UndoManagers is really
|
|
// a supported scenario (/me thinks it is not), then we would need to notify all such clients instances.
|
|
|
|
pUndoMgr = pNewUndoMgr;
|
|
if (pUndoMgr && !comphelper::IsFuzzing())
|
|
{
|
|
pUndoMgr->SetMaxUndoActionCount(
|
|
officecfg::Office::Common::Undo::Steps::get());
|
|
}
|
|
}
|
|
|
|
SfxRepeatTarget* SfxShell::GetRepeatTarget() const
|
|
{
|
|
return pImpl->pRepeatTarget;
|
|
}
|
|
|
|
void SfxShell::SetRepeatTarget( SfxRepeatTarget *pTarget )
|
|
{
|
|
pImpl->pRepeatTarget = pTarget;
|
|
}
|
|
|
|
void SfxShell::Invalidate
|
|
(
|
|
sal_uInt16 nId /* Invalidated Slot-Id or Which-Id.
|
|
If these are 0 (default), then all
|
|
by this Shell currently handled Slot-Ids are
|
|
invalidated. */
|
|
)
|
|
{
|
|
if ( !GetViewShell() )
|
|
{
|
|
OSL_FAIL( "wrong Invalidate method called!" );
|
|
return;
|
|
}
|
|
|
|
Invalidate_Impl( GetViewShell()->GetViewFrame().GetBindings(), nId );
|
|
}
|
|
|
|
void SfxShell::Invalidate_Impl( SfxBindings& rBindings, sal_uInt16 nId )
|
|
{
|
|
if ( nId == 0 )
|
|
{
|
|
rBindings.InvalidateShell( *this );
|
|
}
|
|
else
|
|
{
|
|
const SfxInterface *pIF = GetInterface();
|
|
do
|
|
{
|
|
const SfxSlot *pSlot = pIF->GetSlot(nId);
|
|
if ( pSlot )
|
|
{
|
|
// Invalidate the Slot itself
|
|
rBindings.Invalidate( pSlot->GetSlotId() );
|
|
return;
|
|
}
|
|
|
|
pIF = pIF->GetGenoType();
|
|
}
|
|
|
|
while ( pIF );
|
|
|
|
SAL_INFO( "sfx.control", "W3: invalidating slot-id unknown in shell" );
|
|
}
|
|
}
|
|
|
|
void SfxShell::HandleOpenXmlFilterSettings(SfxRequest & rReq)
|
|
{
|
|
try
|
|
{
|
|
uno::Reference < ui::dialogs::XExecutableDialog > xDialog = ui::dialogs::XSLTFilterDialog::create( ::comphelper::getProcessComponentContext() );
|
|
(void)xDialog->execute();
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
rReq.Ignore ();
|
|
}
|
|
|
|
void SfxShell::DoActivate_Impl( SfxViewFrame *pFrame, bool bMDI )
|
|
{
|
|
SfxObjectShell* pObjectShell = GetObjectShell();
|
|
if ( pObjectShell )
|
|
{
|
|
const OUString sActiveDocName = pObjectShell->GetTitle();
|
|
if( !pImpl->aObjectName.startsWith(sActiveDocName) )
|
|
{
|
|
CrashReporter::setActiveSfxObjectName(pImpl->aObjectName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CrashReporter::setActiveSfxObjectName(pImpl->aObjectName);
|
|
}
|
|
|
|
#ifdef DBG_UTIL
|
|
const SfxInterface *p_IF = GetInterface();
|
|
if ( !p_IF )
|
|
return;
|
|
#endif
|
|
SAL_INFO(
|
|
"sfx.control",
|
|
"SfxShell::DoActivate() " << this << " " << GetInterface()->GetClassName()
|
|
<< " bMDI " << (bMDI ? "MDI" : ""));
|
|
|
|
if ( bMDI )
|
|
{
|
|
// Remember Frame, in which it was activated
|
|
pImpl->pFrame = pFrame;
|
|
pImpl->bActive = true;
|
|
}
|
|
|
|
// Notify Subclass
|
|
Activate(bMDI);
|
|
}
|
|
|
|
void SfxShell::DoDeactivate_Impl( SfxViewFrame const *pFrame, bool bMDI )
|
|
{
|
|
#ifdef DBG_UTIL
|
|
const SfxInterface *p_IF = GetInterface();
|
|
if ( !p_IF )
|
|
return;
|
|
#endif
|
|
SAL_INFO(
|
|
"sfx.control",
|
|
"SfxShell::DoDeactivate()" << this << " " << GetInterface()->GetClassName()
|
|
<< " bMDI " << (bMDI ? "MDI" : ""));
|
|
|
|
// Only when it comes from a Frame
|
|
// (not when for instance by popping BASIC-IDE from AppDisp)
|
|
if ( bMDI && pImpl->pFrame == pFrame )
|
|
{
|
|
// deliver
|
|
pImpl->pFrame = nullptr;
|
|
pImpl->bActive = false;
|
|
}
|
|
|
|
// Notify Subclass
|
|
Deactivate(bMDI);
|
|
}
|
|
|
|
bool SfxShell::IsActive() const
|
|
{
|
|
return pImpl->bActive;
|
|
}
|
|
|
|
void SfxShell::Activate
|
|
(
|
|
bool /*bMDI*/ /* TRUE
|
|
the <SfxDispatcher>, on which the SfxShell is
|
|
located, is activated or the SfxShell instance
|
|
was pushed on an active SfxDispatcher.
|
|
(compare with SystemWindow::IsMDIActivate())
|
|
|
|
FALSE
|
|
the <SfxViewFrame>, on which SfxDispatcher
|
|
the SfxShell instance is located, was
|
|
activated. (for example by a closing dialog) */
|
|
)
|
|
{
|
|
BroadcastContextForActivation(true);
|
|
}
|
|
|
|
void SfxShell::Deactivate
|
|
(
|
|
bool /*bMDI*/ /* TRUE
|
|
the <SfxDispatcher>, on which the SfxShell is
|
|
located, is inactivated or the SfxShell instance
|
|
was popped on an active SfxDispatcher.
|
|
(compare with SystemWindow::IsMDIActivate())
|
|
|
|
FALSE
|
|
the <SfxViewFrame>, on which SfxDispatcher
|
|
the SfxShell instance is located, was
|
|
deactivated. (for example by a dialog) */
|
|
)
|
|
{
|
|
BroadcastContextForActivation(false);
|
|
}
|
|
|
|
bool SfxShell::CanExecuteSlot_Impl( const SfxSlot &rSlot )
|
|
{
|
|
// Get Slot status
|
|
SfxItemPool &rPool = GetPool();
|
|
const sal_uInt16 nId = rSlot.GetWhich( rPool );
|
|
SfxItemSet aSet(rPool, nId, nId);
|
|
SfxStateFunc pFunc = rSlot.GetStateFnc();
|
|
(*pFunc)( this, aSet );
|
|
return aSet.GetItemState(nId) != SfxItemState::DISABLED;
|
|
}
|
|
|
|
bool SfxShell::IsConditionalFastCall( const SfxRequest &rReq )
|
|
{
|
|
sal_uInt16 nId = rReq.GetSlot();
|
|
bool bRet = false;
|
|
|
|
if (nId == SID_UNDO || nId == SID_REDO)
|
|
{
|
|
const SfxItemSet* pArgs = rReq.GetArgs();
|
|
if (pArgs && pArgs->HasItem(SID_REPAIRPACKAGE))
|
|
bRet = true;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
static void ShellCall_Impl( void* pObj, void* pArg )
|
|
{
|
|
static_cast<SfxShell*>(pObj)->ExecuteSlot( *static_cast<SfxRequest*>(pArg) );
|
|
}
|
|
|
|
void SfxShell::ExecuteSlot( SfxRequest& rReq, bool bAsync )
|
|
{
|
|
if( !bAsync )
|
|
ExecuteSlot( rReq );
|
|
else
|
|
{
|
|
if( !pImpl->pExecuter )
|
|
pImpl->pExecuter.reset( new svtools::AsynchronLink(
|
|
Link<void*,void>( this, ShellCall_Impl ) ) );
|
|
pImpl->pExecuter->Call( new SfxRequest( rReq ) );
|
|
}
|
|
}
|
|
|
|
const SfxPoolItemHolder& SfxShell::ExecuteSlot
|
|
(
|
|
SfxRequest &rReq, // the relayed <SfxRequest>
|
|
const SfxInterface* pIF // default = 0 means get virtually
|
|
)
|
|
{
|
|
if ( !pIF )
|
|
pIF = GetInterface();
|
|
|
|
sal_uInt16 nSlot = rReq.GetSlot();
|
|
const SfxSlot* pSlot = nullptr;
|
|
if ( nSlot >= SID_VERB_START && nSlot <= SID_VERB_END )
|
|
pSlot = GetVerbSlot_Impl(nSlot);
|
|
if ( !pSlot )
|
|
pSlot = pIF->GetSlot(nSlot);
|
|
assert(pSlot && "slot not supported");
|
|
|
|
SfxExecFunc pFunc = pSlot->GetExecFnc();
|
|
if ( pFunc )
|
|
(*pFunc)( this, rReq );
|
|
|
|
return rReq.GetReturnValue();
|
|
}
|
|
|
|
SfxPoolItemHolder SfxShell::GetSlotState
|
|
(
|
|
sal_uInt16 nSlotId, // Slot-Id to the Slots in question
|
|
const SfxInterface* pIF, // default = 0 means get virtually
|
|
SfxItemSet* pStateSet // SfxItemSet of the Slot-State method
|
|
)
|
|
{
|
|
// Get Slot on the given Interface
|
|
if ( !pIF )
|
|
pIF = GetInterface();
|
|
SfxItemState eState(SfxItemState::DEFAULT);
|
|
bool bItemStateSet(false);
|
|
SfxItemPool &rPool = GetPool();
|
|
|
|
const SfxSlot* pSlot = nullptr;
|
|
if ( nSlotId >= SID_VERB_START && nSlotId <= SID_VERB_END )
|
|
pSlot = GetVerbSlot_Impl(nSlotId);
|
|
if ( !pSlot )
|
|
pSlot = pIF->GetSlot(nSlotId);
|
|
if ( pSlot )
|
|
// Map on Which-Id if possible
|
|
nSlotId = pSlot->GetWhich( rPool );
|
|
|
|
// Get Item and Item status
|
|
const SfxPoolItem *pItem = nullptr;
|
|
SfxItemSet aSet( rPool, nSlotId, nSlotId ); // else pItem dies too soon
|
|
if ( nullptr != pSlot )
|
|
{
|
|
// Call Status method
|
|
SfxStateFunc pFunc = pSlot->GetStateFnc();
|
|
if ( pFunc )
|
|
(*pFunc)( this, aSet );
|
|
eState = aSet.GetItemState( nSlotId, true, &pItem );
|
|
bItemStateSet = true;
|
|
|
|
// get default Item if possible
|
|
if ( eState == SfxItemState::DEFAULT )
|
|
{
|
|
if ( SfxItemPool::IsWhich(nSlotId) )
|
|
pItem = &rPool.GetUserOrPoolDefaultItem(nSlotId);
|
|
else
|
|
eState = SfxItemState::INVALID;
|
|
}
|
|
}
|
|
|
|
// Evaluate Item and item status and possibly maintain them in pStateSet
|
|
if ( !bItemStateSet || eState <= SfxItemState::DISABLED )
|
|
{
|
|
if ( pStateSet )
|
|
pStateSet->DisableItem(nSlotId);
|
|
return SfxPoolItemHolder();
|
|
}
|
|
|
|
if ( bItemStateSet && eState == SfxItemState::INVALID )
|
|
{
|
|
if ( pStateSet )
|
|
pStateSet->ClearItem(nSlotId);
|
|
return SfxPoolItemHolder(rPool, DISABLED_POOL_ITEM);
|
|
}
|
|
|
|
// bItemStateSet && eState >= SfxItemState::DEFAULT
|
|
if ( pStateSet && pStateSet->Put( *pItem ) )
|
|
{
|
|
return SfxPoolItemHolder(rPool, &pStateSet->Get(pItem->Which()));
|
|
}
|
|
|
|
return SfxPoolItemHolder(rPool, pItem);
|
|
}
|
|
|
|
static SFX_EXEC_STUB(SfxShell, VerbExec)
|
|
static void SfxStubSfxShellVerbState(SfxShell *, SfxItemSet& rSet)
|
|
{
|
|
SfxShell::VerbState( rSet );
|
|
}
|
|
|
|
void SfxShell::SetVerbs(const css::uno::Sequence < css::embed::VerbDescriptor >& aVerbs)
|
|
{
|
|
SfxViewShell *pViewSh = dynamic_cast<SfxViewShell*>( this );
|
|
|
|
DBG_ASSERT(pViewSh, "Only call SetVerbs at the ViewShell!");
|
|
if ( !pViewSh )
|
|
return;
|
|
|
|
// First make all Statecaches dirty, so that no-one no longer tries to use
|
|
// the Slots
|
|
{
|
|
SfxBindings *pBindings =
|
|
pViewSh->GetViewFrame().GetDispatcher()->GetBindings();
|
|
sal_uInt16 nCount = pImpl->aSlotArr.size();
|
|
for (sal_uInt16 n1=0; n1<nCount ; n1++)
|
|
{
|
|
sal_uInt16 nId = SID_VERB_START + n1;
|
|
pBindings->Invalidate(nId, false, true);
|
|
}
|
|
}
|
|
|
|
sal_uInt16 nr=0;
|
|
for (sal_Int32 n=0; n<aVerbs.getLength(); n++)
|
|
{
|
|
sal_uInt16 nSlotId = SID_VERB_START + nr++;
|
|
DBG_ASSERT(nSlotId <= SID_VERB_END, "Too many Verbs!");
|
|
if (nSlotId > SID_VERB_END)
|
|
break;
|
|
|
|
SfxSlot* pNewSlot = new SfxSlot{
|
|
nSlotId, SfxGroupId::NONE,
|
|
// Verb slots must be executed asynchronously, so that they can be
|
|
// destroyed while executing.
|
|
SfxSlotMode::ASYNCHRON | SfxSlotMode::CONTAINER,
|
|
0, 0,
|
|
SFX_STUB_PTR(SfxShell, VerbExec), SFX_STUB_PTR(SfxShell, VerbState),
|
|
nullptr, // HACK(SFX_TYPE(SfxVoidItem)) ???
|
|
nullptr, nullptr, 0, SfxDisableFlags::NONE, u""_ustr};
|
|
|
|
if (!pImpl->aSlotArr.empty())
|
|
{
|
|
SfxSlot& rSlot = *pImpl->aSlotArr[0];
|
|
pNewSlot->pNextSlot = rSlot.pNextSlot;
|
|
rSlot.pNextSlot = pNewSlot;
|
|
}
|
|
else
|
|
pNewSlot->pNextSlot = pNewSlot;
|
|
|
|
pImpl->aSlotArr.insert(pImpl->aSlotArr.begin() + static_cast<sal_uInt16>(n), std::unique_ptr<SfxSlot>(pNewSlot));
|
|
}
|
|
|
|
pImpl->aVerbList = aVerbs;
|
|
|
|
// The status of SID_OBJECT is collected in the controller directly on
|
|
// the Shell, it is thus enough to encourage a new status update
|
|
SfxBindings* pBindings = pViewSh->GetViewFrame().GetDispatcher()->GetBindings();
|
|
pBindings->Invalidate(SID_OBJECT, true, true);
|
|
}
|
|
|
|
const css::uno::Sequence < css::embed::VerbDescriptor >& SfxShell::GetVerbs() const
|
|
{
|
|
return pImpl->aVerbList;
|
|
}
|
|
|
|
void SfxShell::VerbExec(SfxRequest& rReq)
|
|
{
|
|
sal_uInt16 nId = rReq.GetSlot();
|
|
SfxViewShell *pViewShell = GetViewShell();
|
|
if ( !pViewShell )
|
|
return;
|
|
|
|
bool bReadOnly = pViewShell->GetObjectShell()->IsReadOnly();
|
|
const css::uno::Sequence < css::embed::VerbDescriptor > aList = pViewShell->GetVerbs();
|
|
sal_Int32 nVerb = 0;
|
|
for (const auto& rVerb : aList)
|
|
{
|
|
// check for ReadOnly verbs
|
|
if ( bReadOnly && !(rVerb.VerbAttributes & embed::VerbAttributes::MS_VERBATTR_NEVERDIRTIES) )
|
|
continue;
|
|
|
|
// check for verbs that shouldn't appear in the menu
|
|
if ( !(rVerb.VerbAttributes & embed::VerbAttributes::MS_VERBATTR_ONCONTAINERMENU) )
|
|
continue;
|
|
|
|
if (nId == SID_VERB_START + nVerb++)
|
|
{
|
|
pViewShell->DoVerb(rVerb.VerbID);
|
|
rReq.Done();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SfxShell::VerbState(SfxItemSet& )
|
|
{
|
|
}
|
|
|
|
const SfxSlot* SfxShell::GetVerbSlot_Impl(sal_uInt16 nId) const
|
|
{
|
|
css::uno::Sequence < css::embed::VerbDescriptor > rList = pImpl->aVerbList;
|
|
|
|
DBG_ASSERT(nId >= SID_VERB_START && nId <= SID_VERB_END,"Wrong VerbId!");
|
|
sal_uInt16 nIndex = nId - SID_VERB_START;
|
|
DBG_ASSERT(nIndex < rList.getLength(),"Wrong VerbId!");
|
|
|
|
if (nIndex < rList.getLength())
|
|
return pImpl->aSlotArr[nIndex].get();
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
SfxObjectShell* SfxShell::GetObjectShell()
|
|
{
|
|
if ( GetViewShell() )
|
|
return GetViewShell()->GetViewFrame().GetObjectShell();
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
bool SfxShell::HasUIFeature(SfxShellFeature) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static void DispatcherUpdate_Impl( void*, void* pArg )
|
|
{
|
|
static_cast<SfxDispatcher*>(pArg)->Update_Impl( true );
|
|
static_cast<SfxDispatcher*>(pArg)->GetBindings()->InvalidateAll(false);
|
|
}
|
|
|
|
void SfxShell::UIFeatureChanged()
|
|
{
|
|
SfxViewFrame *pFrame = GetFrame();
|
|
if ( pFrame && pFrame->IsVisible() )
|
|
{
|
|
// Also force an update, if dispatcher is already updated otherwise
|
|
// something may get stuck in the bunkered tools. Asynchronous call to
|
|
// prevent recursion.
|
|
if ( !pImpl->pUpdater )
|
|
pImpl->pUpdater.reset( new svtools::AsynchronLink( Link<void*,void>( this, DispatcherUpdate_Impl ) ) );
|
|
|
|
// Multiple views allowed
|
|
pImpl->pUpdater->Call( pFrame->GetDispatcher(), true );
|
|
}
|
|
}
|
|
|
|
void SfxShell::SetDisableFlags( SfxDisableFlags nFlags )
|
|
{
|
|
pImpl->nDisableFlags = nFlags;
|
|
}
|
|
|
|
SfxDisableFlags SfxShell::GetDisableFlags() const
|
|
{
|
|
return pImpl->nDisableFlags;
|
|
}
|
|
|
|
std::optional<SfxItemSet> SfxShell::CreateItemSet( sal_uInt16 )
|
|
{
|
|
return {};
|
|
}
|
|
|
|
void SfxShell::ApplyItemSet( sal_uInt16, const SfxItemSet& )
|
|
{
|
|
}
|
|
|
|
void SfxShell::SetContextName (const OUString& rsContextName)
|
|
{
|
|
pImpl->maContextChangeBroadcaster.Initialize(rsContextName);
|
|
}
|
|
|
|
void SfxShell::SetViewShell_Impl( SfxViewShell* pView )
|
|
{
|
|
pImpl->pViewSh = pView;
|
|
}
|
|
|
|
void SfxShell::BroadcastContextForActivation (const bool bIsActivated)
|
|
{
|
|
// Avoids activation and de-activation (can be seen on switching view) from causing
|
|
// the sidebar to re-build. Such switching can happen as we change view to render
|
|
// using LOK for example, and is un-necessary for Online.
|
|
if (comphelper::LibreOfficeKit::isDialogPainting())
|
|
return;
|
|
|
|
SfxViewFrame* pViewFrame = GetFrame();
|
|
if (pViewFrame != nullptr)
|
|
{
|
|
if (bIsActivated)
|
|
pImpl->maContextChangeBroadcaster.Activate(pViewFrame->GetFrame().GetFrameInterface());
|
|
else
|
|
pImpl->maContextChangeBroadcaster.Deactivate(pViewFrame->GetFrame().GetFrameInterface());
|
|
}
|
|
}
|
|
|
|
bool SfxShell::SetContextBroadcasterEnabled (const bool bIsEnabled)
|
|
{
|
|
return pImpl->maContextChangeBroadcaster.SetBroadcasterEnabled(bIsEnabled);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|