Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / dbaccess / source / ui / browser / genericcontroller.cxx
blob4283d7eed1802d30e02acfb82fc4a44b81bbf71a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "genericcontroller.hxx"
30 #include <comphelper/uno3.hxx>
31 #include <toolkit/awt/vclxwindow.hxx>
32 #include "browserids.hxx"
33 #include <vcl/svapp.hxx>
34 #include <toolkit/helper/vclunohelper.hxx>
35 #include "dataview.hxx"
36 #include <tools/diagnose_ex.h>
37 #include <osl/diagnose.h>
38 #include "dbustrings.hrc"
39 #include <vcl/stdtext.hxx>
40 #include <cppuhelper/typeprovider.hxx>
41 #include <framework/titlehelper.hxx>
42 #include <comphelper/sequence.hxx>
43 #include <comphelper/extract.hxx>
44 #include <com/sun/star/sdbc/XDataSource.hpp>
45 #include <com/sun/star/sdb/SQLContext.hpp>
46 #include <com/sun/star/sdb/XCompletedConnection.hpp>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/task/XInteractionHandler.hpp>
49 #include <com/sun/star/util/XCloseable.hpp>
50 #include "UITools.hxx"
51 #include "commontypes.hxx"
53 #include <vcl/waitobj.hxx>
54 #include <svl/urihelper.hxx>
55 #include "datasourceconnector.hxx"
56 #include <unotools/moduleoptions.hxx>
57 #include <com/sun/star/frame/FrameSearchFlag.hpp>
58 #include <com/sun/star/frame/status/Visibility.hpp>
59 #include <com/sun/star/util/XModifiable.hpp>
60 #include <rtl/ustring.hxx>
61 #include <rtl/logfile.hxx>
62 #include <algorithm>
63 #include <o3tl/compat_functional.hxx>
64 #include <boost/unordered_map.hpp>
65 #include <cppuhelper/implbase1.hxx>
66 #include <limits>
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::frame;
72 using namespace ::com::sun::star::frame::status;
73 using namespace ::com::sun::star::util;
74 using namespace ::com::sun::star::lang;
75 using namespace ::com::sun::star::container;
76 using namespace ::com::sun::star::sdbc;
77 using namespace ::com::sun::star::sdb;
78 using namespace ::com::sun::star::task;
79 using namespace ::com::sun::star::awt;
80 using namespace ::com::sun::star;
81 using namespace ::dbtools;
82 using namespace ::comphelper;
84 // -------------------------------------------------------------------------
85 #define ALL_FEATURES -1
86 #define FIRST_USER_DEFINED_FEATURE ( ::std::numeric_limits< sal_uInt16 >::max() - 1000 )
87 #define LAST_USER_DEFINED_FEATURE ( ::std::numeric_limits< sal_uInt16 >::max() )
89 // -------------------------------------------------------------------------
90 typedef ::boost::unordered_map< sal_Int16, sal_Int16 > CommandHashMap;
91 typedef ::std::list< DispatchInformation > DispatchInfoList;
94 // -------------------------------------------------------------------------
95 const ::rtl::OUString& getConfirmDeletionURL()
97 static const ::rtl::OUString sConfirmDeletionURL( RTL_CONSTASCII_USTRINGPARAM( ".uno:FormSlots/ConfirmDeletion" ) );
98 return sConfirmDeletionURL;
101 namespace dbaui
104 //==========================================================================
105 //= UserDefinedFeatures
106 //==========================================================================
107 class UserDefinedFeatures
109 public:
110 UserDefinedFeatures( const Reference< XController >& _rxController );
112 FeatureState getState( const URL& _rFeatureURL );
113 void execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs );
115 private:
116 ::com::sun::star::uno::WeakReference< XController > m_aController;
119 //--------------------------------------------------------------------------
120 UserDefinedFeatures::UserDefinedFeatures( const Reference< XController >& _rxController )
121 :m_aController( _rxController )
125 //--------------------------------------------------------------------------
126 FeatureState UserDefinedFeatures::getState( const URL& /*_rFeatureURL*/ )
128 // for now, enable all the time
129 // TODO: we should ask the dispatcher. However, this is laborious, since you cannot ask a dispatcher
130 // directly, but need to add a status listener.
131 FeatureState aState;
132 aState.bEnabled = sal_True;
133 return aState;
136 //--------------------------------------------------------------------------
137 void UserDefinedFeatures::execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs )
141 Reference< XController > xController( (Reference< XController >)m_aController, UNO_SET_THROW );
142 Reference< XDispatchProvider > xDispatchProvider( xController->getFrame(), UNO_QUERY_THROW );
143 Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch(
144 _rFeatureURL,
145 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ),
146 FrameSearchFlag::AUTO
147 ) );
149 if ( xDispatch == xController )
151 OSL_FAIL( "UserDefinedFeatures::execute: the controller shouldn't be the dispatcher here!" );
152 xDispatch.clear();
155 if ( xDispatch.is() )
156 xDispatch->dispatch( _rFeatureURL, _rArgs );
158 catch( const Exception& )
160 DBG_UNHANDLED_EXCEPTION();
164 //==========================================================================
165 //= OGenericUnoController_Data
166 //==========================================================================
167 struct OGenericUnoController_Data
169 ::sfx2::UserInputInterception m_aUserInputInterception;
170 UserDefinedFeatures m_aUserDefinedFeatures;
172 OGenericUnoController_Data( OGenericUnoController& _rController, ::osl::Mutex& _rMutex )
173 :m_aUserInputInterception( _rController, _rMutex )
174 ,m_aUserDefinedFeatures( _rController.getXController() )
179 //==========================================================================
180 //= OGenericUnoController
181 //==========================================================================
182 DBG_NAME(OGenericUnoController)
183 // -------------------------------------------------------------------------
184 OGenericUnoController::OGenericUnoController(const Reference< XMultiServiceFactory >& _rM)
185 :OGenericUnoController_Base( getMutex() )
186 ,m_pView(NULL)
187 #ifdef DBG_UTIL
188 ,m_bDescribingSupportedFeatures( false )
189 #endif
190 ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
191 ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
192 ,m_xServiceFactory(_rM)
193 ,m_aCurrentFrame( *this )
194 ,m_bPreview(sal_False)
195 ,m_bReadOnly(sal_False)
196 ,m_bCurrentlyModified(sal_False)
197 ,m_bExternalTitle(sal_False)
199 osl_incrementInterlockedCount( &m_refCount );
201 m_pData.reset( new OGenericUnoController_Data( *this, getMutex() ) );
203 osl_decrementInterlockedCount( &m_refCount );
205 DBG_CTOR(OGenericUnoController,NULL);
209 m_xUrlTransformer = Reference< XURLTransformer > (_rM->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), UNO_QUERY);
211 catch(Exception&)
213 DBG_UNHANDLED_EXCEPTION();
217 #ifdef WNT
218 // -----------------------------------------------------------------------------
219 OGenericUnoController::OGenericUnoController()
220 :OGenericUnoController_Base( getMutex() )
221 ,m_pView(NULL)
222 #ifdef DBG_UTIL
223 ,m_bDescribingSupportedFeatures( false )
224 #endif
225 ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
226 ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
227 ,m_aCurrentFrame( *this )
228 ,m_bPreview(sal_False)
229 ,m_bReadOnly(sal_False)
230 ,m_bCurrentlyModified(sal_False)
232 OSL_FAIL( "OGenericUnoController::OGenericUnoController: illegal call!" );
233 // This ctor only exists because the MSVC compiler complained about an unresolved external
234 // symbol. It should not be used at all. Since using it yields strange runtime problems,
235 // we simply abort here.
236 abort();
238 #endif
240 // -----------------------------------------------------------------------------
241 OGenericUnoController::~OGenericUnoController()
244 DBG_DTOR(OGenericUnoController,NULL);
247 // -----------------------------------------------------------------------------
248 sal_Bool OGenericUnoController::Construct(Window* /*pParent*/)
250 OSL_ENSURE( getView(), "the view is NULL!" );
252 if ( getView() )
254 getView()->Construct();
255 getView()->Show();
258 m_aSupportedFeatures.clear();
259 fillSupportedFeatures();
261 // create the database context
262 OSL_ENSURE(getORB().is(), "OGenericUnoController::Construct need a service factory!");
265 m_xDatabaseContext = Reference< XNameAccess >(getORB()->createInstance(SERVICE_SDB_DATABASECONTEXT), UNO_QUERY);
267 catch(Exception&)
269 OSL_FAIL("OGenericUnoController::Construct: could not create (or start listening at) the database context!");
272 if (!m_xDatabaseContext.is())
273 { // at least notify the user. Though the whole component does not make any sense without the database context ...
274 ShowServiceNotAvailableError(getView(), String(SERVICE_SDB_DATABASECONTEXT), sal_True);
276 return sal_True;
278 //------------------------------------------------------------------------------
279 IMPL_LINK_NOARG(OGenericUnoController, OnAsyncInvalidateAll)
281 if ( !OGenericUnoController_Base::rBHelper.bInDispose && !OGenericUnoController_Base::rBHelper.bDisposed )
282 InvalidateFeature_Impl();
283 return 0L;
285 // -----------------------------------------------------------------------------
286 void OGenericUnoController::impl_initialize()
289 // -------------------------------------------------------------------------
290 void SAL_CALL OGenericUnoController::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException)
292 SolarMutexGuard aSolarGuard;
293 ::osl::MutexGuard aGuard( getMutex() );
295 Reference< XWindow > xParent;
296 Reference< XFrame > xFrame;
298 PropertyValue aValue;
299 const Any* pIter = aArguments.getConstArray();
300 const Any* pEnd = pIter + aArguments.getLength();
302 for ( ; pIter != pEnd; ++pIter )
304 if ( ( *pIter >>= aValue ) && ( 0 == aValue.Name.compareToAscii( "Frame" ) ) )
306 xFrame.set(aValue.Value,UNO_QUERY_THROW);
308 else if ( ( *pIter >>= aValue ) && ( 0 == aValue.Name.compareToAscii( "Preview" ) ) )
310 aValue.Value >>= m_bPreview;
311 m_bReadOnly = sal_True;
316 if ( !xFrame.is() )
317 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "need a frame" ) ), *this, 1 );
319 xParent = xFrame->getContainerWindow();
320 VCLXWindow* pParentComponent = VCLXWindow::GetImplementation(xParent);
321 Window* pParentWin = pParentComponent ? pParentComponent->GetWindow() : NULL;
322 if (!pParentWin)
324 throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Parent window is null")), *this, 1 );
327 m_aInitParameters.assign( aArguments );
328 Construct( pParentWin );
330 ODataView* pView = getView();
331 if ( !pView )
332 throw RuntimeException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unable to create a view")), *this );
334 if ( m_bReadOnly || m_bPreview )
335 pView->EnableInput( sal_False );
337 impl_initialize();
339 catch(Exception&)
341 // no one clears my view if I won't
342 ::std::auto_ptr<Window> aTemp(m_pView);
343 m_pView = NULL;
344 throw;
348 //------------------------------------------------------------------------------
349 void SAL_CALL OGenericUnoController::acquire( ) throw ()
351 OGenericUnoController_Base::acquire();
354 //------------------------------------------------------------------------------
355 void SAL_CALL OGenericUnoController::release( ) throw ()
357 OGenericUnoController_Base::release();
360 // -------------------------------------------------------------------------
361 void OGenericUnoController::startFrameListening( const Reference< XFrame >& _rxFrame )
363 if ( _rxFrame.is() )
364 _rxFrame->addFrameActionListener( this );
367 // -------------------------------------------------------------------------
368 void OGenericUnoController::stopFrameListening( const Reference< XFrame >& _rxFrame )
370 if ( _rxFrame.is() )
371 _rxFrame->removeFrameActionListener( this );
374 // -------------------------------------------------------------------------
375 void OGenericUnoController::disposing(const EventObject& Source) throw( RuntimeException )
377 // our frame ?
378 if ( Source.Source == getFrame() )
379 stopFrameListening( getFrame() );
381 //------------------------------------------------------------------------
382 void OGenericUnoController::modified(const EventObject& aEvent) throw( RuntimeException )
384 ::osl::MutexGuard aGuard( getMutex() );
385 if ( !isDataSourceReadOnly() )
387 Reference<XModifiable> xModi(aEvent.Source,UNO_QUERY);
388 if ( xModi.is() )
389 m_bCurrentlyModified = xModi->isModified(); // can only be reset by save
390 else
391 m_bCurrentlyModified = sal_True;
393 InvalidateFeature(ID_BROWSER_SAVEDOC);
394 InvalidateFeature(ID_BROWSER_UNDO);
396 // -----------------------------------------------------------------------
397 Reference< XWindow > SAL_CALL OGenericUnoController::getComponentWindow() throw (RuntimeException)
399 return VCLUnoHelper::GetInterface( getView() );
402 // -----------------------------------------------------------------------
403 ::rtl::OUString SAL_CALL OGenericUnoController::getViewControllerName() throw (::com::sun::star::uno::RuntimeException)
405 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Default" ) );
408 // -----------------------------------------------------------------------
409 Sequence< PropertyValue > SAL_CALL OGenericUnoController::getCreationArguments() throw (RuntimeException)
411 // currently we do not support any creation args, so anything passed to XModel2::createViewController would be
412 // lost, so we can equally return an empty sequence here
413 return Sequence< PropertyValue >();
416 // -----------------------------------------------------------------------
417 void OGenericUnoController::attachFrame( const Reference< XFrame >& _rxFrame ) throw( RuntimeException )
419 SolarMutexGuard aSolarGuard;
420 ::osl::MutexGuard aGuard( getMutex() );
422 stopFrameListening( m_aCurrentFrame.getFrame() );
423 Reference< XFrame > xFrame = m_aCurrentFrame.attachFrame( _rxFrame );
424 startFrameListening( xFrame );
426 loadMenu( xFrame );
428 if ( getView() )
429 getView()->attachFrame( xFrame );
432 // -----------------------------------------------------------------------------
433 struct CommandCollector : public ::std::unary_function< SupportedFeatures::value_type, void>
435 sal_uInt16 m_nFeature;
436 StringBag& m_rFeatureCommands;
437 CommandCollector( sal_uInt16 _nFeature, StringBag& _rFeatureCommands )
438 :m_nFeature ( _nFeature )
439 ,m_rFeatureCommands( _rFeatureCommands )
443 void operator() ( const SupportedFeatures::value_type& lhs )
445 if ( lhs.second.nFeatureId == m_nFeature )
446 m_rFeatureCommands.insert( lhs.first );
450 // -----------------------------------------------------------------------
451 namespace
453 typedef ::std::vector< Any > States;
455 // ...................................................................
456 void lcl_notifyMultipleStates( XStatusListener& _rListener, FeatureStateEvent& _rEvent, const States& _rStates )
458 for ( States::const_iterator state = _rStates.begin();
459 state != _rStates.end();
460 ++state
463 _rEvent.State = *state;
464 _rListener.statusChanged( _rEvent );
468 // ...................................................................
469 void lcl_collectStates( const FeatureState& _rFeatureState, States& _out_rStates )
471 // order matters, due to a bug in framework which resets the check state when any non-boolean event
472 // arrives
473 // #i68215# is the bug to (re-)introduce this "ordered" notification here
474 // #i67882# is the bug which was caused by the real fix which we did in framework
475 // #i68216# is the bug which requests to fix the code in Draw which relies on
476 // framework's implementation details
477 if ( !!_rFeatureState.sTitle )
478 _out_rStates.push_back( makeAny( *_rFeatureState.sTitle ) );
479 if ( !!_rFeatureState.bChecked )
480 _out_rStates.push_back( makeAny( (sal_Bool)*_rFeatureState.bChecked ) );
481 if ( !!_rFeatureState.bInvisible )
482 _out_rStates.push_back( makeAny( Visibility( !*_rFeatureState.bInvisible ) ) );
483 if ( _rFeatureState.aValue.hasValue() )
484 _out_rStates.push_back( _rFeatureState.aValue );
485 if ( _out_rStates.empty() )
486 _out_rStates.push_back( Any() );
490 // -----------------------------------------------------------------------
491 void OGenericUnoController::ImplBroadcastFeatureState(const ::rtl::OUString& _rFeature, const Reference< XStatusListener > & xListener, sal_Bool _bIgnoreCache)
493 sal_uInt16 nFeat = m_aSupportedFeatures[ _rFeature ].nFeatureId;
494 FeatureState aFeatState( GetState( nFeat ) );
496 FeatureState& rCachedState = m_aStateCache[nFeat]; // creates if neccessary
497 if ( !_bIgnoreCache )
499 // check if we really need to notify the listeners : this method may be called much more often than needed, so check
500 // the cached state of the feature
501 sal_Bool bAlreadyCached = ( m_aStateCache.find(nFeat) != m_aStateCache.end() );
502 if ( bAlreadyCached )
503 if ( ( rCachedState.bEnabled == aFeatState.bEnabled )
504 && ( rCachedState.bChecked == aFeatState.bChecked )
505 && ( rCachedState.bInvisible == aFeatState.bInvisible )
506 && ( rCachedState.sTitle == aFeatState.sTitle )
508 return;
510 rCachedState = aFeatState;
512 FeatureStateEvent aEvent;
513 aEvent.FeatureURL.Complete = _rFeature;
514 if (m_xUrlTransformer.is())
515 m_xUrlTransformer->parseStrict(aEvent.FeatureURL);
516 aEvent.Source = (XDispatch*)this;
517 aEvent.IsEnabled = aFeatState.bEnabled;
519 // collect all states to be notified
520 States aStates;
521 lcl_collectStates( aFeatState, aStates );
523 // a special listener ?
524 if ( xListener.is() )
525 lcl_notifyMultipleStates( *xListener.get(), aEvent, aStates );
526 else
527 { // no -> iterate through all listeners responsible for the URL
528 StringBag aFeatureCommands;
529 ::std::for_each(
530 m_aSupportedFeatures.begin(),
531 m_aSupportedFeatures.end(),
532 CommandCollector( nFeat, aFeatureCommands )
535 // it is possible that listeners are registered or revoked while
536 // we are notifying them, so we must use a copy of m_arrStatusListener, not
537 // m_arrStatusListener itself
538 Dispatch aNotifyLoop( m_arrStatusListener );
539 DispatchIterator iterSearch = aNotifyLoop.begin();
540 DispatchIterator iterEnd = aNotifyLoop.end();
542 while (iterSearch != iterEnd)
544 DispatchTarget& rCurrent = *iterSearch;
545 if ( aFeatureCommands.find( rCurrent.aURL.Complete ) != aFeatureCommands.end() )
547 aEvent.FeatureURL = rCurrent.aURL;
548 lcl_notifyMultipleStates( *rCurrent.xListener.get(), aEvent, aStates );
550 ++iterSearch;
556 //------------------------------------------------------------------------------
557 sal_Bool OGenericUnoController::isFeatureSupported( sal_Int32 _nId )
559 SupportedFeatures::iterator aFeaturePos = ::std::find_if(
560 m_aSupportedFeatures.begin(),
561 m_aSupportedFeatures.end(),
562 ::std::bind2nd( CompareFeatureById(), _nId )
565 return ( m_aSupportedFeatures.end() != aFeaturePos && !aFeaturePos->first.isEmpty());
568 // -----------------------------------------------------------------------
569 void OGenericUnoController::InvalidateFeature(const ::rtl::OUString& _rURLPath, const Reference< XStatusListener > & _xListener, sal_Bool _bForceBroadcast)
571 ImplInvalidateFeature( m_aSupportedFeatures[ _rURLPath ].nFeatureId, _xListener, _bForceBroadcast );
574 // -----------------------------------------------------------------------------
575 void OGenericUnoController::InvalidateFeature_Impl()
577 #ifdef DBG_UTIL
578 static sal_Int32 s_nRecursions = 0;
579 ++s_nRecursions;
580 #endif
582 sal_Bool bEmpty = sal_True;
583 FeatureListener aNextFeature;
585 ::osl::MutexGuard aGuard( m_aFeatureMutex);
586 bEmpty = m_aFeaturesToInvalidate.empty();
587 if (!bEmpty)
588 aNextFeature = m_aFeaturesToInvalidate.front();
590 while(!bEmpty)
592 if ( ALL_FEATURES == aNextFeature.nId )
594 InvalidateAll_Impl();
595 break;
597 else
599 SupportedFeatures::iterator aFeaturePos = ::std::find_if(
600 m_aSupportedFeatures.begin(),
601 m_aSupportedFeatures.end(),
602 ::std::bind2nd( CompareFeatureById(), aNextFeature.nId )
605 #if OSL_DEBUG_LEVEL > 0
606 if ( m_aSupportedFeatures.end() == aFeaturePos )
608 ::rtl::OString sMessage( "OGenericUnoController::InvalidateFeature_Impl: feature id " );
609 sMessage += ::rtl::OString::valueOf( aNextFeature.nId );
610 sMessage += ::rtl::OString( " has been invalidated, but is not supported!" );
611 OSL_FAIL( sMessage.getStr() );
613 #endif
614 if ( m_aSupportedFeatures.end() != aFeaturePos )
615 // we really know this feature
616 ImplBroadcastFeatureState( aFeaturePos->first, aNextFeature.xListener, aNextFeature.bForceBroadcast );
619 ::osl::MutexGuard aGuard( m_aFeatureMutex);
620 m_aFeaturesToInvalidate.pop_front();
621 bEmpty = m_aFeaturesToInvalidate.empty();
622 if (!bEmpty)
623 aNextFeature = m_aFeaturesToInvalidate.front();
626 #ifdef DBG_UTIL
627 --s_nRecursions;
628 #endif
631 // -----------------------------------------------------------------------
632 void OGenericUnoController::ImplInvalidateFeature( sal_Int32 _nId, const Reference< XStatusListener >& _xListener, sal_Bool _bForceBroadcast )
634 #if OSL_DEBUG_LEVEL > 0
635 if ( _nId != -1 )
637 SupportedFeatures::iterator aFeaturePos = ::std::find_if(
638 m_aSupportedFeatures.begin(),
639 m_aSupportedFeatures.end(),
640 ::std::bind2nd( CompareFeatureById(), _nId )
642 OSL_ENSURE( aFeaturePos != m_aSupportedFeatures.end(), "OGenericUnoController::ImplInvalidateFeature: invalidating an unsupported feature is suspicious, at least!" );
644 #endif
646 FeatureListener aListener;
647 aListener.nId = _nId;
648 aListener.xListener = _xListener;
649 aListener.bForceBroadcast = _bForceBroadcast;
651 sal_Bool bWasEmpty;
653 ::osl::MutexGuard aGuard( m_aFeatureMutex );
654 bWasEmpty = m_aFeaturesToInvalidate.empty();
655 m_aFeaturesToInvalidate.push_back( aListener );
658 if ( bWasEmpty )
659 m_aAsyncInvalidateAll.Call();
662 // -----------------------------------------------------------------------
663 void OGenericUnoController::InvalidateFeature(sal_uInt16 _nId, const Reference< XStatusListener > & _xListener, sal_Bool _bForceBroadcast)
665 ImplInvalidateFeature( _nId, _xListener, _bForceBroadcast );
668 // -----------------------------------------------------------------------
669 void OGenericUnoController::InvalidateAll()
671 ImplInvalidateFeature( ALL_FEATURES, NULL, sal_True );
674 // -----------------------------------------------------------------------------
675 void OGenericUnoController::InvalidateAll_Impl()
677 // ---------------------------------
678 // invalidate all supported features
680 for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
681 aIter != m_aSupportedFeatures.end();
682 ++aIter
684 ImplBroadcastFeatureState( aIter->first, NULL, sal_True );
687 ::osl::MutexGuard aGuard( m_aFeatureMutex);
688 OSL_ENSURE(m_aFeaturesToInvalidate.size(), "OGenericUnoController::InvalidateAll_Impl: to be called from within InvalidateFeature_Impl only!");
689 m_aFeaturesToInvalidate.pop_front();
690 if(!m_aFeaturesToInvalidate.empty())
691 m_aAsyncInvalidateAll.Call();
695 // -----------------------------------------------------------------------
696 Reference< XDispatch > OGenericUnoController::queryDispatch(const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException )
698 Reference< XDispatch > xReturn;
700 OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::queryDispatch: shouldn't this be filled at construction time?" );
701 if ( m_aSupportedFeatures.empty() )
702 fillSupportedFeatures();
704 // URL's we can handle ourself?
705 if ( aURL.Complete.equals( getConfirmDeletionURL() )
706 || ( ( m_aSupportedFeatures.find( aURL.Complete ) != m_aSupportedFeatures.end() )
707 && !isUserDefinedFeature( aURL.Complete )
711 xReturn = this;
713 // no? -> ask the slave dispatcher
714 else if ( m_xSlaveDispatcher.is() )
716 xReturn = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
719 // outta here
720 return xReturn;
723 // -----------------------------------------------------------------------
724 Sequence< Reference< XDispatch > > OGenericUnoController::queryDispatches(const Sequence< DispatchDescriptor >& aDescripts) throw( RuntimeException )
726 Sequence< Reference< XDispatch > > aReturn;
727 sal_Int32 nLen = aDescripts.getLength();
728 if ( nLen )
730 aReturn.realloc( nLen );
731 Reference< XDispatch >* pReturn = aReturn.getArray();
732 const Reference< XDispatch >* pReturnEnd = aReturn.getArray() + nLen;
733 const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
735 for ( ; pReturn != pReturnEnd; ++ pReturn, ++pDescripts )
737 *pReturn = queryDispatch( pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags );
741 return aReturn;
744 // -----------------------------------------------------------------------
745 Reference< XDispatchProvider > OGenericUnoController::getSlaveDispatchProvider(void) throw( RuntimeException )
747 return m_xSlaveDispatcher;
750 // -----------------------------------------------------------------------
751 void OGenericUnoController::setSlaveDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider) throw( RuntimeException )
753 m_xSlaveDispatcher = _xNewProvider;
756 // -----------------------------------------------------------------------
757 Reference< XDispatchProvider > OGenericUnoController::getMasterDispatchProvider(void) throw( RuntimeException )
759 return m_xMasterDispatcher;
762 // -----------------------------------------------------------------------
763 void OGenericUnoController::setMasterDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider) throw( RuntimeException )
765 m_xMasterDispatcher = _xNewProvider;
768 // -----------------------------------------------------------------------
769 void OGenericUnoController::dispatch(const URL& _aURL, const Sequence< PropertyValue >& aArgs) throw(RuntimeException)
771 SolarMutexGuard aSolarGuard;
772 // The SolarMutex is not locked anymore when the framework calls into
773 // here. So, lock it ourself. The real solution would be to lock it only in the places
774 // where it's needed, but a) this might turn out difficult, since we then also need to care
775 // for locking in the proper order (SolarMutex and m_aMutex), and b) this would be too many places
776 // for the time frame of the fix.
777 // #i52602#
779 #ifdef TIMELOG
780 ::rtl::OString sLog( "OGenericUnoController::dispatch( '" );
781 sLog += ::rtl::OString( _aURL.Main.getStr(), _aURL.Main.getLength(), osl_getThreadTextEncoding() );
782 sLog += ::rtl::OString( "' )" );
783 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", sLog.getStr() );
784 #endif
786 executeChecked(_aURL,aArgs);
789 // -----------------------------------------------------------------------
790 void OGenericUnoController::addStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL) throw(RuntimeException)
792 // parse the ULR now and here, this saves later parsing in each notification round
793 URL aParsedURL( _rURL );
794 if ( m_xUrlTransformer.is() )
795 m_xUrlTransformer->parseStrict( aParsedURL );
797 // remember the listener together with the URL
798 m_arrStatusListener.insert( m_arrStatusListener.end(), DispatchTarget( aParsedURL, aListener ) );
800 // initially broadcast the state
801 ImplBroadcastFeatureState( aParsedURL.Complete, aListener, sal_True );
802 // force the new state to be broadcast to the new listener
805 // -----------------------------------------------------------------------
806 void OGenericUnoController::removeStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL) throw(RuntimeException)
808 DispatchIterator iterSearch = m_arrStatusListener.begin();
810 sal_Bool bRemoveForAll = _rURL.Complete.isEmpty();
811 while ( iterSearch != m_arrStatusListener.end() )
813 DispatchTarget& rCurrent = *iterSearch;
814 if ( (rCurrent.xListener == aListener)
815 && ( bRemoveForAll
816 || (rCurrent.aURL.Complete.equals(_rURL.Complete))
820 m_arrStatusListener.erase( iterSearch );
821 if (!bRemoveForAll)
822 // remove the listener only for the given URL, so we can exit the loop after deletion
823 break;
825 else
826 ++iterSearch;
829 OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::removeStatusListener: shouldn't this be filled at construction time?" );
830 if ( m_aSupportedFeatures.empty() )
831 fillSupportedFeatures();
833 SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find(_rURL.Complete);
834 if (aIter != m_aSupportedFeatures.end())
835 { // clear the cache for that feature
836 StateCacheIterator aCachePos = m_aStateCache.find( aIter->second.nFeatureId );
837 if ( aCachePos != m_aStateCache.end() )
838 m_aStateCache.erase( aCachePos );
841 // now remove the listener from the deque
842 ::osl::MutexGuard aGuard( m_aFeatureMutex );
843 m_aFeaturesToInvalidate.erase(
844 ::std::remove_if( m_aFeaturesToInvalidate.begin(),
845 m_aFeaturesToInvalidate.end(),
846 ::std::bind2nd(FindFeatureListener(),aListener))
847 ,m_aFeaturesToInvalidate.end());
849 // -----------------------------------------------------------------------------
850 void OGenericUnoController::releaseNumberForComponent()
854 Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
855 if ( xUntitledProvider.is() )
856 xUntitledProvider->releaseNumberForComponent(static_cast<XWeak*>(this));
858 catch( const Exception& )
860 // NII
863 // -----------------------------------------------------------------------
864 void OGenericUnoController::disposing()
867 EventObject aDisposeEvent;
868 aDisposeEvent.Source = static_cast<XWeak*>(this);
869 Dispatch aStatusListener = m_arrStatusListener;
870 Dispatch::iterator aEnd = aStatusListener.end();
871 for (Dispatch::iterator aIter = aStatusListener.begin(); aIter != aEnd; ++aIter)
873 aIter->xListener->disposing(aDisposeEvent);
875 m_arrStatusListener.clear();
878 m_xDatabaseContext = NULL;
880 ::osl::MutexGuard aGuard( m_aFeatureMutex);
881 m_aAsyncInvalidateAll.CancelCall();
882 m_aFeaturesToInvalidate.clear();
885 releaseNumberForComponent();
887 // check out from all the objects we are listening
888 // the frame
889 stopFrameListening( m_aCurrentFrame.getFrame() );
890 m_aCurrentFrame.attachFrame( NULL );
892 m_xMasterDispatcher = NULL;
893 m_xSlaveDispatcher = NULL;
894 m_xServiceFactory = NULL;
895 m_xTitleHelper.clear();
896 m_xUrlTransformer.clear();
897 m_aInitParameters.clear();
900 // -----------------------------------------------------------------------------
901 void SAL_CALL OGenericUnoController::addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
903 // disambiguate
904 OGenericUnoController_Base::WeakComponentImplHelperBase::addEventListener( xListener );
907 // -----------------------------------------------------------------------------
908 void SAL_CALL OGenericUnoController::removeEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
910 // disambiguate
911 OGenericUnoController_Base::WeakComponentImplHelperBase::removeEventListener( xListener );
914 //------------------------------------------------------------------------------
915 void OGenericUnoController::frameAction(const FrameActionEvent& aEvent) throw( RuntimeException )
917 ::osl::MutexGuard aGuard( getMutex() );
918 if ( aEvent.Frame == m_aCurrentFrame.getFrame() )
919 m_aCurrentFrame.frameAction( aEvent.Action );
922 //------------------------------------------------------------------------------
923 void OGenericUnoController::implDescribeSupportedFeature( const sal_Char* _pAsciiCommandURL,
924 sal_uInt16 _nFeatureId, sal_Int16 _nCommandGroup )
926 #ifdef DBG_UTIL
927 OSL_ENSURE( m_bDescribingSupportedFeatures, "OGenericUnoController::implDescribeSupportedFeature: bad timing for this call!" );
928 #endif
929 OSL_PRECOND( _nFeatureId < FIRST_USER_DEFINED_FEATURE, "OGenericUnoController::implDescribeSupportedFeature: invalid feature id!" );
931 ControllerFeature aFeature;
932 aFeature.Command = ::rtl::OUString::createFromAscii( _pAsciiCommandURL );
933 aFeature.nFeatureId = _nFeatureId;
934 aFeature.GroupId = _nCommandGroup;
936 #if OSL_DEBUG_LEVEL > 0
937 OSL_ENSURE( m_aSupportedFeatures.find( aFeature.Command ) == m_aSupportedFeatures.end(),
938 "OGenericUnoController::implDescribeSupportedFeature: this feature is already there!" );
939 #endif
940 m_aSupportedFeatures[ aFeature.Command ] = aFeature;
943 //------------------------------------------------------------------------------
944 void OGenericUnoController::describeSupportedFeatures()
946 // add all supported features
947 implDescribeSupportedFeature( ".uno:Copy", ID_BROWSER_COPY, CommandGroup::EDIT );
948 implDescribeSupportedFeature( ".uno:Cut", ID_BROWSER_CUT, CommandGroup::EDIT );
949 implDescribeSupportedFeature( ".uno:Paste", ID_BROWSER_PASTE, CommandGroup::EDIT );
950 implDescribeSupportedFeature( ".uno:ClipboardFormatItems", ID_BROWSER_CLIPBOARD_FORMAT_ITEMS );
951 implDescribeSupportedFeature( ".uno:DSBEditDoc", ID_BROWSER_EDITDOC, CommandGroup::DOCUMENT );
954 //------------------------------------------------------------------------------
955 FeatureState OGenericUnoController::GetState( sal_uInt16 _nId ) const
957 FeatureState aReturn;
958 // (disabled automatically)
960 switch ( _nId )
962 case ID_BROWSER_UNDO:
963 case ID_BROWSER_SAVEDOC:
964 aReturn.bEnabled = sal_True;
965 break;
966 default:
967 aReturn = m_pData->m_aUserDefinedFeatures.getState( getURLForId( _nId ) );
968 break;
971 return aReturn;
974 //------------------------------------------------------------------------------
975 void OGenericUnoController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue>& _rArgs )
977 OSL_ENSURE( isUserDefinedFeature( _nId ),
978 "OGenericUnoController::Execute: responsible for user defined features only!" );
980 // user defined features can be handled by dispatch interceptors resp. protocol handlers only.
981 // So, we need to do a queryDispatch, and dispatch the URL
982 m_pData->m_aUserDefinedFeatures.execute( getURLForId( _nId ), _rArgs );
985 //------------------------------------------------------------------------------
986 URL OGenericUnoController::getURLForId(sal_Int32 _nId) const
988 URL aReturn;
989 if ( m_xUrlTransformer.is() )
991 SupportedFeatures::const_iterator aIter = ::std::find_if(
992 m_aSupportedFeatures.begin(),
993 m_aSupportedFeatures.end(),
994 ::std::bind2nd( CompareFeatureById(), _nId )
997 if ( m_aSupportedFeatures.end() != aIter && !aIter->first.isEmpty() )
999 aReturn.Complete = aIter->first;
1000 m_xUrlTransformer->parseStrict( aReturn );
1003 return aReturn;
1006 //-------------------------------------------------------------------------
1007 bool OGenericUnoController::isUserDefinedFeature( const sal_uInt16 _nFeatureId ) const
1009 return ( _nFeatureId >= FIRST_USER_DEFINED_FEATURE ) && ( _nFeatureId < LAST_USER_DEFINED_FEATURE );
1012 //-------------------------------------------------------------------------
1013 bool OGenericUnoController::isUserDefinedFeature( const ::rtl::OUString& _rFeatureURL ) const
1015 SupportedFeatures::const_iterator pos = m_aSupportedFeatures.find( _rFeatureURL );
1016 OSL_PRECOND( pos != m_aSupportedFeatures.end(),
1017 "OGenericUnoController::isUserDefinedFeature: this is no supported feature at all!" );
1019 return ( pos != m_aSupportedFeatures.end() ) ? isUserDefinedFeature( pos->second.nFeatureId ) : false;
1022 //-------------------------------------------------------------------------
1023 sal_Bool SAL_CALL OGenericUnoController::supportsService(const ::rtl::OUString& ServiceName) throw(RuntimeException)
1025 Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
1027 const ::rtl::OUString* pArray = aSupported.getConstArray();
1028 const ::rtl::OUString* pArrayEnd = aSupported.getConstArray() + aSupported.getLength();
1030 for ( ;( pArray != pArrayEnd ) && !pArray->equals( ServiceName ); ++pArray )
1032 return pArray != pArrayEnd;
1035 // -----------------------------------------------------------------------------
1036 void OGenericUnoController::startConnectionListening(const Reference< XConnection >& _rxConnection)
1038 // we have to remove ourself before dispoing the connection
1039 Reference< XComponent > xComponent(_rxConnection, UNO_QUERY);
1040 if (xComponent.is())
1041 xComponent->addEventListener(static_cast<XFrameActionListener*>(this));
1044 // -----------------------------------------------------------------------------
1045 void OGenericUnoController::stopConnectionListening(const Reference< XConnection >& _rxConnection)
1047 // we have to remove ourself before dispoing the connection
1048 Reference< XComponent > xComponent(_rxConnection, UNO_QUERY);
1049 if (xComponent.is())
1050 xComponent->removeEventListener(static_cast<XFrameActionListener*>(this));
1052 // -----------------------------------------------------------------------------
1053 Reference< XConnection > OGenericUnoController::connect( const Reference< XDataSource>& _xDataSource,
1054 ::dbtools::SQLExceptionInfo* _pErrorInfo )
1056 WaitObject aWaitCursor( getView() );
1058 ODatasourceConnector aConnector( getORB(), getView(), ::rtl::OUString() );
1059 Reference< XConnection > xConnection = aConnector.connect( _xDataSource, _pErrorInfo );
1060 startConnectionListening( xConnection );
1062 return xConnection;
1064 // -----------------------------------------------------------------------------
1065 Reference< XConnection > OGenericUnoController::connect( const ::rtl::OUString& _rDataSourceName,
1066 const ::rtl::OUString& _rContextInformation, ::dbtools::SQLExceptionInfo* _pErrorInfo )
1068 WaitObject aWaitCursor( getView() );
1070 ODatasourceConnector aConnector( getORB(), getView(), _rContextInformation );
1071 Reference<XConnection> xConnection = aConnector.connect( _rDataSourceName, _pErrorInfo );
1072 startConnectionListening( xConnection );
1074 return xConnection;
1077 // -----------------------------------------------------------------------------
1078 void OGenericUnoController::showError(const SQLExceptionInfo& _rInfo)
1080 ::dbaui::showError(_rInfo,getView(),getORB());
1082 // -----------------------------------------------------------------------------
1083 Reference< XLayoutManager > OGenericUnoController::getLayoutManager(const Reference< XFrame >& _xFrame) const
1085 Reference< XPropertySet > xPropSet( _xFrame, UNO_QUERY );
1086 Reference< XLayoutManager > xLayoutManager;
1087 if ( xPropSet.is() )
1091 xLayoutManager.set(xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))),UNO_QUERY);
1093 catch ( Exception& )
1097 return xLayoutManager;
1099 // -----------------------------------------------------------------------------
1100 void OGenericUnoController::loadMenu(const Reference< XFrame >& _xFrame)
1102 Reference< XLayoutManager > xLayoutManager = getLayoutManager(_xFrame);
1103 if ( xLayoutManager.is() )
1105 xLayoutManager->lock();
1106 xLayoutManager->createElement( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )));
1107 xLayoutManager->createElement( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/toolbar" )));
1108 xLayoutManager->unlock();
1109 xLayoutManager->doLayout();
1112 onLoadedMenu( xLayoutManager );
1115 // -----------------------------------------------------------------------------
1116 void OGenericUnoController::onLoadedMenu(const Reference< XLayoutManager >& /*_xLayoutManager*/)
1118 // not interested in
1121 // -----------------------------------------------------------------------------
1122 void OGenericUnoController::closeTask()
1124 m_aAsyncCloseTask.Call();
1126 // -----------------------------------------------------------------------------
1127 IMPL_LINK_NOARG(OGenericUnoController, OnAsyncCloseTask)
1129 if ( !OGenericUnoController_Base::rBHelper.bInDispose )
1133 Reference< util::XCloseable > xCloseable( m_aCurrentFrame.getFrame(), UNO_QUERY_THROW );
1134 xCloseable->close( sal_False ); // false - holds the owner ship for this frame inside this object!
1136 catch( const Exception& )
1138 DBG_UNHANDLED_EXCEPTION();
1141 return 0L;
1143 // -----------------------------------------------------------------------------
1144 Any SAL_CALL OGenericUnoController::getViewData(void) throw( RuntimeException )
1146 return Any();
1148 // -----------------------------------------------------------------------------
1149 void SAL_CALL OGenericUnoController::restoreViewData(const Any& /*Data*/) throw( RuntimeException )
1153 // -----------------------------------------------------------------------------
1154 Reference< XModel > SAL_CALL OGenericUnoController::getModel(void) throw( RuntimeException )
1156 return Reference< XModel >();
1159 // -----------------------------------------------------------------------------
1160 Reference< XFrame > SAL_CALL OGenericUnoController::getFrame(void) throw( RuntimeException )
1162 ::osl::MutexGuard aGuard( getMutex() );
1163 return m_aCurrentFrame.getFrame();
1166 // -----------------------------------------------------------------------------
1167 sal_Bool SAL_CALL OGenericUnoController::attachModel(const Reference< XModel > & /*xModel*/) throw( RuntimeException )
1169 OSL_FAIL( "OGenericUnoController::attachModel: not supported!" );
1170 return sal_False;
1173 // -----------------------------------------------------------------------------
1174 void OGenericUnoController::executeUnChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
1176 Execute(_nCommandId, aArgs);
1178 // -----------------------------------------------------------------------------
1179 void OGenericUnoController::executeUnChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
1181 OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeUnChecked: shouldn't this be filled at construction time?" );
1182 if ( m_aSupportedFeatures.empty() )
1183 fillSupportedFeatures();
1185 SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
1186 if (aIter != m_aSupportedFeatures.end())
1187 Execute( aIter->second.nFeatureId, aArgs );
1189 // -----------------------------------------------------------------------------
1190 void OGenericUnoController::executeChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
1192 OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeChecked: shouldn't this be filled at construction time?" );
1193 if ( m_aSupportedFeatures.empty() )
1194 fillSupportedFeatures();
1196 SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
1197 if ( aIter != m_aSupportedFeatures.end() )
1199 sal_uInt16 nFeatureId = aIter->second.nFeatureId;
1200 if ( GetState( nFeatureId ).bEnabled )
1201 Execute( nFeatureId, aArgs );
1204 // -----------------------------------------------------------------------------
1205 //------------------------------------------------------------------------------
1206 namespace
1208 ::rtl::OUString lcl_getModuleHelpModuleName( const Reference< XFrame >& _rxFrame )
1210 const sal_Char* pReturn = NULL;
1214 // get the model of the document in the given frame
1215 Reference< XController > xController;
1216 if ( _rxFrame.is() )
1217 xController = _rxFrame->getController();
1218 Reference< XModel > xModel;
1219 if ( xController.is() )
1220 xModel = xController->getModel();
1221 Reference< XServiceInfo > xSI( xModel, UNO_QUERY );
1223 if ( !xSI.is() )
1224 { // try to go up the frame hierarchy
1226 Reference< XFrame > xParentFrame;
1227 if ( _rxFrame.is() )
1228 xParentFrame = xParentFrame.query( _rxFrame->getCreator() );
1229 // did we find a parent frame? Which is no top-level frame?
1230 if ( xParentFrame.is() && !_rxFrame->isTop() )
1231 // TODO: to prevent framework assertions, re-insert this "isTop" once 98303 is fixed
1232 return lcl_getModuleHelpModuleName( xParentFrame );
1234 else
1236 #if OSL_DEBUG_LEVEL > 0
1237 Sequence< ::rtl::OUString > sServiceNames = xSI->getSupportedServiceNames();
1238 const ::rtl::OUString* pLoop = sServiceNames.getConstArray();
1239 for ( sal_Int32 i=0; i<sServiceNames.getLength(); ++i, ++pLoop )
1241 sal_Int32 nDummy = 0;
1242 (void)nDummy;
1244 #endif
1246 // check which service we know ....
1247 static const sal_Char* pTransTable[] = {
1248 "com.sun.star.sdb.OfficeDatabaseDocument","sdatabase",
1249 "com.sun.star.report.ReportDefinition","sdatabase",
1250 "com.sun.star.text.TextDocument", "swriter",
1251 "com.sun.star.sheet.SpreadsheetDocument", "scalc",
1252 "com.sun.star.presentation.PresentationDocument", "simpress",
1253 "com.sun.star.drawing.DrawingDocument", "sdraw",
1254 "com.sun.star.formula.FormularProperties", "smath",
1255 "com.sun.star.chart.ChartDocument", "schart"
1257 OSL_ENSURE( ( sizeof( pTransTable ) / sizeof( pTransTable[0] ) ) % 2 == 0,
1258 "lcl_getModuleHelpModuleName: odd size of translation table!" );
1260 // loop through the table
1261 sal_Int32 nTableEntries = ( sizeof( pTransTable ) / sizeof( pTransTable[0] ) ) / 2;
1262 const sal_Char** pDocumentService = pTransTable;
1263 const sal_Char** pHelpModuleName = pTransTable + 1;
1264 for ( sal_Int32 j=0; j<nTableEntries; ++j )
1266 if ( xSI->supportsService( ::rtl::OUString::createFromAscii( *pDocumentService ) ) )
1267 { // found a table entry which matches the model's services
1268 pReturn = *pHelpModuleName;
1269 break;
1272 ++pDocumentService; ++pDocumentService;
1273 ++pHelpModuleName; ++pHelpModuleName;
1277 if ( !pReturn )
1279 // could not determine the document type we're living in
1280 // ->fallback
1281 SvtModuleOptions aModOpt;
1282 if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
1283 pReturn = "swriter";
1284 else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
1285 pReturn = "sdatabase";
1286 else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
1287 pReturn = "scalc";
1288 else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
1289 pReturn = "simpress";
1290 else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
1291 pReturn = "sdraw";
1292 else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
1293 pReturn = "smath";
1294 else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCHART ) )
1295 pReturn = "schart";
1296 else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SBASIC ) )
1297 pReturn = "sbasic";
1298 else
1300 OSL_FAIL( "lcl_getModuleHelpModuleName: no installed module found" );
1304 catch( const Exception& )
1306 DBG_UNHANDLED_EXCEPTION();
1309 if ( !pReturn )
1310 pReturn = "swriter";
1312 return ::rtl::OUString::createFromAscii( pReturn );
1316 // -----------------------------------------------------------------------------
1318 void OGenericUnoController::openHelpAgent(rtl::OUString const& _suHelpStringURL )
1320 rtl::OUString suURL(_suHelpStringURL);
1321 rtl::OUString sLanguage(RTL_CONSTASCII_USTRINGPARAM("Language="));
1322 if (suURL.indexOf(sLanguage) == -1)
1324 AppendConfigToken(suURL, sal_False /* sal_False := add '&' */ );
1326 URL aURL;
1327 aURL.Complete = suURL;
1329 openHelpAgent( aURL );
1332 void OGenericUnoController::openHelpAgent(const rtl::OString& _sHelpId)
1334 openHelpAgent( createHelpAgentURL( lcl_getModuleHelpModuleName( getFrame() ), _sHelpId ) );
1337 void OGenericUnoController::openHelpAgent( const URL& _rURL )
1341 URL aURL( _rURL );
1343 if ( m_xUrlTransformer.is() )
1344 m_xUrlTransformer->parseStrict(aURL);
1346 Reference< XDispatchProvider > xDispProv( m_aCurrentFrame.getFrame(), UNO_QUERY );
1347 Reference< XDispatch > xHelpDispatch;
1348 if ( xDispProv.is() )
1349 xHelpDispatch = xDispProv->queryDispatch(aURL, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_helpagent")), FrameSearchFlag::PARENT | FrameSearchFlag::SELF);
1350 OSL_ENSURE(xHelpDispatch.is(), "SbaTableQueryBrowser::openHelpAgent: could not get a dispatcher!");
1351 if (xHelpDispatch.is())
1353 xHelpDispatch->dispatch(aURL, Sequence< PropertyValue >());
1356 catch( const Exception& )
1358 DBG_UNHANDLED_EXCEPTION();
1361 // -----------------------------------------------------------------------------
1362 Reference< awt::XWindow> OGenericUnoController::getTopMostContainerWindow() const
1364 Reference< ::com::sun::star::awt::XWindow> xWindow;
1366 // get the top most window
1367 Reference< XFrame > xFrame( m_aCurrentFrame.getFrame() );
1368 if ( xFrame.is() )
1370 xWindow = xFrame->getContainerWindow();
1372 while ( xFrame.is() && !xFrame->isTop() )
1374 xFrame.set( xFrame->getCreator(), UNO_QUERY );
1376 if ( xFrame.is() )
1377 xWindow = xFrame->getContainerWindow();
1379 return xWindow;
1381 // -----------------------------------------------------------------------------
1382 Reference< XTitle > OGenericUnoController::impl_getTitleHelper_throw()
1384 SolarMutexGuard aSolarGuard;
1385 ::osl::MutexGuard aGuard( getMutex() );
1387 if ( ! m_xTitleHelper.is ())
1389 Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
1390 Reference< XController > xThis(static_cast< XController* >(this), UNO_QUERY_THROW);
1392 ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(m_xServiceFactory);
1393 m_xTitleHelper.set( static_cast< ::cppu::OWeakObject* >(pHelper), UNO_QUERY_THROW);
1395 pHelper->setOwner (xThis );
1396 pHelper->connectWithUntitledNumbers (xUntitledProvider);
1399 return m_xTitleHelper;
1402 //=============================================================================
1403 // XTitle
1404 ::rtl::OUString SAL_CALL OGenericUnoController::getTitle()
1405 throw (RuntimeException)
1407 ::osl::MutexGuard aGuard( getMutex() );
1408 if ( m_bExternalTitle )
1409 return impl_getTitleHelper_throw()->getTitle ();
1410 return getPrivateTitle() + impl_getTitleHelper_throw()->getTitle ();
1413 //=============================================================================
1414 // XTitle
1415 void SAL_CALL OGenericUnoController::setTitle(const ::rtl::OUString& sTitle)
1416 throw (RuntimeException)
1418 SolarMutexGuard aSolarGuard;
1419 ::osl::MutexGuard aGuard( getMutex() );
1420 m_bExternalTitle = sal_True;
1421 impl_getTitleHelper_throw()->setTitle (sTitle);
1424 //=============================================================================
1425 // XTitleChangeBroadcaster
1426 void SAL_CALL OGenericUnoController::addTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
1427 throw (RuntimeException)
1429 Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
1430 if (xBroadcaster.is ())
1431 xBroadcaster->addTitleChangeListener (xListener);
1434 // -----------------------------------------------------------------------------
1435 void SAL_CALL OGenericUnoController::removeTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
1436 throw (RuntimeException)
1438 Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
1439 if (xBroadcaster.is ())
1440 xBroadcaster->removeTitleChangeListener (xListener);
1443 // =============================================================================
1444 // XUserInputInterception
1445 // -----------------------------------------------------------------------------
1446 void SAL_CALL OGenericUnoController::addKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException)
1448 if ( _rxHandler.is() )
1449 m_pData->m_aUserInputInterception.addKeyHandler( _rxHandler );
1452 // -----------------------------------------------------------------------------
1453 void SAL_CALL OGenericUnoController::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException)
1455 m_pData->m_aUserInputInterception.removeKeyHandler( _rxHandler );
1458 // -----------------------------------------------------------------------------
1459 void SAL_CALL OGenericUnoController::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException)
1461 if ( _rxHandler.is() )
1462 m_pData->m_aUserInputInterception.addMouseClickHandler( _rxHandler );
1465 // -----------------------------------------------------------------------------
1466 void SAL_CALL OGenericUnoController::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException)
1468 m_pData->m_aUserInputInterception.removeMouseClickHandler( _rxHandler );
1471 // =============================================================================
1472 // -----------------------------------------------------------------------------
1473 void OGenericUnoController::executeChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
1475 if ( isCommandEnabled(_nCommandId) )
1476 Execute(_nCommandId, aArgs);
1479 // -----------------------------------------------------------------------------
1480 sal_Bool OGenericUnoController::isCommandEnabled(sal_uInt16 _nCommandId) const
1482 return GetState( _nCommandId ).bEnabled;
1485 // -----------------------------------------------------------------------------
1486 sal_uInt16 OGenericUnoController::registerCommandURL( const ::rtl::OUString& _rCompleteCommandURL )
1488 if ( _rCompleteCommandURL.isEmpty() )
1489 return 0;
1491 SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL );
1492 if ( aIter != m_aSupportedFeatures.end() )
1493 return aIter->second.nFeatureId;
1495 // this is a previously unkwnon command
1496 sal_uInt16 nFeatureId = FIRST_USER_DEFINED_FEATURE;
1497 while ( isFeatureSupported( nFeatureId ) && ( nFeatureId < LAST_USER_DEFINED_FEATURE ) )
1498 ++nFeatureId;
1499 if ( nFeatureId == LAST_USER_DEFINED_FEATURE )
1501 OSL_FAIL( "OGenericUnoController::registerCommandURL: no more space for user defined features!" );
1502 return 0L;
1505 ControllerFeature aFeature;
1506 aFeature.Command = _rCompleteCommandURL;
1507 aFeature.nFeatureId = nFeatureId;
1508 aFeature.GroupId = CommandGroup::INTERNAL;
1509 m_aSupportedFeatures[ aFeature.Command ] = aFeature;
1511 return nFeatureId;
1514 // -----------------------------------------------------------------------------
1515 void OGenericUnoController::notifyHiContrastChanged()
1519 // -----------------------------------------------------------------------------
1520 sal_Bool OGenericUnoController::isDataSourceReadOnly() const
1522 return sal_False;
1525 // -----------------------------------------------------------------------------
1526 Reference< XController > OGenericUnoController::getXController() throw( RuntimeException )
1528 return this;
1531 // -----------------------------------------------------------------------------
1532 bool OGenericUnoController::interceptUserInput( const NotifyEvent& _rEvent )
1534 return m_pData->m_aUserInputInterception.handleNotifyEvent( _rEvent );
1537 // -----------------------------------------------------------------------------
1538 sal_Bool OGenericUnoController::isCommandChecked(sal_uInt16 _nCommandId) const
1540 FeatureState aState = GetState( _nCommandId );
1542 return aState.bChecked && (sal_Bool)*aState.bChecked;
1544 // -----------------------------------------------------------------------------
1545 sal_Bool OGenericUnoController::isCommandEnabled( const ::rtl::OUString& _rCompleteCommandURL ) const
1547 OSL_ENSURE( !_rCompleteCommandURL.isEmpty(), "OGenericUnoController::isCommandEnabled: Empty command url!" );
1549 sal_Bool bIsEnabled = sal_False;
1550 SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL );
1551 if ( aIter != m_aSupportedFeatures.end() )
1552 bIsEnabled = isCommandEnabled( aIter->second.nFeatureId );
1554 return bIsEnabled;
1557 // -----------------------------------------------------------------------------
1558 Sequence< ::sal_Int16 > SAL_CALL OGenericUnoController::getSupportedCommandGroups() throw (RuntimeException)
1560 CommandHashMap aCmdHashMap;
1561 for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
1562 aIter != m_aSupportedFeatures.end();
1563 ++aIter
1565 if ( aIter->second.GroupId != CommandGroup::INTERNAL )
1566 aCmdHashMap.insert( CommandHashMap::value_type( aIter->second.GroupId, 0 ));
1568 Sequence< sal_Int16 > aCommandGroups( aCmdHashMap.size() );
1569 ::std::transform( aCmdHashMap.begin(),
1570 aCmdHashMap.end(),
1571 aCommandGroups.getArray(),
1572 ::o3tl::select1st< CommandHashMap::value_type >()
1575 return aCommandGroups;
1578 namespace
1580 //Current c++0x draft (apparently) has std::identity, but not operator()
1581 template<typename T> struct SGI_identity : public std::unary_function<T,T>
1583 T& operator()(T& x) const { return x; }
1584 const T& operator()(const T& x) const { return x; }
1588 // -----------------------------------------------------------------------------
1589 Sequence< DispatchInformation > SAL_CALL OGenericUnoController::getConfigurableDispatchInformation( ::sal_Int16 CommandGroup ) throw (RuntimeException)
1591 DispatchInfoList aInformationList;
1592 DispatchInformation aDispatchInfo;
1593 for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
1594 aIter != m_aSupportedFeatures.end();
1595 ++aIter
1598 if ( sal_Int16( aIter->second.GroupId ) == CommandGroup )
1600 aDispatchInfo = aIter->second;
1601 aInformationList.push_back( aDispatchInfo );
1605 Sequence< DispatchInformation > aInformation( aInformationList.size() );
1606 ::std::transform( aInformationList.begin(),
1607 aInformationList.end(),
1608 aInformation.getArray(),
1609 SGI_identity< DispatchInformation >()
1612 return aInformation;
1614 // -----------------------------------------------------------------------------
1615 void OGenericUnoController::fillSupportedFeatures()
1617 #ifdef DBG_UTIL
1618 m_bDescribingSupportedFeatures = true;
1619 #endif
1620 describeSupportedFeatures();
1621 // -----------------------------------------------------------------------------
1622 #ifdef DBG_UTIL
1623 m_bDescribingSupportedFeatures = false;
1624 #endif
1628 void SAL_CALL OGenericUnoController::dispose() throw(::com::sun::star::uno::RuntimeException)
1630 SolarMutexGuard aSolarGuard;
1631 OGenericUnoController_Base::dispose();
1633 } // namespace dbaui
1635 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */