Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/dbaccess/source/ui/browser/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 37 kB image not shown  

Quelle  genericcontroller.cxx   Sprache: 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 <dbaccess/genericcontroller.hxx>
#include <browserids.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <dbaccess/dataview.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <osl/diagnose.h>
#include <vcl/stdtext.hxx>
#include <framework/titlehelper.hxx>
#include <connectivity/dbtools.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <com/sun/star/sdbc/XDataSource.hpp>
#include <com/sun/star/sdb/DatabaseContext.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <com/sun/star/util/XCloseable.hpp>

#include <com/sun/star/ui/XSidebarProvider.hpp>

#include <datasourceconnector.hxx>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/frame/status/Visibility.hpp>
#include <com/sun/star/frame/XUntitledNumbers.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <rtl/ustring.hxx>
#include <sal/log.hxx>
#include <limits>
#include <unordered_map>
#include <set>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::frame::status;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::task;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::ui;
using namespace ::dbtools;
using namespace ::comphelper;

constexpr auto ALL_FEATURES = -1;

typedef std::unordered_map< sal_Int16, sal_Int16 > CommandHashMap;

namespace dbaui
{

void OGenericUnoController::executeUserDefinedFeatures( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs )
{
    try
    {
        Reference< XController > xController( getXController(), UNO_SET_THROW );
        Reference< XDispatchProvider > xDispatchProvider( xController->getFrame(), UNO_QUERY_THROW );
        Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch(
            _rFeatureURL,
            u"_self"_ustr,
            FrameSearchFlag::AUTO
        ) );

        if ( xDispatch == xController )
        {
            SAL_WARN("dbaccess.ui""UserDefinedFeatures::execute: the controller shouldn't be the dispatcher here!" );
            xDispatch.clear();
        }

        if ( xDispatch.is() )
            xDispatch->dispatch( _rFeatureURL, _rArgs );
    }
    catchconst Exception& )
    {
        DBG_UNHANDLED_EXCEPTION("dbaccess");
    }
}

// OGenericUnoController
OGenericUnoController::OGenericUnoController(const Reference< XComponentContext >& ;_rM)
    :OGenericUnoController_Base( getMutex() )
    ,m_aUserInputInterception(*this, getMutex())
    ,m_pView(nullptr)
#ifdef DBG_UTIL
    ,m_bDescribingSupportedFeatures( false )
#endif
    ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
    ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
    ,m_xContext(_rM)
    ,m_aCurrentFrame( *this )
    ,m_bPreview(false)
    ,m_bReadOnly(false)
    ,m_bCurrentlyModified(false)
    ,m_bExternalTitle(false)
{

    try
    {
        m_xUrlTransformer = URLTransformer::create(_rM);
    }
    catch(Exception&)
    {
        DBG_UNHANDLED_EXCEPTION("dbaccess");
    }
}

OGenericUnoController::~OGenericUnoController()
{

}

bool OGenericUnoController::Construct(vcl::Window* /*pParent*/)
{
    OSL_ENSURE( getView(), "the view is NULL!" );

    if ( getView() )
    {
        getView()->Construct();
        getView()->Show();
    }

    m_aSupportedFeatures.clear();
    fillSupportedFeatures();

    // 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);
    }

    return true;
}

IMPL_LINK_NOARG(OGenericUnoController, OnAsyncInvalidateAll, void*, void)
{
    if ( !OGenericUnoController_Base::rBHelper.bInDispose && !OGenericUnoController_Base::rBHelper.bDisposed )
        InvalidateFeature_Impl();
}

void OGenericUnoController::impl_initialize(const ::comphelper::NamedValueCollection& /*rArguments*/)
{
}

void SAL_CALL OGenericUnoController::initialize( const Sequence< Any >& aArguments )
{
    SolarMutexGuard aSolarGuard;
    ::osl::MutexGuard aGuard( getMutex() );

    Reference< XFrame > xFrame;

    for (auto& arg : aArguments)
    {
        PropertyValue aValue;
        if (arg >>= aValue)
        {
            if (aValue.Name == "Frame")
            {
                xFrame.set(aValue.Value, UNO_QUERY_THROW);
            }
            else if (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;
    }
}

void SAL_CALL OGenericUnoController::acquire(  ) noexcept
{
    OGenericUnoController_Base::acquire();
}

void SAL_CALL OGenericUnoController::release(  ) noexcept
{
    OGenericUnoController_Base::release();
}

void OGenericUnoController::startFrameListening( const Reference< XFrame >& _rxFrame )
{
    if ( _rxFrame.is() )
        _rxFrame->addFrameActionListener( this );
}

void OGenericUnoController::stopFrameListening( const Reference< XFrame >& _rxFrame )
{
    if ( _rxFrame.is() )
        _rxFrame->removeFrameActionListener( this );
}

void OGenericUnoController::disposing(const EventObject& Source)
{
    // our frame ?
    if ( Source.Source == getFrame() )
        stopFrameListening( getFrame() );
}

void OGenericUnoController::modified(const EventObject& aEvent)
{
    ::osl::MutexGuard aGuard( getMutex() );
    if ( !isDataSourceReadOnly() )
    {
        Reference<XModifiable> xModi(aEvent.Source,UNO_QUERY);
        if ( xModi.is() )
            m_bCurrentlyModified = xModi->isModified(); // can only be reset by save
        else
            m_bCurrentlyModified = true;
    }
    InvalidateFeature(ID_BROWSER_SAVEDOC);
    InvalidateFeature(ID_BROWSER_UNDO);
}

Reference< XWindow > SAL_CALL OGenericUnoController::getComponentWindow()
{
    SolarMutexGuard g;
    return VCLUnoHelper::GetInterface( getView() );
}

Reference<XSidebarProvider> SAL_CALL OGenericUnoController::getSidebar()
{
        return nullptr;
}

OUString SAL_CALL OGenericUnoController::getViewControllerName()
{
    return u"Default"_ustr;
}

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 OGenericUnoController::attachFrame( const Reference< XFrame >& _rxFrame )
{
    SolarMutexGuard aSolarGuard;
    ::osl::MutexGuard aGuard( getMutex() );

    stopFrameListening( m_aCurrentFrame.getFrame() );
    Reference< XFrame > xFrame = m_aCurrentFrame.attachFrame( _rxFrame );
    startFrameListening( xFrame );

    loadMenu( xFrame );

    if ( getView() )
        getView()->attachFrame( xFrame );
}

namespace
{
    typedef std::vector< Any >    States;

    void    lcl_notifyMultipleStates( XStatusListener& _rListener, FeatureStateEvent&&nbsp;_rEvent, const States& _rStates )
    {
        for (auto const& elem : _rStates)
        {
            _rEvent.State = elem;
            _rListener.statusChanged( _rEvent );
        }
    }

    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( );
    }
}

void OGenericUnoController::ImplBroadcastFeatureState(const OUString& _rFeatureconst Reference< XStatusListener > & xListener, bool _bIgnoreCache)
{
    sal_uInt16 nFeat = m_aSupportedFeatures[ _rFeature ].nFeatureId;
    FeatureState aFeatState( GetState( nFeat ) );

    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;

    FeatureStateEvent aEvent;
    aEvent.FeatureURL.Complete = _rFeature;
    if (m_xUrlTransformer.is())
        m_xUrlTransformer->parseStrict(aEvent.FeatureURL);
    aEvent.Source       = static_cast<XDispatch*>(this);
    aEvent.IsEnabled    = aFeatState.bEnabled;

    // 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;
        forconst auto& 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 );

        for (auto const& elem : aNotifyLoop)
        {
            if ( aFeatureCommands.find( elem.aURL.Complete ) != aFeatureCommands.end() )
            {
                aEvent.FeatureURL = elem.aURL;
                lcl_notifyMultipleStates( *elem.xListener, aEvent, aStates );
            }
        }
    }

}

bool OGenericUnoController::isFeatureSupported( sal_Int32 _nId )
{
    SupportedFeatures::const_iterator aFeaturePos = std::find_if(
        m_aSupportedFeatures.begin(),
        m_aSupportedFeatures.end(),
        CompareFeatureById(_nId)
    );

    return ( m_aSupportedFeatures.end() != aFeaturePos && !aFeaturePos->first.isEmpty());
}

void OGenericUnoController::InvalidateFeature_Impl()
{
    bool bEmpty = true;
    FeatureListener aNextFeature;
    {
        std::unique_lock aGuard( m_aFeatureMutex);
        bEmpty = m_aFeaturesToInvalidate.empty();
        if (!bEmpty)
            aNextFeature = m_aFeaturesToInvalidate.front();
    }
    while(!bEmpty)
    {
        if ( ALL_FEATURES == aNextFeature.nId )
        {
            InvalidateAll_Impl();
            break;
        }
        else
        {
            SupportedFeatures::const_iterator aFeaturePos = std::find_if(
                m_aSupportedFeatures.begin(),
                m_aSupportedFeatures.end(),
                CompareFeatureById( aNextFeature.nId )
            );

#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 );
        }

        std::unique_lock aGuard( m_aFeatureMutex);
        m_aFeaturesToInvalidate.pop_front();
        bEmpty = m_aFeaturesToInvalidate.empty();
        if (!bEmpty)
            aNextFeature = m_aFeaturesToInvalidate.front();
    }
}

void OGenericUnoController::ImplInvalidateFeature( sal_Int32 _nId, const Reference< XStatusListener >& _xListener, bool _bForceBroadcast )
{
#if OSL_DEBUG_LEVEL > 0
    if ( _nId != -1 )
    {
        auto isSupportedFeature = std::any_of(
            m_aSupportedFeatures.begin(),
            m_aSupportedFeatures.end(),
            CompareFeatureById( _nId )
        );
        OSL_ENSURE( isSupportedFeature, "OGenericUnoController::ImplInvalidateFeature: invalidating an unsupported feature is suspicious, at least!" );
    }
#endif

    FeatureListener aListener;
    aListener.nId               = _nId;
    aListener.xListener         = _xListener;
    aListener.bForceBroadcast   = _bForceBroadcast;

    bool bWasEmpty;
    {
        std::unique_lock aGuard( m_aFeatureMutex );
        bWasEmpty = m_aFeaturesToInvalidate.empty();
        m_aFeaturesToInvalidate.push_back( aListener );
    }

    if ( bWasEmpty )
        m_aAsyncInvalidateAll.Call();
}

void OGenericUnoController::InvalidateFeature(sal_uInt16 _nId, const Reference< XStatusListener > & _xListener, bool _bForceBroadcast)
{
    ImplInvalidateFeature( _nId, _xListener, _bForceBroadcast );
}

void OGenericUnoController::InvalidateAll()
{
    ImplInvalidateFeature( ALL_FEATURES, nullptr, true );
}

void OGenericUnoController::InvalidateAll_Impl()
{
    // invalidate all supported features
    for (auto const& 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();
    }
}

Reference< XDispatch >  OGenericUnoController::queryDispatch(const URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags)
{
    Reference< XDispatch > xReturn;

    OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::queryDispatch: shouldn't this be filled at construction time?" );
    if ( m_aSupportedFeatures.empty() )
        fillSupportedFeatures();

    // URL's we can handle ourself?
    if  (   aURL.Complete == ".uno:FormSlots/ConfirmDeletion"
        ||  (   ( m_aSupportedFeatures.find( aURL.Complete ) != m_aSupportedFeatures.end() )
            &&  !isUserDefinedFeature( aURL.Complete )
            )
        )
    {
        xReturn = this;
    }
    // no? -> ask the slave dispatcher
    else if ( m_xSlaveDispatcher.is() )
    {
        xReturn = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
    }

    // outta here
    return xReturn;
}

Sequence< Reference< XDispatch > > OGenericUnoController::queryDispatches(const Sequence< DispatchDescriptor >& aDescripts)
{
    Sequence< Reference< XDispatch > > aReturn(aDescripts.getLength());
    if (aDescripts.hasElements())
    {
        std::transform(aDescripts.begin(), aDescripts.end(), aReturn.getArray(),
                       [this](auto& desc) {
                           return queryDispatch(desc.FeatureURL, desc.FrameName, desc.SearchFlags);
                       });
    }

    return aReturn;
}

Reference< XDispatchProvider >  OGenericUnoController::getSlaveDispatchProvider()
{
    return m_xSlaveDispatcher;
}

void OGenericUnoController::setSlaveDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider)
{
    m_xSlaveDispatcher = _xNewProvider;
}

Reference< XDispatchProvider >  OGenericUnoController::getMasterDispatchProvider()
{
    return m_xMasterDispatcher;
}

void OGenericUnoController::setMasterDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider)
{
    m_xMasterDispatcher = _xNewProvider;
}

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 > &&nbsp;aListener, const URL& _rURL)
{
    if (_rURL.Complete.isEmpty())
    {
        std::erase_if(m_arrStatusListener, [&aListener](const DispatchTarget&&nbsp;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));
}

void OGenericUnoController::releaseNumberForComponent()
{
    try
    {
        Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY      );
        if ( xUntitledProvider.is() )
            xUntitledProvider->releaseNumberForComponent(static_cast<XWeak*>(this));
    }
    catchconst Exception& )
    {
        // NII
    }
}

void OGenericUnoController::disposing()
{
    {
        EventObject aDisposeEvent;
        aDisposeEvent.Source = static_cast<XWeak*>(this);
        std::vector<DispatchTarget> aStatusListener = m_arrStatusListener;
        for (auto const& statusListener : aStatusListener)
        {
            statusListener.xListener->disposing(aDisposeEvent);
        }
        m_arrStatusListener.clear();
    }

    m_xDatabaseContext = nullptr;
    {
        std::unique_lock aGuard( m_aFeatureMutex);
        m_aAsyncInvalidateAll.CancelCall();
        m_aFeaturesToInvalidate.clear();
    }

    releaseNumberForComponent();

    // check out from all the objects we are listening
    // the frame
    stopFrameListening( m_aCurrentFrame.getFrame() );
    m_aCurrentFrame.attachFrame( nullptr );

    m_xMasterDispatcher = nullptr;
    m_xSlaveDispatcher = nullptr;
    m_xTitleHelper.clear();
    m_xUrlTransformer.clear();
}

void SAL_CALL OGenericUnoController::addEventListener( const Reference< XEventListener >&&nbsp;xListener )
{
    // disambiguate
    OGenericUnoController_Base::WeakComponentImplHelperBase::addEventListener( xListener );
}

void SAL_CALL OGenericUnoController::removeEventListener( const Reference< XEventListener >& xListener )
{
    // disambiguate
    OGenericUnoController_Base::WeakComponentImplHelperBase::removeEventListener( xListener );
}

void OGenericUnoController::frameAction(const FrameActionEvent& aEvent)
{
    ::osl::MutexGuard aGuard( getMutex() );
    if ( aEvent.Frame == m_aCurrentFrame.getFrame() )
        m_aCurrentFrame.frameAction( aEvent.Action );
}

void OGenericUnoController::implDescribeSupportedFeature( const OUString& _rCommandURL,
        sal_uInt16 _nFeatureId, sal_Int16 _nCommandGroup )
{
#ifdef DBG_UTIL
    OSL_ENSURE( m_bDescribingSupportedFeatures, "OGenericUnoController::implDescribeSupportedFeature: bad timing for this call!" );
#endif
    OSL_PRECOND( _nFeatureId < ( std::numeric_limits< sal_uInt16 >::max() - 1000 ), // FIRST_USER_DEFINED_FEATURE
                "OGenericUnoController::implDescribeSupportedFeature: invalid feature id!" );

    ControllerFeature aFeature;
    aFeature.Command = _rCommandURL;
    aFeature.nFeatureId = _nFeatureId;
    aFeature.GroupId = _nCommandGroup;

#if OSL_DEBUG_LEVEL > 0
    OSL_ENSURE( m_aSupportedFeatures.find( aFeature.Command ) == m_aSupportedFeatures.end(),
        "OGenericUnoController::implDescribeSupportedFeature: this feature is already there!" );
#endif
    m_aSupportedFeatures[ aFeature.Command ] = aFeature;
}

void OGenericUnoController::describeSupportedFeatures()
{
    // add all supported features
    implDescribeSupportedFeature( u".uno:Copy"_ustr, ID_BROWSER_COPY, CommandGroup::EDIT );
    implDescribeSupportedFeature( u".uno:Cut"_ustr, ID_BROWSER_CUT, CommandGroup::EDIT );
    implDescribeSupportedFeature( u".uno:Paste"_ustr, ID_BROWSER_PASTE, CommandGroup::EDIT );
    implDescribeSupportedFeature( u".uno:ClipboardFormatItems"_ustr, ID_BROWSER_CLIPBOARD_FORMAT_ITEMS );
    implDescribeSupportedFeature( u".uno:DSBEditDoc"_ustr, ID_BROWSER_EDITDOC, CommandGroup::DOCUMENT );
}

