summaryrefslogtreecommitdiff
path: root/dbaccess/source/ui/browser/genericcontroller.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/source/ui/browser/genericcontroller.cxx')
-rw-r--r--dbaccess/source/ui/browser/genericcontroller.cxx1636
1 files changed, 1636 insertions, 0 deletions
diff --git a/dbaccess/source/ui/browser/genericcontroller.cxx b/dbaccess/source/ui/browser/genericcontroller.cxx
new file mode 100644
index 000000000000..706d58400c2d
--- /dev/null
+++ b/dbaccess/source/ui/browser/genericcontroller.cxx
@@ -0,0 +1,1636 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_dbaccess.hxx"
+#include "genericcontroller.hxx"
+#include <comphelper/uno3.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include "browserids.hxx"
+#include <vcl/svapp.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include "dataview.hxx"
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include "dbustrings.hrc"
+#include <vcl/stdtext.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <framework/titlehelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/extract.hxx>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include "UITools.hxx"
+#include "commontypes.hxx"
+
+#include <sal/macros.h>
+#include <vcl/waitobj.hxx>
+#include <tools/urlobj.hxx>
+#include <svl/urihelper.hxx>
+#include "datasourceconnector.hxx"
+#include <unotools/moduleoptions.hxx>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/status/Visibility.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <rtl/ustring.hxx>
+#include <rtl/logfile.hxx>
+#include <algorithm>
+#include <o3tl/compat_functional.hxx>
+#include <boost/unordered_map.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <limits>
+
+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::container;
+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;
+using namespace ::dbtools;
+using namespace ::comphelper;
+
+// -------------------------------------------------------------------------
+#define ALL_FEATURES -1
+#define FIRST_USER_DEFINED_FEATURE ( ::std::numeric_limits< sal_uInt16 >::max() - 1000 )
+#define LAST_USER_DEFINED_FEATURE ( ::std::numeric_limits< sal_uInt16 >::max() )
+
+// -------------------------------------------------------------------------
+typedef ::boost::unordered_map< sal_Int16, sal_Int16 > CommandHashMap;
+typedef ::std::list< DispatchInformation > DispatchInfoList;
+
+
+// -------------------------------------------------------------------------
+const ::rtl::OUString& getConfirmDeletionURL()
+{
+ static const ::rtl::OUString sConfirmDeletionURL( RTL_CONSTASCII_USTRINGPARAM( ".uno:FormSlots/ConfirmDeletion" ) );
+ return sConfirmDeletionURL;
+}
+
+namespace dbaui
+{
+
+//==========================================================================
+//= UserDefinedFeatures
+//==========================================================================
+class UserDefinedFeatures
+{
+public:
+ UserDefinedFeatures( const Reference< XController >& _rxController );
+
+ FeatureState getState( const URL& _rFeatureURL );
+ void execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs );
+
+private:
+ ::com::sun::star::uno::WeakReference< XController > m_aController;
+};
+
+//--------------------------------------------------------------------------
+UserDefinedFeatures::UserDefinedFeatures( const Reference< XController >& _rxController )
+ :m_aController( _rxController )
+{
+}
+
+//--------------------------------------------------------------------------
+FeatureState UserDefinedFeatures::getState( const URL& /*_rFeatureURL*/ )
+{
+ // 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.
+ FeatureState aState;
+ aState.bEnabled = sal_True;
+ return aState;
+}
+
+//--------------------------------------------------------------------------
+void UserDefinedFeatures::execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs )
+{
+ try
+ {
+ Reference< XController > xController( (Reference< XController >)m_aController, UNO_SET_THROW );
+ Reference< XDispatchProvider > xDispatchProvider( xController->getFrame(), UNO_QUERY_THROW );
+ Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch(
+ _rFeatureURL,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ),
+ FrameSearchFlag::AUTO
+ ) );
+
+ if ( xDispatch == xController )
+ {
+ OSL_FAIL( "UserDefinedFeatures::execute: the controller shouldn't be the dispatcher here!" );
+ xDispatch.clear();
+ }
+
+ if ( xDispatch.is() )
+ xDispatch->dispatch( _rFeatureURL, _rArgs );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//==========================================================================
+//= OGenericUnoController_Data
+//==========================================================================
+struct OGenericUnoController_Data
+{
+ ::sfx2::UserInputInterception m_aUserInputInterception;
+ UserDefinedFeatures m_aUserDefinedFeatures;
+
+ OGenericUnoController_Data( OGenericUnoController& _rController, ::osl::Mutex& _rMutex )
+ :m_aUserInputInterception( _rController, _rMutex )
+ ,m_aUserDefinedFeatures( _rController.getXController() )
+ {
+ }
+};
+
+//==========================================================================
+//= OGenericUnoController
+//==========================================================================
+DBG_NAME(OGenericUnoController)
+// -------------------------------------------------------------------------
+OGenericUnoController::OGenericUnoController(const Reference< XMultiServiceFactory >& _rM)
+ :OGenericUnoController_Base( getMutex() )
+ ,m_pView(NULL)
+#ifdef DBG_UTIL
+ ,m_bDescribingSupportedFeatures( false )
+#endif
+ ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
+ ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
+ ,m_xServiceFactory(_rM)
+ ,m_aCurrentFrame( *this )
+ ,m_bPreview(sal_False)
+ ,m_bReadOnly(sal_False)
+ ,m_bCurrentlyModified(sal_False)
+ ,m_bExternalTitle(sal_False)
+{
+ osl_incrementInterlockedCount( &m_refCount );
+ {
+ m_pData.reset( new OGenericUnoController_Data( *this, getMutex() ) );
+ }
+ osl_decrementInterlockedCount( &m_refCount );
+
+ DBG_CTOR(OGenericUnoController,NULL);
+
+ try
+ {
+ m_xUrlTransformer = Reference< XURLTransformer > (_rM->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), UNO_QUERY);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+#ifdef WNT
+// -----------------------------------------------------------------------------
+OGenericUnoController::OGenericUnoController()
+ :OGenericUnoController_Base( getMutex() )
+ ,m_pView(NULL)
+#ifdef DBG_UTIL
+ ,m_bDescribingSupportedFeatures( false )
+#endif
+ ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
+ ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
+ ,m_aCurrentFrame( *this )
+ ,m_bPreview(sal_False)
+ ,m_bReadOnly(sal_False)
+ ,m_bCurrentlyModified(sal_False)
+{
+ OSL_FAIL( "OGenericUnoController::OGenericUnoController: illegal call!" );
+ // This ctor only exists because the MSVC compiler complained about an unresolved external
+ // symbol. It should not be used at all. Since using it yields strange runtime problems,
+ // we simply abort here.
+ abort();
+}
+#endif
+
+// -----------------------------------------------------------------------------
+OGenericUnoController::~OGenericUnoController()
+{
+
+ DBG_DTOR(OGenericUnoController,NULL);
+}
+
+// -----------------------------------------------------------------------------
+sal_Bool OGenericUnoController::Construct(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 = Reference< XNameAccess >(getORB()->createInstance(SERVICE_SDB_DATABASECONTEXT), UNO_QUERY);
+ }
+ catch(Exception&)
+ {
+ OSL_FAIL("OGenericUnoController::Construct: could not create (or start listening at) the database context!");
+ }
+
+ if (!m_xDatabaseContext.is())
+ { // at least notify the user. Though the whole component does not make any sense without the database context ...
+ ShowServiceNotAvailableError(getView(), String(SERVICE_SDB_DATABASECONTEXT), sal_True);
+ }
+ return sal_True;
+}
+//------------------------------------------------------------------------------
+IMPL_LINK(OGenericUnoController, OnAsyncInvalidateAll, void*, EMPTYARG)
+{
+ if ( !OGenericUnoController_Base::rBHelper.bInDispose && !OGenericUnoController_Base::rBHelper.bDisposed )
+ InvalidateFeature_Impl();
+ return 0L;
+}
+// -----------------------------------------------------------------------------
+void OGenericUnoController::impl_initialize()
+{
+}
+// -------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Reference< XWindow > xParent;
+ Reference< XFrame > xFrame;
+
+ PropertyValue aValue;
+ const Any* pIter = aArguments.getConstArray();
+ const Any* pEnd = pIter + aArguments.getLength();
+
+ for ( ; pIter != pEnd; ++pIter )
+ {
+ if ( ( *pIter >>= aValue ) && ( 0 == aValue.Name.compareToAscii( "Frame" ) ) )
+ {
+ xFrame.set(aValue.Value,UNO_QUERY_THROW);
+ }
+ else if ( ( *pIter >>= aValue ) && ( 0 == aValue.Name.compareToAscii( "Preview" ) ) )
+ {
+ aValue.Value >>= m_bPreview;
+ m_bReadOnly = sal_True;
+ }
+ }
+ try
+ {
+ if ( !xFrame.is() )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "need a frame" ) ), *this, 1 );
+
+ xParent = xFrame->getContainerWindow();
+ VCLXWindow* pParentComponent = VCLXWindow::GetImplementation(xParent);
+ Window* pParentWin = pParentComponent ? pParentComponent->GetWindow() : NULL;
+ if (!pParentWin)
+ {
+ throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Parent window is null")), *this, 1 );
+ }
+
+ m_aInitParameters.assign( aArguments );
+ Construct( pParentWin );
+
+ ODataView* pView = getView();
+ if ( !pView )
+ throw RuntimeException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unable to create a view")), *this );
+
+ if ( m_bReadOnly || m_bPreview )
+ pView->EnableInput( sal_False );
+
+ impl_initialize();
+ }
+ catch(Exception& e)
+ {
+ // no one clears my view if I won't
+ ::std::auto_ptr<Window> aTemp(m_pView);
+ m_pView = NULL;
+ throw;
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::acquire( ) throw ()
+{
+ OGenericUnoController_Base::acquire();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::release( ) throw ()
+{
+ 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) throw( RuntimeException )
+{
+ // our frame ?
+ if ( Source.Source == getFrame() )
+ stopFrameListening( getFrame() );
+}
+//------------------------------------------------------------------------
+void OGenericUnoController::modified(const EventObject& aEvent) throw( RuntimeException )
+{
+ ::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 = sal_True;
+ }
+ InvalidateFeature(ID_BROWSER_SAVEDOC);
+ InvalidateFeature(ID_BROWSER_UNDO);
+}
+// -----------------------------------------------------------------------
+Reference< XWindow > SAL_CALL OGenericUnoController::getComponentWindow() throw (RuntimeException)
+{
+ return VCLUnoHelper::GetInterface( getView() );
+}
+
+// -----------------------------------------------------------------------
+::rtl::OUString SAL_CALL OGenericUnoController::getViewControllerName() throw (::com::sun::star::uno::RuntimeException)
+{
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Default" ) );
+}
+
+// -----------------------------------------------------------------------
+Sequence< PropertyValue > SAL_CALL OGenericUnoController::getCreationArguments() throw (RuntimeException)
+{
+ // 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 ) throw( RuntimeException )
+{
+ 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 );
+}
+
+// -----------------------------------------------------------------------------
+struct CommandCollector : public ::std::unary_function< SupportedFeatures::value_type, void>
+{
+ sal_uInt16 m_nFeature;
+ StringBag& m_rFeatureCommands;
+ CommandCollector( sal_uInt16 _nFeature, StringBag& _rFeatureCommands )
+ :m_nFeature ( _nFeature )
+ ,m_rFeatureCommands( _rFeatureCommands )
+ {
+ }
+
+ void operator() ( const SupportedFeatures::value_type& lhs )
+ {
+ if ( lhs.second.nFeatureId == m_nFeature )
+ m_rFeatureCommands.insert( lhs.first );
+ }
+};
+
+// -----------------------------------------------------------------------
+namespace
+{
+ typedef ::std::vector< Any > States;
+
+ // ...................................................................
+ void lcl_notifyMultipleStates( XStatusListener& _rListener, FeatureStateEvent& _rEvent, const States& _rStates )
+ {
+ for ( States::const_iterator state = _rStates.begin();
+ state != _rStates.end();
+ ++state
+ )
+ {
+ _rEvent.State = *state;
+ _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( makeAny( *_rFeatureState.sTitle ) );
+ if ( !!_rFeatureState.bChecked )
+ _out_rStates.push_back( makeAny( (sal_Bool)*_rFeatureState.bChecked ) );
+ if ( !!_rFeatureState.bInvisible )
+ _out_rStates.push_back( makeAny( Visibility( !*_rFeatureState.bInvisible ) ) );
+ if ( _rFeatureState.aValue.hasValue() )
+ _out_rStates.push_back( _rFeatureState.aValue );
+ if ( _out_rStates.empty() )
+ _out_rStates.push_back( Any() );
+ }
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::ImplBroadcastFeatureState(const ::rtl::OUString& _rFeature, const Reference< XStatusListener > & xListener, sal_Bool _bIgnoreCache)
+{
+ sal_uInt16 nFeat = m_aSupportedFeatures[ _rFeature ].nFeatureId;
+ FeatureState aFeatState( GetState( nFeat ) );
+
+ FeatureState& rCachedState = m_aStateCache[nFeat]; // creates if neccessary
+ 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
+ sal_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 = (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.get(), aEvent, aStates );
+ else
+ { // no -> iterate through all listeners responsible for the URL
+ StringBag aFeatureCommands;
+ ::std::for_each(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ CommandCollector( nFeat, aFeatureCommands )
+ );
+
+ // 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
+ Dispatch aNotifyLoop( m_arrStatusListener );
+ DispatchIterator iterSearch = aNotifyLoop.begin();
+ DispatchIterator iterEnd = aNotifyLoop.end();
+
+ while (iterSearch != iterEnd)
+ {
+ DispatchTarget& rCurrent = *iterSearch;
+ if ( aFeatureCommands.find( rCurrent.aURL.Complete ) != aFeatureCommands.end() )
+ {
+ aEvent.FeatureURL = rCurrent.aURL;
+ lcl_notifyMultipleStates( *rCurrent.xListener.get(), aEvent, aStates );
+ }
+ ++iterSearch;
+ }
+ }
+
+}
+
+//------------------------------------------------------------------------------
+sal_Bool OGenericUnoController::isFeatureSupported( sal_Int32 _nId )
+{
+ SupportedFeatures::iterator aFeaturePos = ::std::find_if(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ ::std::bind2nd( CompareFeatureById(), _nId )
+ );
+
+ return ( m_aSupportedFeatures.end() != aFeaturePos && aFeaturePos->first.getLength());
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::InvalidateFeature(const ::rtl::OUString& _rURLPath, const Reference< XStatusListener > & _xListener, sal_Bool _bForceBroadcast)
+{
+ ImplInvalidateFeature( m_aSupportedFeatures[ _rURLPath ].nFeatureId, _xListener, _bForceBroadcast );
+}
+
+// -----------------------------------------------------------------------------
+void OGenericUnoController::InvalidateFeature_Impl()
+{
+#ifdef DBG_UTIL
+ static sal_Int32 s_nRecursions = 0;
+ ++s_nRecursions;
+#endif
+
+ sal_Bool bEmpty = sal_True;
+ FeatureListener aNextFeature;
+ {
+ ::osl::MutexGuard 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::iterator aFeaturePos = ::std::find_if(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ ::std::bind2nd( CompareFeatureById(), aNextFeature.nId )
+ );
+
+#if OSL_DEBUG_LEVEL > 0
+ if ( m_aSupportedFeatures.end() == aFeaturePos )
+ {
+ ::rtl::OString sMessage( "OGenericUnoController::InvalidateFeature_Impl: feature id " );
+ sMessage += ::rtl::OString::valueOf( aNextFeature.nId );
+ sMessage += ::rtl::OString( " has been invalidated, but is not supported!" );
+ OSL_FAIL( sMessage.getStr() );
+ }
+#endif
+ if ( m_aSupportedFeatures.end() != aFeaturePos )
+ // we really know this feature
+ ImplBroadcastFeatureState( aFeaturePos->first, aNextFeature.xListener, aNextFeature.bForceBroadcast );
+ }
+
+ ::osl::MutexGuard aGuard( m_aFeatureMutex);
+ m_aFeaturesToInvalidate.pop_front();
+ bEmpty = m_aFeaturesToInvalidate.empty();
+ if (!bEmpty)
+ aNextFeature = m_aFeaturesToInvalidate.front();
+ }
+
+#ifdef DBG_UTIL
+ --s_nRecursions;
+#endif
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::ImplInvalidateFeature( sal_Int32 _nId, const Reference< XStatusListener >& _xListener, sal_Bool _bForceBroadcast )
+{
+#if OSL_DEBUG_LEVEL > 0
+ if ( _nId != -1 )
+ {
+ SupportedFeatures::iterator aFeaturePos = ::std::find_if(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ ::std::bind2nd( CompareFeatureById(), _nId )
+ );
+ OSL_ENSURE( aFeaturePos != m_aSupportedFeatures.end(), "OGenericUnoController::ImplInvalidateFeature: invalidating an unsupported feature is suspicious, at least!" );
+ }
+#endif
+
+ FeatureListener aListener;
+ aListener.nId = _nId;
+ aListener.xListener = _xListener;
+ aListener.bForceBroadcast = _bForceBroadcast;
+
+ sal_Bool bWasEmpty;
+ {
+ ::osl::MutexGuard 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, sal_Bool _bForceBroadcast)
+{
+ ImplInvalidateFeature( _nId, _xListener, _bForceBroadcast );
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::InvalidateAll()
+{
+ ImplInvalidateFeature( ALL_FEATURES, NULL, sal_True );
+}
+
+// -----------------------------------------------------------------------------
+void OGenericUnoController::InvalidateAll_Impl()
+{
+ // ---------------------------------
+ // invalidate all supported features
+
+ for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
+ aIter != m_aSupportedFeatures.end();
+ ++aIter
+ )
+ ImplBroadcastFeatureState( aIter->first, NULL, sal_True );
+
+ {
+ ::osl::MutexGuard 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 ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException )
+{
+ 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.equals( getConfirmDeletionURL() )
+ || ( ( 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) throw( RuntimeException )
+{
+ Sequence< Reference< XDispatch > > aReturn;
+ sal_Int32 nLen = aDescripts.getLength();
+ if ( nLen )
+ {
+ aReturn.realloc( nLen );
+ Reference< XDispatch >* pReturn = aReturn.getArray();
+ const Reference< XDispatch >* pReturnEnd = aReturn.getArray() + nLen;
+ const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
+
+ for ( ; pReturn != pReturnEnd; ++ pReturn, ++pDescripts )
+ {
+ *pReturn = queryDispatch( pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags );
+ }
+ }
+
+ return aReturn;
+}
+
+// -----------------------------------------------------------------------
+Reference< XDispatchProvider > OGenericUnoController::getSlaveDispatchProvider(void) throw( RuntimeException )
+{
+ return m_xSlaveDispatcher;
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::setSlaveDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider) throw( RuntimeException )
+{
+ m_xSlaveDispatcher = _xNewProvider;
+}
+
+// -----------------------------------------------------------------------
+Reference< XDispatchProvider > OGenericUnoController::getMasterDispatchProvider(void) throw( RuntimeException )
+{
+ return m_xMasterDispatcher;
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::setMasterDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider) throw( RuntimeException )
+{
+ m_xMasterDispatcher = _xNewProvider;
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::dispatch(const URL& _aURL, const Sequence< PropertyValue >& aArgs) throw(RuntimeException)
+{
+ 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#
+
+#ifdef TIMELOG
+ ::rtl::OString sLog( "OGenericUnoController::dispatch( '" );
+ sLog += ::rtl::OString( _aURL.Main.getStr(), _aURL.Main.getLength(), osl_getThreadTextEncoding() );
+ sLog += ::rtl::OString( "' )" );
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", sLog.getStr() );
+#endif
+
+ executeChecked(_aURL,aArgs);
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::addStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL) throw(RuntimeException)
+{
+ // parse the ULR 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, sal_True );
+ // force the new state to be broadcast to the new listener
+}
+
+// -----------------------------------------------------------------------
+void OGenericUnoController::removeStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL) throw(RuntimeException)
+{
+ DispatchIterator iterSearch = m_arrStatusListener.begin();
+
+ sal_Bool bRemoveForAll = (_rURL.Complete.getLength() == 0);
+ while ( iterSearch != m_arrStatusListener.end() )
+ {
+ DispatchTarget& rCurrent = *iterSearch;
+ if ( (rCurrent.xListener == aListener)
+ && ( bRemoveForAll
+ || (rCurrent.aURL.Complete.equals(_rURL.Complete))
+ )
+ )
+ {
+ m_arrStatusListener.erase( iterSearch );
+ if (!bRemoveForAll)
+ // remove the listener only for the given URL, so we can exit the loop after deletion
+ break;
+ }
+ else
+ ++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
+ StateCacheIterator aCachePos = m_aStateCache.find( aIter->second.nFeatureId );
+ if ( aCachePos != m_aStateCache.end() )
+ m_aStateCache.erase( aCachePos );
+ }
+
+ // now remove the listener from the deque
+ ::osl::MutexGuard aGuard( m_aFeatureMutex );
+ m_aFeaturesToInvalidate.erase(
+ ::std::remove_if( m_aFeaturesToInvalidate.begin(),
+ m_aFeaturesToInvalidate.end(),
+ ::std::bind2nd(FindFeatureListener(),aListener))
+ ,m_aFeaturesToInvalidate.end());
+}
+// -----------------------------------------------------------------------------
+void OGenericUnoController::releaseNumberForComponent()
+{
+ try
+ {
+ Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
+ if ( xUntitledProvider.is() )
+ xUntitledProvider->releaseNumberForComponent(static_cast<XWeak*>(this));
+ }
+ catch( const Exception& )
+ {
+ // NII
+ }
+}
+// -----------------------------------------------------------------------
+void OGenericUnoController::disposing()
+{
+ {
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = static_cast<XWeak*>(this);
+ Dispatch aStatusListener = m_arrStatusListener;
+ Dispatch::iterator aEnd = aStatusListener.end();
+ for (Dispatch::iterator aIter = aStatusListener.begin(); aIter != aEnd; ++aIter)
+ {
+ aIter->xListener->disposing(aDisposeEvent);
+ }
+ m_arrStatusListener.clear();
+ }
+
+ m_xDatabaseContext = NULL;
+ {
+ ::osl::MutexGuard 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( NULL );
+
+ m_xMasterDispatcher = NULL;
+ m_xSlaveDispatcher = NULL;
+ m_xServiceFactory = NULL;
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
+{
+ // disambiguate
+ OGenericUnoController_Base::WeakComponentImplHelperBase::addEventListener( xListener );
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::removeEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
+{
+ // disambiguate
+ OGenericUnoController_Base::WeakComponentImplHelperBase::removeEventListener( xListener );
+}
+
+//------------------------------------------------------------------------------
+void OGenericUnoController::frameAction(const FrameActionEvent& aEvent) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( aEvent.Frame == m_aCurrentFrame.getFrame() )
+ m_aCurrentFrame.frameAction( aEvent.Action );
+}
+
+//------------------------------------------------------------------------------
+void OGenericUnoController::implDescribeSupportedFeature( const sal_Char* _pAsciiCommandURL,
+ sal_uInt16 _nFeatureId, sal_Int16 _nCommandGroup )
+{
+#ifdef DBG_UTIL
+ OSL_ENSURE( m_bDescribingSupportedFeatures, "OGenericUnoController::implDescribeSupportedFeature: bad timing for this call!" );
+#endif
+ OSL_PRECOND( _nFeatureId < FIRST_USER_DEFINED_FEATURE, "OGenericUnoController::implDescribeSupportedFeature: invalid feature id!" );
+
+ ControllerFeature aFeature;
+ aFeature.Command = ::rtl::OUString::createFromAscii( _pAsciiCommandURL );
+ 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( ".uno:Copy", ID_BROWSER_COPY, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Cut", ID_BROWSER_CUT, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Paste", ID_BROWSER_PASTE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:ClipboardFormatItems", ID_BROWSER_CLIPBOARD_FORMAT_ITEMS );
+ implDescribeSupportedFeature( ".uno:DSBEditDoc", 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 = sal_True;
+ break;
+ default:
+ aReturn = m_pData->m_aUserDefinedFeatures.getState( getURLForId( _nId ) );
+ 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
+ m_pData->m_aUserDefinedFeatures.execute( 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(),
+ ::std::bind2nd( CompareFeatureById(), _nId )
+ );
+
+ if ( m_aSupportedFeatures.end() != aIter && aIter->first.getLength() )
+ {
+ aReturn.Complete = aIter->first;
+ m_xUrlTransformer->parseStrict( aReturn );
+ }
+ }
+ return aReturn;
+}
+
+//-------------------------------------------------------------------------
+bool OGenericUnoController::isUserDefinedFeature( const sal_uInt16 _nFeatureId ) const
+{
+ return ( _nFeatureId >= FIRST_USER_DEFINED_FEATURE ) && ( _nFeatureId < LAST_USER_DEFINED_FEATURE );
+}
+
+//-------------------------------------------------------------------------
+bool OGenericUnoController::isUserDefinedFeature( const ::rtl::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 ) : false;
+}
+
+//-------------------------------------------------------------------------
+sal_Bool SAL_CALL OGenericUnoController::supportsService(const ::rtl::OUString& ServiceName) throw(RuntimeException)
+{
+ Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
+
+ const ::rtl::OUString* pArray = aSupported.getConstArray();
+ const ::rtl::OUString* pArrayEnd = aSupported.getConstArray() + aSupported.getLength();
+
+ for ( ;( pArray != pArrayEnd ) && !pArray->equals( ServiceName ); ++pArray )
+ ;
+ return pArray != pArrayEnd;
+}
+
+// -----------------------------------------------------------------------------
+void OGenericUnoController::startConnectionListening(const Reference< XConnection >& _rxConnection)
+{
+ // we have to remove ourself before dispoing 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 dispoing 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,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ WaitObject aWaitCursor( getView() );
+
+ ODatasourceConnector aConnector( getORB(), getView(), ::rtl::OUString() );
+ Reference< XConnection > xConnection = aConnector.connect( _xDataSource, _pErrorInfo );
+ startConnectionListening( xConnection );
+
+ return xConnection;
+}
+// -----------------------------------------------------------------------------
+Reference< XConnection > OGenericUnoController::connect( const ::rtl::OUString& _rDataSourceName,
+ const ::rtl::OUString& _rContextInformation, ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ WaitObject aWaitCursor( getView() );
+
+ ODatasourceConnector aConnector( getORB(), getView(), _rContextInformation );
+ Reference<XConnection> xConnection = aConnector.connect( _rDataSourceName, _pErrorInfo );
+ startConnectionListening( xConnection );
+
+ return xConnection;
+}
+
+// -----------------------------------------------------------------------------
+void OGenericUnoController::showError(const SQLExceptionInfo& _rInfo)
+{
+ ::dbaui::showError(_rInfo,getView(),getORB());
+}
+// -----------------------------------------------------------------------------
+Reference< XLayoutManager > OGenericUnoController::getLayoutManager(const Reference< XFrame >& _xFrame) const
+{
+ Reference< XPropertySet > xPropSet( _xFrame, UNO_QUERY );
+ Reference< XLayoutManager > xLayoutManager;
+ if ( xPropSet.is() )
+ {
+ try
+ {
+ xLayoutManager.set(xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))),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( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )));
+ xLayoutManager->createElement( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/toolbar" )));
+ xLayoutManager->unlock();
+ xLayoutManager->doLayout();
+ }
+
+ onLoadedMenu( xLayoutManager );
+}
+
+// -----------------------------------------------------------------------------
+void OGenericUnoController::onLoadedMenu(const Reference< XLayoutManager >& /*_xLayoutManager*/)
+{
+ // not interested in
+}
+
+// -----------------------------------------------------------------------------
+void OGenericUnoController::closeTask()
+{
+ m_aAsyncCloseTask.Call();
+}
+// -----------------------------------------------------------------------------
+IMPL_LINK(OGenericUnoController, OnAsyncCloseTask, void*, EMPTYARG)
+{
+ if ( !OGenericUnoController_Base::rBHelper.bInDispose )
+ {
+ try
+ {
+ Reference< util::XCloseable > xCloseable( m_aCurrentFrame.getFrame(), UNO_QUERY_THROW );
+ xCloseable->close( sal_False ); // false - holds the owner ship for this frame inside this object!
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ return 0L;
+}
+// -----------------------------------------------------------------------------
+Any SAL_CALL OGenericUnoController::getViewData(void) throw( RuntimeException )
+{
+ return Any();
+}
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::restoreViewData(const Any& /*Data*/) throw( RuntimeException )
+{
+}
+
+// -----------------------------------------------------------------------------
+Reference< XModel > SAL_CALL OGenericUnoController::getModel(void) throw( RuntimeException )
+{
+ return Reference< XModel >();
+}
+
+// -----------------------------------------------------------------------------
+Reference< XFrame > SAL_CALL OGenericUnoController::getFrame(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ return m_aCurrentFrame.getFrame();
+}
+
+// -----------------------------------------------------------------------------
+sal_Bool SAL_CALL OGenericUnoController::attachModel(const Reference< XModel > & /*xModel*/) throw( RuntimeException )
+{
+ OSL_FAIL( "OGenericUnoController::attachModel: not supported!" );
+ return sal_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 );
+ }
+}
+// -----------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace
+{
+ ::rtl::OUString lcl_getModuleHelpModuleName( const Reference< XFrame >& _rxFrame )
+ {
+ const sal_Char* pReturn = NULL;
+
+ try
+ {
+ // get the model of the document in the given frame
+ Reference< XController > xController;
+ if ( _rxFrame.is() )
+ xController = _rxFrame->getController();
+ Reference< XModel > xModel;
+ if ( xController.is() )
+ xModel = xController->getModel();
+ Reference< XServiceInfo > xSI( xModel, UNO_QUERY );
+
+ if ( !xSI.is() )
+ { // try to go up the frame hierarchy
+
+ Reference< XFrame > xParentFrame;
+ if ( _rxFrame.is() )
+ xParentFrame = xParentFrame.query( _rxFrame->getCreator() );
+ // did we find a parent frame? Which is no top-level frame?
+ if ( xParentFrame.is() && !_rxFrame->isTop() )
+ // TODO: to prevent framework assertions, re-insert this "isTop" once 98303 is fixed
+ return lcl_getModuleHelpModuleName( xParentFrame );
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 0
+ Sequence< ::rtl::OUString > sServiceNames = xSI->getSupportedServiceNames();
+ const ::rtl::OUString* pLoop = sServiceNames.getConstArray();
+ for ( sal_Int32 i=0; i<sServiceNames.getLength(); ++i, ++pLoop )
+ {
+ sal_Int32 nDummy = 0;
+ (void)nDummy;
+ }
+#endif
+
+ // check which service we know ....
+ static const sal_Char* pTransTable[] = {
+ "com.sun.star.sdb.OfficeDatabaseDocument","sdatabase",
+ "com.sun.star.report.ReportDefinition","sdatabase",
+ "com.sun.star.text.TextDocument", "swriter",
+ "com.sun.star.sheet.SpreadsheetDocument", "scalc",
+ "com.sun.star.presentation.PresentationDocument", "simpress",
+ "com.sun.star.drawing.DrawingDocument", "sdraw",
+ "com.sun.star.formula.FormularProperties", "smath",
+ "com.sun.star.chart.ChartDocument", "schart"
+ };
+ OSL_ENSURE( ( SAL_N_ELEMENTS( pTransTable ) ) % 2 == 0,
+ "lcl_getModuleHelpModuleName: odd size of translation table!" );
+
+ // loop through the table
+ sal_Int32 nTableEntries = ( SAL_N_ELEMENTS( pTransTable ) ) / 2;
+ const sal_Char** pDocumentService = pTransTable;
+ const sal_Char** pHelpModuleName = pTransTable + 1;
+ for ( sal_Int32 j=0; j<nTableEntries; ++j )
+ {
+ if ( xSI->supportsService( ::rtl::OUString::createFromAscii( *pDocumentService ) ) )
+ { // found a table entry which matches the model's services
+ pReturn = *pHelpModuleName;
+ break;
+ }
+
+ ++pDocumentService; ++pDocumentService;
+ ++pHelpModuleName; ++pHelpModuleName;
+ }
+ }
+
+ if ( !pReturn )
+ {
+ // could not determine the document type we're living in
+ // ->fallback
+ SvtModuleOptions aModOpt;
+ if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
+ pReturn = "swriter";
+ else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
+ pReturn = "sdatabase";
+ else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
+ pReturn = "scalc";
+ else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
+ pReturn = "simpress";
+ else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
+ pReturn = "sdraw";
+ else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
+ pReturn = "smath";
+ else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCHART ) )
+ pReturn = "schart";
+ else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SBASIC ) )
+ pReturn = "sbasic";
+ else
+ {
+ OSL_FAIL( "lcl_getModuleHelpModuleName: no installed module found" );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ if ( !pReturn )
+ pReturn = "swriter";
+
+ return ::rtl::OUString::createFromAscii( pReturn );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void OGenericUnoController::openHelpAgent(rtl::OUString const& _suHelpStringURL )
+{
+ rtl::OUString suURL(_suHelpStringURL);
+ rtl::OUString sLanguage(RTL_CONSTASCII_USTRINGPARAM("Language="));
+ if (suURL.indexOf(sLanguage) == -1)
+ {
+ AppendConfigToken(suURL, sal_False /* sal_False := add '&' */ );
+ }
+ URL aURL;
+ aURL.Complete = suURL;
+
+ openHelpAgent( aURL );
+}
+
+void OGenericUnoController::openHelpAgent(const rtl::OString& _sHelpId)
+{
+ openHelpAgent( createHelpAgentURL( lcl_getModuleHelpModuleName( getFrame() ), _sHelpId ) );
+}
+
+void OGenericUnoController::openHelpAgent( const URL& _rURL )
+{
+ try
+ {
+ URL aURL( _rURL );
+
+ if ( m_xUrlTransformer.is() )
+ m_xUrlTransformer->parseStrict(aURL);
+
+ Reference< XDispatchProvider > xDispProv( m_aCurrentFrame.getFrame(), UNO_QUERY );
+ Reference< XDispatch > xHelpDispatch;
+ if ( xDispProv.is() )
+ xHelpDispatch = xDispProv->queryDispatch(aURL, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_helpagent")), FrameSearchFlag::PARENT | FrameSearchFlag::SELF);
+ OSL_ENSURE(xHelpDispatch.is(), "SbaTableQueryBrowser::openHelpAgent: could not get a dispatcher!");
+ if (xHelpDispatch.is())
+ {
+ xHelpDispatch->dispatch(aURL, Sequence< PropertyValue >());
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+// -----------------------------------------------------------------------------
+Reference< awt::XWindow> OGenericUnoController::getTopMostContainerWindow() const
+{
+ Reference< ::com::sun::star::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.set( xFrame->getCreator(), UNO_QUERY );
+ }
+ if ( xFrame.is() )
+ xWindow = xFrame->getContainerWindow();
+ }
+ return xWindow;
+}
+// -----------------------------------------------------------------------------
+Reference< XTitle > OGenericUnoController::impl_getTitleHelper_throw()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( ! m_xTitleHelper.is ())
+ {
+ Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
+ Reference< XController > xThis(static_cast< XController* >(this), UNO_QUERY_THROW);
+
+ ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(m_xServiceFactory);
+ m_xTitleHelper.set( static_cast< ::cppu::OWeakObject* >(pHelper), UNO_QUERY_THROW);
+
+ pHelper->setOwner (xThis );
+ pHelper->connectWithUntitledNumbers (xUntitledProvider);
+ }
+
+ return m_xTitleHelper;
+}
+
+//=============================================================================
+// XTitle
+::rtl::OUString SAL_CALL OGenericUnoController::getTitle()
+ throw (RuntimeException)
+{
+ ::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 ::rtl::OUString& sTitle)
+ throw (RuntimeException)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ m_bExternalTitle = sal_True;
+ impl_getTitleHelper_throw()->setTitle (sTitle);
+}
+
+//=============================================================================
+// XTitleChangeBroadcaster
+void SAL_CALL OGenericUnoController::addTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
+ throw (RuntimeException)
+{
+ Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
+ if (xBroadcaster.is ())
+ xBroadcaster->addTitleChangeListener (xListener);
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::removeTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
+ throw (RuntimeException)
+{
+ Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
+ if (xBroadcaster.is ())
+ xBroadcaster->removeTitleChangeListener (xListener);
+}
+
+// =============================================================================
+// XUserInputInterception
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::addKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException)
+{
+ if ( _rxHandler.is() )
+ m_pData->m_aUserInputInterception.addKeyHandler( _rxHandler );
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException)
+{
+ m_pData->m_aUserInputInterception.removeKeyHandler( _rxHandler );
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException)
+{
+ if ( _rxHandler.is() )
+ m_pData->m_aUserInputInterception.addMouseClickHandler( _rxHandler );
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL OGenericUnoController::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException)
+{
+ m_pData->m_aUserInputInterception.removeMouseClickHandler( _rxHandler );
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+void OGenericUnoController::executeChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
+{
+ if ( isCommandEnabled(_nCommandId) )
+ Execute(_nCommandId, aArgs);
+}
+
+// -----------------------------------------------------------------------------
+sal_Bool OGenericUnoController::isCommandEnabled(sal_uInt16 _nCommandId) const
+{
+ return GetState( _nCommandId ).bEnabled;
+}
+
+// -----------------------------------------------------------------------------
+sal_uInt16 OGenericUnoController::registerCommandURL( const ::rtl::OUString& _rCompleteCommandURL )
+{
+ if ( !_rCompleteCommandURL.getLength() )
+ return 0;
+
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL );
+ if ( aIter != m_aSupportedFeatures.end() )
+ return aIter->second.nFeatureId;
+
+ // this is a previously unkwnon command
+ sal_uInt16 nFeatureId = FIRST_USER_DEFINED_FEATURE;
+ while ( isFeatureSupported( nFeatureId ) && ( nFeatureId < LAST_USER_DEFINED_FEATURE ) )
+ ++nFeatureId;
+ if ( nFeatureId == LAST_USER_DEFINED_FEATURE )
+ {
+ OSL_FAIL( "OGenericUnoController::registerCommandURL: no more space for user defined features!" );
+ return 0L;
+ }
+
+ ControllerFeature aFeature;
+ aFeature.Command = _rCompleteCommandURL;
+ aFeature.nFeatureId = nFeatureId;
+ aFeature.GroupId = CommandGroup::INTERNAL;
+ m_aSupportedFeatures[ aFeature.Command ] = aFeature;
+
+ return nFeatureId;
+}
+
+// -----------------------------------------------------------------------------
+void OGenericUnoController::notifyHiContrastChanged()
+{
+}
+
+// -----------------------------------------------------------------------------
+sal_Bool OGenericUnoController::isDataSourceReadOnly() const
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------------
+Reference< XController > OGenericUnoController::getXController() throw( RuntimeException )
+{
+ return this;
+}
+
+// -----------------------------------------------------------------------------
+bool OGenericUnoController::interceptUserInput( const NotifyEvent& _rEvent )
+{
+ return m_pData->m_aUserInputInterception.handleNotifyEvent( _rEvent );
+}
+
+// -----------------------------------------------------------------------------
+sal_Bool OGenericUnoController::isCommandChecked(sal_uInt16 _nCommandId) const
+{
+ FeatureState aState = GetState( _nCommandId );
+
+ return aState.bChecked && (sal_Bool)*aState.bChecked;
+}
+// -----------------------------------------------------------------------------
+sal_Bool OGenericUnoController::isCommandEnabled( const ::rtl::OUString& _rCompleteCommandURL ) const
+{
+ OSL_ENSURE( _rCompleteCommandURL.getLength(), "OGenericUnoController::isCommandEnabled: Empty command url!" );
+
+ sal_Bool bIsEnabled = sal_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() throw (RuntimeException)
+{
+ CommandHashMap aCmdHashMap;
+ for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
+ aIter != m_aSupportedFeatures.end();
+ ++aIter
+ )
+ if ( aIter->second.GroupId != CommandGroup::INTERNAL )
+ aCmdHashMap.insert( CommandHashMap::value_type( aIter->second.GroupId, 0 ));
+
+ Sequence< sal_Int16 > aCommandGroups( aCmdHashMap.size() );
+ ::std::transform( aCmdHashMap.begin(),
+ aCmdHashMap.end(),
+ aCommandGroups.getArray(),
+ ::o3tl::select1st< CommandHashMap::value_type >()
+ );
+
+ return aCommandGroups;
+}
+
+namespace
+{
+ //Current c++0x draft (apparently) has std::identity, but not operator()
+ template<typename T> struct SGI_identity : public std::unary_function<T,T>
+ {
+ T& operator()(T& x) const { return x; }
+ const T& operator()(const T& x) const { return x; }
+ };
+}
+
+// -----------------------------------------------------------------------------
+Sequence< DispatchInformation > SAL_CALL OGenericUnoController::getConfigurableDispatchInformation( ::sal_Int16 CommandGroup ) throw (RuntimeException)
+{
+ DispatchInfoList aInformationList;
+ DispatchInformation aDispatchInfo;
+ for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
+ aIter != m_aSupportedFeatures.end();
+ ++aIter
+ )
+ {
+ if ( sal_Int16( aIter->second.GroupId ) == CommandGroup )
+ {
+ aDispatchInfo = aIter->second;
+ aInformationList.push_back( aDispatchInfo );
+ }
+ }
+
+ Sequence< DispatchInformation > aInformation( aInformationList.size() );
+ ::std::transform( aInformationList.begin(),
+ aInformationList.end(),
+ aInformation.getArray(),
+ SGI_identity< DispatchInformation >()
+ );
+
+ return aInformation;
+}
+// -----------------------------------------------------------------------------
+void OGenericUnoController::fillSupportedFeatures()
+{
+#ifdef DBG_UTIL
+ m_bDescribingSupportedFeatures = true;
+#endif
+ describeSupportedFeatures();
+// -----------------------------------------------------------------------------
+#ifdef DBG_UTIL
+ m_bDescribingSupportedFeatures = false;
+#endif
+}
+
+
+void SAL_CALL OGenericUnoController::dispose() throw(::com::sun::star::uno::RuntimeException)
+{
+ SolarMutexGuard aSolarGuard;
+ OGenericUnoController_Base::dispose();
+}
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */