/* -*- 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 .
*/
if ( xDispatch == xController )
{
SAL_WARN("dbaccess.ui", "UserDefinedFeatures::execute: the controller shouldn't be the dispatcher here!" );
xDispatch.clear();
}
// create the database context
OSL_ENSURE(getORB().is(), "OGenericUnoController::Construct need a service factory!"); try
{
m_xDatabaseContext = DatabaseContext::create(getORB());
} catch(const Exception&)
{
SAL_WARN("dbaccess.ui","OGenericUnoController::Construct: could not create (or start listening at) the database context!"); // at least notify the user. Though the whole component does not make any sense without the database context ...
ShowServiceNotAvailableError(getFrameWeld(), u"com.sun.star.sdb.DatabaseContext", true);
}
for (auto& arg : aArguments)
{
PropertyValue aValue; if (arg >>= aValue)
{ if (aValue.Name == "Frame")
{
xFrame.set(aValue.Value, UNO_QUERY_THROW);
} elseif (aValue.Name == "Preview")
{
aValue.Value >>= m_bPreview;
m_bReadOnly = true;
}
}
} try
{ if ( !xFrame.is() ) throw IllegalArgumentException(u"need a frame"_ustr, *this, 1 );
Reference<XWindow> xParent = xFrame->getContainerWindow();
VclPtr<vcl::Window> pParentWin = VCLUnoHelper::GetWindow(xParent); if (!pParentWin)
{ throw IllegalArgumentException(u"Parent window is null"_ustr, *this, 1 );
}
Construct( pParentWin );
ODataView* pView = getView(); if ( !pView ) throw RuntimeException(u"unable to create a view"_ustr, *this );
if ( m_bReadOnly || m_bPreview )
pView->EnableInput( false );
impl_initialize(::comphelper::NamedValueCollection(aArguments));
} catch(Exception&)
{ // no one clears my view if I won't
m_pView = nullptr; throw;
}
}
Sequence< PropertyValue > SAL_CALL OGenericUnoController::getCreationArguments()
{ // currently we do not support any creation args, so anything passed to XModel2::createViewController would be // lost, so we can equally return an empty sequence here return Sequence< PropertyValue >();
}
void lcl_collectStates( const FeatureState& _rFeatureState, States& _out_rStates )
{ // order matters, due to a bug in framework which resets the check state when any non-boolean event // arrives // #i68215# is the bug to (re-)introduce this "ordered" notification here // #i67882# is the bug which was caused by the real fix which we did in framework // #i68216# is the bug which requests to fix the code in Draw which relies on // framework's implementation details if ( !!_rFeatureState.sTitle )
_out_rStates.push_back( Any( *_rFeatureState.sTitle ) ); if ( _rFeatureState.bChecked.has_value() )
_out_rStates.push_back( Any( *_rFeatureState.bChecked ) ); if ( _rFeatureState.bInvisible.has_value() )
_out_rStates.push_back( Any( Visibility( !*_rFeatureState.bInvisible ) ) ); if ( _rFeatureState.aValue.hasValue() )
_out_rStates.push_back( _rFeatureState.aValue ); if ( _out_rStates.empty() )
_out_rStates.emplace_back( );
}
}
FeatureState& rCachedState = m_aStateCache[nFeat]; // creates if necessary if ( !_bIgnoreCache )
{ // check if we really need to notify the listeners : this method may be called much more often than needed, so check // the cached state of the feature bool bAlreadyCached = ( m_aStateCache.find(nFeat) != m_aStateCache.end() ); if ( bAlreadyCached ) if ( ( rCachedState.bEnabled == aFeatState.bEnabled )
&& ( rCachedState.bChecked == aFeatState.bChecked )
&& ( rCachedState.bInvisible == aFeatState.bInvisible )
&& ( rCachedState.sTitle == aFeatState.sTitle )
) return;
}
rCachedState = aFeatState;
// collect all states to be notified
States aStates;
lcl_collectStates( aFeatState, aStates );
// a special listener ? if ( xListener.is() )
lcl_notifyMultipleStates( *xListener, aEvent, aStates ); else
{ // no -> iterate through all listeners responsible for the URL
std::set<OUString> aFeatureCommands; for( constauto& rFeature : m_aSupportedFeatures )
{ if( rFeature.second.nFeatureId == nFeat )
aFeatureCommands.insert( rFeature.first );
}
// it is possible that listeners are registered or revoked while // we are notifying them, so we must use a copy of m_arrStatusListener, not // m_arrStatusListener itself
std::vector<DispatchTarget> aNotifyLoop( m_arrStatusListener );
#if OSL_DEBUG_LEVEL > 0 if ( m_aSupportedFeatures.end() == aFeaturePos )
{
SAL_WARN( "dbaccess.ui", "OGenericUnoController::InvalidateFeature_Impl: feature id "
<< aNextFeature.nId
<< " has been invalidated, but is not supported!" );
} #endif if ( m_aSupportedFeatures.end() != aFeaturePos ) // we really know this feature
ImplBroadcastFeatureState( aFeaturePos->first, aNextFeature.xListener, aNextFeature.bForceBroadcast );
}
void OGenericUnoController::InvalidateAll_Impl()
{ // invalidate all supported features for (autoconst& supportedFeature : m_aSupportedFeatures)
ImplBroadcastFeatureState( supportedFeature.first, nullptr, true );
{
std::unique_lock aGuard( m_aFeatureMutex);
OSL_ENSURE(m_aFeaturesToInvalidate.size(), "OGenericUnoController::InvalidateAll_Impl: to be called from within InvalidateFeature_Impl only!");
m_aFeaturesToInvalidate.pop_front(); if(!m_aFeaturesToInvalidate.empty())
m_aAsyncInvalidateAll.Call();
}
}
OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::queryDispatch: shouldn't this be filled at construction time?" ); if ( m_aSupportedFeatures.empty() )
fillSupportedFeatures();
void OGenericUnoController::dispatch(const URL& _aURL, const Sequence< PropertyValue >& aArgs)
{
SolarMutexGuard aSolarGuard; // The SolarMutex is not locked anymore when the framework calls into // here. So, lock it ourself. The real solution would be to lock it only in the places // where it's needed, but a) this might turn out difficult, since we then also need to care // for locking in the proper order (SolarMutex and m_aMutex), and b) this would be too many places // for the time frame of the fix. // #i52602#
executeChecked(_aURL,aArgs);
}
void OGenericUnoController::addStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL)
{ // parse the URL now and here, this saves later parsing in each notification round
URL aParsedURL( _rURL ); if ( m_xUrlTransformer.is() )
m_xUrlTransformer->parseStrict( aParsedURL );
// remember the listener together with the URL
m_arrStatusListener.insert( m_arrStatusListener.end(), DispatchTarget( aParsedURL, aListener ) );
// initially broadcast the state
ImplBroadcastFeatureState( aParsedURL.Complete, aListener, true ); // force the new state to be broadcast to the new listener
}
void OGenericUnoController::removeStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL)
{ if (_rURL.Complete.isEmpty())
{
std::erase_if(m_arrStatusListener, [&aListener](const DispatchTarget& rCurrent) { return rCurrent.xListener == aListener; });
} else
{ // remove the listener only for the given URL auto iterSearch = std::find_if(m_arrStatusListener.begin(), m_arrStatusListener.end(),
[&aListener, &_rURL](const DispatchTarget& rCurrent) { return (rCurrent.xListener == aListener) && (rCurrent.aURL.Complete == _rURL.Complete); }); if (iterSearch != m_arrStatusListener.end())
m_arrStatusListener.erase(iterSearch);
}
OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::removeStatusListener: shouldn't this be filled at construction time?" ); if ( m_aSupportedFeatures.empty() )
fillSupportedFeatures();
SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find(_rURL.Complete); if (aIter != m_aSupportedFeatures.end())
{ // clear the cache for that feature auto aCachePos = m_aStateCache.find( aIter->second.nFeatureId ); if ( aCachePos != m_aStateCache.end() )
m_aStateCache.erase( aCachePos );
}
// now remove the listener from the deque
std::unique_lock aGuard( m_aFeatureMutex );
std::erase_if( m_aFeaturesToInvalidate, FindFeatureListener(aListener));
}
// check out from all the objects we are listening // the frame
stopFrameListening( m_aCurrentFrame.getFrame() );
m_aCurrentFrame.attachFrame( nullptr );
switch ( _nId )
{ case ID_BROWSER_UNDO: case ID_BROWSER_SAVEDOC:
aReturn.bEnabled = true; break; default: // for now, enable all the time // TODO: we should ask the dispatcher. However, this is laborious, since you cannot ask a dispatcher // directly, but need to add a status listener.
aReturn.bEnabled = true; break;
}
return aReturn;
}
void OGenericUnoController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue>& _rArgs )
{
OSL_ENSURE( isUserDefinedFeature( _nId ), "OGenericUnoController::Execute: responsible for user defined features only!" );
// user defined features can be handled by dispatch interceptors resp. protocol handlers only. // So, we need to do a queryDispatch, and dispatch the URL
executeUserDefinedFeatures( getURLForId( _nId ), _rArgs );
}
void OGenericUnoController::startConnectionListening(const Reference< XConnection >& _rxConnection)
{ // we have to remove ourself before disposing the connection
Reference< XComponent > xComponent(_rxConnection, UNO_QUERY); if (xComponent.is())
xComponent->addEventListener(static_cast<XFrameActionListener*>(this));
}
void OGenericUnoController::stopConnectionListening(const Reference< XConnection >& _rxConnection)
{ // we have to remove ourself before disposing the connection
Reference< XComponent > xComponent(_rxConnection, UNO_QUERY); if (xComponent.is())
xComponent->removeEventListener(static_cast<XFrameActionListener*>(this));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.