FeatureState OGenericUnoController::GetState( sal_uInt16 _nId ) const
{
    FeatureState aReturn;
        // (disabled automatically)

    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 );
}

URL OGenericUnoController::getURLForId(sal_Int32 _nId) const
{
    URL aReturn;
    if ( m_xUrlTransformer.is() )
    {
        SupportedFeatures::const_iterator aIter = std::find_if(
            m_aSupportedFeatures.begin(),
            m_aSupportedFeatures.end(),
            CompareFeatureById( _nId )
        );

        if ( m_aSupportedFeatures.end() != aIter && !aIter->first.isEmpty() )
        {
            aReturn.Complete = aIter->first;
            m_xUrlTransformer->parseStrict( aReturn );
        }
    }
    return aReturn;
}

bool OGenericUnoController::isUserDefinedFeature( const sal_uInt16 _nFeatureId )
{
    return
        (_nFeatureId >= ( std::numeric_limits< sal_uInt16 >::max() - 1000 )) // test if >= FIRST_USER_DEFINED_FEATURE
        &&
        ( _nFeatureId < (std::numeric_limits< sal_uInt16 >::max())) // test if < LAST_USER_DEFINED_FEATURE
    ;
}

bool OGenericUnoController::isUserDefinedFeature( const OUString& _rFeatureURL ) const
{
    SupportedFeatures::const_iterator pos = m_aSupportedFeatures.find( _rFeatureURL );
    OSL_PRECOND( pos != m_aSupportedFeatures.end(),
        "OGenericUnoController::isUserDefinedFeature: this is no supported feature at all!" );

    return ( pos != m_aSupportedFeatures.end() ) && isUserDefinedFeature( pos->second.nFeatureId );
}

sal_Bool SAL_CALL OGenericUnoController::supportsService(const OUString& ServiceName)
{
    return cppu::supportsService(this, ServiceName);
}

void OGenericUnoController::startConnectionListening(const Reference< XConnection >&&nbsp;_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));
}

Reference< XConnection > OGenericUnoController::connect( const Reference< XDataSource>& ;_xDataSource )
{
    weld::WaitObject aWaitCursor(getFrameWeld());

    ODatasourceConnector aConnector( getORB(), getFrameWeld(), OUString() );
    Reference< XConnection > xConnection = aConnector.connect( _xDataSource, nullptr );
    startConnectionListening( xConnection );

    return xConnection;
}

Reference< XConnection > OGenericUnoController::connect( const OUString& _rDataSourceName,
    const OUString& _rContextInformation, ::dbtools::SQLExceptionInfo* _pErrorInfo )
{
    weld::WaitObject aWaitCursor(getFrameWeld());

    ODatasourceConnector aConnector( getORB(), getFrameWeld(), _rContextInformation );
    Reference<XConnection> xConnection = aConnector.connect( _rDataSourceName, _pErrorInfo );
    startConnectionListening( xConnection );

    return xConnection;
}

void OGenericUnoController::setView( const VclPtr<ODataView> &i_rView )
{
    m_pView = i_rView;
}

void OGenericUnoController::clearView()
{
    m_pView = nullptr;
}

void OGenericUnoController::showError(const SQLExceptionInfo& _rInfo)
{
    ::dbtools::showError(_rInfo,VCLUnoHelper::GetInterface(getView()),getORB());
}

Reference< XLayoutManager > OGenericUnoController::getLayoutManager(const Reference< XFrame >& _xFrame)
{
    Reference< XPropertySet > xPropSet( _xFrame, UNO_QUERY );
    Reference< XLayoutManager > xLayoutManager;
    if ( xPropSet.is() )
    {
        try
        {
            xLayoutManager.set(xPropSet->getPropertyValue(u"LayoutManager"_ustr),UNO_QUERY);
        }
        catch ( Exception& )
        {
        }
    }
    return xLayoutManager;
}

void OGenericUnoController::loadMenu(const Reference< XFrame >& _xFrame)
{
    Reference< XLayoutManager > xLayoutManager = getLayoutManager(_xFrame);
    if ( xLayoutManager.is() )
    {
        xLayoutManager->lock();
        xLayoutManager->createElement( u"private:resource/menubar/menubar"_ustr );
        xLayoutManager->createElement( u"private:resource/toolbar/toolbar"_ustr );
        xLayoutManager->unlock();
        xLayoutManager->doLayout();
    }

    onLoadedMenu( xLayoutManager );
}

void OGenericUnoController::onLoadedMenu(const Reference< XLayoutManager >& /*_xLayoutManager*/)
{
    // not interested in
}

void OGenericUnoController::closeTask()
{
    m_aAsyncCloseTask.Call();
}

IMPL_LINK_NOARG(OGenericUnoController, OnAsyncCloseTask, void*, void)
{
    if ( !OGenericUnoController_Base::rBHelper.bInDispose )
    {
        try
        {
            Reference< util::XCloseable > xCloseable( m_aCurrentFrame.getFrame(), UNO_QUERY_THROW );
            xCloseable->close( false ); // false - holds the owner ship for this frame inside this object!
        }
        catchconst Exception& )
        {
            DBG_UNHANDLED_EXCEPTION("dbaccess");
        }
    }
}

Any SAL_CALL OGenericUnoController::getViewData()
{
    return Any();
}

void SAL_CALL OGenericUnoController::restoreViewData(const Any& /*Data*/)
{
}

Reference< XModel > SAL_CALL OGenericUnoController::getModel()
{
    return Reference< XModel >();
}

Reference< XFrame > SAL_CALL OGenericUnoController::getFrame()
{
    ::osl::MutexGuard aGuard( getMutex() );
    return m_aCurrentFrame.getFrame();
}

sal_Bool SAL_CALL OGenericUnoController::attachModel(const Reference< XModel > & /*xModel*/)
{
    SAL_WARN("dbaccess.ui""OGenericUnoController::attachModel: not supported!" );
    return false;
}

void OGenericUnoController::executeUnChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
{
    Execute(_nCommandId, aArgs);
}

void OGenericUnoController::executeUnChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
{
    OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeUnChecked: shouldn't this be filled at construction time?" );
    if ( m_aSupportedFeatures.empty() )
        fillSupportedFeatures();

    SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
    if (aIter != m_aSupportedFeatures.end())
        Execute( aIter->second.nFeatureId, aArgs );
}

void OGenericUnoController::executeChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
{
    OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeChecked: shouldn't this be filled at construction time?" );
    if ( m_aSupportedFeatures.empty() )
        fillSupportedFeatures();

    SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
    if ( aIter != m_aSupportedFeatures.end() )
    {
        sal_uInt16 nFeatureId = aIter->second.nFeatureId;
        if ( GetState( nFeatureId ).bEnabled )
            Execute( nFeatureId, aArgs );
    }
}

Reference< awt::XWindow> OGenericUnoController::getTopMostContainerWindow() const
{
    Reference< css::awt::XWindow> xWindow;

    // get the top most window
    Reference< XFrame > xFrame( m_aCurrentFrame.getFrame() );
    if ( xFrame.is() )
    {
        xWindow = xFrame->getContainerWindow();

        while ( xFrame.is() && !xFrame->isTop() )
        {
            xFrame = xFrame->getCreator();
        }
        if ( xFrame.is() )
            xWindow = xFrame->getContainerWindow();
    }
    return xWindow;
}

Reference< XTitle > OGenericUnoController::impl_getTitleHelper_throw(bool bCreateIfNecessary)
{
    SolarMutexGuard aSolarGuard;
    ::osl::MutexGuard aGuard( getMutex() );

    if (!m_xTitleHelper.is() && bCreateIfNecessary)
    {
        Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY      );

        m_xTitleHelper = new ::framework::TitleHelper( m_xContext, Reference< XController >(this), xUntitledProvider );
    }

    return m_xTitleHelper;
}

// XTitle
OUString SAL_CALL OGenericUnoController::getTitle()
{
    ::osl::MutexGuard aGuard( getMutex() );
    if ( m_bExternalTitle )
        return impl_getTitleHelper_throw()->getTitle ();
    return getPrivateTitle() + impl_getTitleHelper_throw()->getTitle ();
}

// XTitle
void SAL_CALL OGenericUnoController::setTitle(const OUString& sTitle)
{
    SolarMutexGuard aSolarGuard;
    ::osl::MutexGuard aGuard( getMutex() );
    m_bExternalTitle = true;
    impl_getTitleHelper_throw()->setTitle (sTitle);
}

// XTitleChangeBroadcaster
void SAL_CALL OGenericUnoController::addTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
{
    Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
    if (xBroadcaster.is ())
        xBroadcaster->addTitleChangeListener (xListener);
}

void SAL_CALL OGenericUnoController::removeTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
{
    Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(false), UNO_QUERY);
    if (xBroadcaster.is ())
        xBroadcaster->removeTitleChangeListener (xListener);
}

// XUserInputInterception
void SAL_CALL OGenericUnoController::addKeyHandler( const Reference< XKeyHandler >& _rxHandler )
{
    if ( _rxHandler.is() )
        m_aUserInputInterception.addKeyHandler( _rxHandler );
}

void SAL_CALL OGenericUnoController::removeKeyHandler( const Reference< XKeyHandler >&&nbsp;_rxHandler )
{
    m_aUserInputInterception.removeKeyHandler( _rxHandler );
}

void SAL_CALL OGenericUnoController::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler )
{
    if ( _rxHandler.is() )
        m_aUserInputInterception.addMouseClickHandler( _rxHandler );
}

void SAL_CALL OGenericUnoController::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler )
{
    m_aUserInputInterception.removeMouseClickHandler( _rxHandler );
}

void OGenericUnoController::executeChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
{
    if ( isCommandEnabled(_nCommandId) )
        Execute(_nCommandId, aArgs);
}

bool OGenericUnoController::isCommandEnabled(sal_uInt16 _nCommandId) const
{
    return GetState( _nCommandId ).bEnabled;
}

bool OGenericUnoController::isDataSourceReadOnly() const
{
    return false;
}

Reference< XController > OGenericUnoController::getXController()
{
    return this;
}

bool OGenericUnoController::interceptUserInput( const NotifyEvent& _rEvent )
{
    return m_aUserInputInterception.handleNotifyEvent( _rEvent );
}

bool OGenericUnoController::isCommandChecked(sal_uInt16 _nCommandId) const
{
    FeatureState aState = GetState( _nCommandId );

    return aState.bChecked.has_value() && *aState.bChecked;
}

bool OGenericUnoController::isCommandEnabled( const OUString& _rCompleteCommandURL ) const
{
    OSL_ENSURE( !_rCompleteCommandURL.isEmpty(), "OGenericUnoController::isCommandEnabled: Empty command url!" );

    bool bIsEnabled = false;
    SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL );
    if ( aIter != m_aSupportedFeatures.end() )
        bIsEnabled = isCommandEnabled( aIter->second.nFeatureId );

    return bIsEnabled;
}

Sequence< ::sal_Int16 > SAL_CALL OGenericUnoController::getSupportedCommandGroups()
{
    CommandHashMap aCmdHashMap;
    for (auto const& supportedFeature : m_aSupportedFeatures)
        if ( supportedFeature.second.GroupId != CommandGroup::INTERNAL )
            aCmdHashMap.emplace( supportedFeature.second.GroupId, 0 );

    return comphelper::mapKeysToSequence( aCmdHashMap );
}

Sequence< DispatchInformation > SAL_CALL OGenericUnoController::getConfigurableDispatchInformation( ::sal_Int16 CommandGroup )
{
    std::vector< DispatchInformation > aInformationVector;
    for (auto const& supportedFeature : m_aSupportedFeatures)
    {
        if ( sal_Int16( supportedFeature.second.GroupId ) == CommandGroup )
        {
            aInformationVector.push_back( supportedFeature.second );
        }
    }

    return comphelper::containerToSequence( aInformationVector );
}

void OGenericUnoController::fillSupportedFeatures()
{
#ifdef DBG_UTIL
    m_bDescribingSupportedFeatures = true;
#endif
    describeSupportedFeatures();
#ifdef DBG_UTIL
    m_bDescribingSupportedFeatures = false;
#endif
}

void SAL_CALL OGenericUnoController::dispose()
{
    SolarMutexGuard aSolarGuard;
    OGenericUnoController_Base::dispose();
    m_xUrlTransformer.clear();
    m_xSlaveDispatcher.clear();
    m_xMasterDispatcher.clear();
    m_xDatabaseContext.clear();
    m_xTitleHelper.clear();
}

weld::Window* OGenericUnoController::getFrameWeld() const
{
    return m_pView ? m_pView->GetFrameWeld() : nullptr;
}

}   // namespace dbaui

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.