Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <dbaccess/genericcontroller.hxx>
21 : #include <comphelper/uno3.hxx>
22 : #include <toolkit/awt/vclxwindow.hxx>
23 : #include "browserids.hxx"
24 : #include <vcl/svapp.hxx>
25 : #include <toolkit/helper/vclunohelper.hxx>
26 : #include <dbaccess/dataview.hxx>
27 : #include <tools/diagnose_ex.h>
28 : #include <osl/diagnose.h>
29 : #include "dbustrings.hrc"
30 : #include <vcl/stdtext.hxx>
31 : #include <comphelper/processfactory.hxx>
32 : #include <cppuhelper/typeprovider.hxx>
33 : #include <framework/titlehelper.hxx>
34 : #include <comphelper/sequence.hxx>
35 : #include <comphelper/extract.hxx>
36 : #include <cppuhelper/supportsservice.hxx>
37 : #include <com/sun/star/sdbc/XDataSource.hpp>
38 : #include <com/sun/star/sdb/DatabaseContext.hpp>
39 : #include <com/sun/star/sdb/SQLContext.hpp>
40 : #include <com/sun/star/sdb/XCompletedConnection.hpp>
41 : #include <com/sun/star/beans/XPropertySet.hpp>
42 : #include <com/sun/star/task/XInteractionHandler.hpp>
43 : #include <com/sun/star/util/URLTransformer.hpp>
44 : #include <com/sun/star/util/XCloseable.hpp>
45 : #include "UITools.hxx"
46 : #include "commontypes.hxx"
47 :
48 : #include <vcl/waitobj.hxx>
49 : #include <svl/urihelper.hxx>
50 : #include "datasourceconnector.hxx"
51 : #include <unotools/moduleoptions.hxx>
52 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
53 : #include <com/sun/star/frame/status/Visibility.hpp>
54 : #include <com/sun/star/util/XModifiable.hpp>
55 : #include <rtl/ustring.hxx>
56 : #include <algorithm>
57 : #include <o3tl/compat_functional.hxx>
58 : #include <boost/scoped_ptr.hpp>
59 : #include <cppuhelper/implbase1.hxx>
60 : #include <limits>
61 : #include <unordered_map>
62 :
63 : using namespace ::com::sun::star;
64 : using namespace ::com::sun::star::uno;
65 : using namespace ::com::sun::star::beans;
66 : using namespace ::com::sun::star::frame;
67 : using namespace ::com::sun::star::frame::status;
68 : using namespace ::com::sun::star::util;
69 : using namespace ::com::sun::star::lang;
70 : using namespace ::com::sun::star::container;
71 : using namespace ::com::sun::star::sdbc;
72 : using namespace ::com::sun::star::sdb;
73 : using namespace ::com::sun::star::task;
74 : using namespace ::com::sun::star::awt;
75 : using namespace ::dbtools;
76 : using namespace ::comphelper;
77 :
78 : #define ALL_FEATURES -1
79 : #define FIRST_USER_DEFINED_FEATURE ( ::std::numeric_limits< sal_uInt16 >::max() - 1000 )
80 : #define LAST_USER_DEFINED_FEATURE ( ::std::numeric_limits< sal_uInt16 >::max() )
81 :
82 : typedef std::unordered_map< sal_Int16, sal_Int16 > CommandHashMap;
83 : typedef ::std::list< DispatchInformation > DispatchInfoList;
84 :
85 : namespace dbaui
86 : {
87 :
88 : // UserDefinedFeatures
89 12 : class UserDefinedFeatures
90 : {
91 : public:
92 : UserDefinedFeatures( const Reference< XController >& _rxController );
93 :
94 : static FeatureState getState( const URL& _rFeatureURL );
95 : void execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs );
96 :
97 : private:
98 : ::com::sun::star::uno::WeakReference< XController > m_aController;
99 : };
100 :
101 14 : UserDefinedFeatures::UserDefinedFeatures( const Reference< XController >& _rxController )
102 14 : :m_aController( _rxController )
103 : {
104 14 : }
105 :
106 30 : FeatureState UserDefinedFeatures::getState( const URL& /*_rFeatureURL*/ )
107 : {
108 : // for now, enable all the time
109 : // TODO: we should ask the dispatcher. However, this is laborious, since you cannot ask a dispatcher
110 : // directly, but need to add a status listener.
111 30 : FeatureState aState;
112 30 : aState.bEnabled = true;
113 30 : return aState;
114 : }
115 :
116 0 : void UserDefinedFeatures::execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs )
117 : {
118 : try
119 : {
120 0 : Reference< XController > xController( Reference< XController >(m_aController), UNO_SET_THROW );
121 0 : Reference< XDispatchProvider > xDispatchProvider( xController->getFrame(), UNO_QUERY_THROW );
122 0 : Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch(
123 : _rFeatureURL,
124 : OUString( "_self" ),
125 : FrameSearchFlag::AUTO
126 0 : ) );
127 :
128 0 : if ( xDispatch == xController )
129 : {
130 : SAL_WARN("dbaccess.ui", "UserDefinedFeatures::execute: the controller shouldn't be the dispatcher here!" );
131 0 : xDispatch.clear();
132 : }
133 :
134 0 : if ( xDispatch.is() )
135 0 : xDispatch->dispatch( _rFeatureURL, _rArgs );
136 : }
137 0 : catch( const Exception& )
138 : {
139 : DBG_UNHANDLED_EXCEPTION();
140 : }
141 0 : }
142 :
143 : // OGenericUnoController_Data
144 12 : struct OGenericUnoController_Data
145 : {
146 : ::sfx2::UserInputInterception m_aUserInputInterception;
147 : UserDefinedFeatures m_aUserDefinedFeatures;
148 :
149 14 : OGenericUnoController_Data( OGenericUnoController& _rController, ::osl::Mutex& _rMutex )
150 : :m_aUserInputInterception( _rController, _rMutex )
151 14 : ,m_aUserDefinedFeatures( _rController.getXController() )
152 : {
153 14 : }
154 : };
155 :
156 : // OGenericUnoController
157 14 : OGenericUnoController::OGenericUnoController(const Reference< XComponentContext >& _rM)
158 14 : :OGenericUnoController_Base( getMutex() )
159 : ,m_pView(NULL)
160 : #ifdef DBG_UTIL
161 : ,m_bDescribingSupportedFeatures( false )
162 : #endif
163 : ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
164 : ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
165 : ,m_xContext(_rM)
166 : ,m_aCurrentFrame( *this )
167 : ,m_bPreview(false)
168 : ,m_bReadOnly(false)
169 : ,m_bCurrentlyModified(false)
170 28 : ,m_bExternalTitle(false)
171 : {
172 14 : osl_atomic_increment( &m_refCount );
173 : {
174 14 : m_pData.reset( new OGenericUnoController_Data( *this, getMutex() ) );
175 : }
176 14 : osl_atomic_decrement( &m_refCount );
177 :
178 :
179 : try
180 : {
181 14 : m_xUrlTransformer = URLTransformer::create(_rM);
182 : }
183 0 : catch(Exception&)
184 : {
185 : DBG_UNHANDLED_EXCEPTION();
186 : }
187 14 : }
188 :
189 : #ifdef _MSC_VER
190 :
191 : #pragma warning(push)
192 : #pragma warning(disable:4702)
193 :
194 : OGenericUnoController::OGenericUnoController()
195 : :OGenericUnoController_Base( getMutex() )
196 : ,m_pView(NULL)
197 : #ifdef DBG_UTIL
198 : ,m_bDescribingSupportedFeatures( false )
199 : #endif
200 : ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
201 : ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
202 : ,m_aCurrentFrame( *this )
203 : ,m_bPreview(sal_False)
204 : ,m_bReadOnly(sal_False)
205 : ,m_bCurrentlyModified(sal_False)
206 : {
207 : SAL_WARN("dbaccess.ui", "OGenericUnoController::OGenericUnoController: illegal call!" );
208 : // This ctor only exists because the MSVC compiler complained about an unresolved external
209 : // symbol. It should not be used at all. Since using it yields strange runtime problems,
210 : // we simply abort here.
211 : abort();
212 : }
213 :
214 : #pragma warning(pop)
215 :
216 : #endif
217 :
218 12 : OGenericUnoController::~OGenericUnoController()
219 : {
220 :
221 12 : }
222 :
223 8 : bool OGenericUnoController::Construct(vcl::Window* /*pParent*/)
224 : {
225 : OSL_ENSURE( getView(), "the view is NULL!" );
226 :
227 8 : if ( getView() )
228 : {
229 8 : getView()->Construct();
230 8 : getView()->Show();
231 : }
232 :
233 8 : m_aSupportedFeatures.clear();
234 8 : fillSupportedFeatures();
235 :
236 : // create the database context
237 : OSL_ENSURE(getORB().is(), "OGenericUnoController::Construct need a service factory!");
238 : try
239 : {
240 8 : m_xDatabaseContext = DatabaseContext::create(getORB());
241 : }
242 0 : catch(const Exception&)
243 : {
244 : SAL_WARN("dbaccess.ui","OGenericUnoController::Construct: could not create (or start listening at) the database context!");
245 : // at least notify the user. Though the whole component does not make any sense without the database context ...
246 0 : ShowServiceNotAvailableError(getView(), OUString("com.sun.star.sdb.DatabaseContext"), true);
247 : }
248 :
249 8 : return true;
250 : }
251 :
252 22 : IMPL_LINK_NOARG(OGenericUnoController, OnAsyncInvalidateAll)
253 : {
254 11 : if ( !OGenericUnoController_Base::rBHelper.bInDispose && !OGenericUnoController_Base::rBHelper.bDisposed )
255 11 : InvalidateFeature_Impl();
256 11 : return 0L;
257 : }
258 :
259 8 : void OGenericUnoController::impl_initialize()
260 : {
261 8 : }
262 :
263 8 : void SAL_CALL OGenericUnoController::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException, std::exception)
264 : {
265 8 : SolarMutexGuard aSolarGuard;
266 16 : ::osl::MutexGuard aGuard( getMutex() );
267 :
268 16 : Reference< XWindow > xParent;
269 16 : Reference< XFrame > xFrame;
270 :
271 16 : PropertyValue aValue;
272 8 : const Any* pIter = aArguments.getConstArray();
273 8 : const Any* pEnd = pIter + aArguments.getLength();
274 :
275 23 : for ( ; pIter != pEnd; ++pIter )
276 : {
277 15 : if ( ( *pIter >>= aValue ) && aValue.Name == "Frame" )
278 : {
279 8 : xFrame.set(aValue.Value,UNO_QUERY_THROW);
280 : }
281 7 : else if ( ( *pIter >>= aValue ) && aValue.Name == "Preview" )
282 : {
283 0 : aValue.Value >>= m_bPreview;
284 0 : m_bReadOnly = true;
285 : }
286 : }
287 : try
288 : {
289 8 : if ( !xFrame.is() )
290 0 : throw IllegalArgumentException("need a frame", *this, 1 );
291 :
292 8 : xParent = xFrame->getContainerWindow();
293 8 : VCLXWindow* pParentComponent = VCLXWindow::GetImplementation(xParent);
294 8 : VclPtr< vcl::Window > pParentWin = pParentComponent ? pParentComponent->GetWindow() : VclPtr< vcl::Window >();
295 8 : if (!pParentWin)
296 : {
297 0 : throw IllegalArgumentException("Parent window is null", *this, 1 );
298 : }
299 :
300 8 : m_aInitParameters.assign( aArguments );
301 8 : Construct( pParentWin );
302 :
303 8 : ODataView* pView = getView();
304 8 : if ( !pView )
305 0 : throw RuntimeException("unable to create a view", *this );
306 :
307 8 : if ( m_bReadOnly || m_bPreview )
308 0 : pView->EnableInput( false );
309 :
310 8 : impl_initialize();
311 : }
312 0 : catch(Exception&)
313 : {
314 : // no one clears my view if I won't
315 0 : m_pView = NULL;
316 0 : throw;
317 8 : }
318 8 : }
319 :
320 3670 : void SAL_CALL OGenericUnoController::acquire( ) throw ()
321 : {
322 3670 : OGenericUnoController_Base::acquire();
323 3670 : }
324 :
325 3662 : void SAL_CALL OGenericUnoController::release( ) throw ()
326 : {
327 3662 : OGenericUnoController_Base::release();
328 3662 : }
329 :
330 18 : void OGenericUnoController::startFrameListening( const Reference< XFrame >& _rxFrame )
331 : {
332 18 : if ( _rxFrame.is() )
333 8 : _rxFrame->addFrameActionListener( this );
334 18 : }
335 :
336 30 : void OGenericUnoController::stopFrameListening( const Reference< XFrame >& _rxFrame )
337 : {
338 30 : if ( _rxFrame.is() )
339 6 : _rxFrame->removeFrameActionListener( this );
340 30 : }
341 :
342 3 : void OGenericUnoController::disposing(const EventObject& Source) throw( RuntimeException, std::exception )
343 : {
344 : // our frame ?
345 3 : if ( Source.Source == getFrame() )
346 0 : stopFrameListening( getFrame() );
347 3 : }
348 :
349 2 : void OGenericUnoController::modified(const EventObject& aEvent) throw( RuntimeException, std::exception )
350 : {
351 2 : ::osl::MutexGuard aGuard( getMutex() );
352 2 : if ( !isDataSourceReadOnly() )
353 : {
354 2 : Reference<XModifiable> xModi(aEvent.Source,UNO_QUERY);
355 2 : if ( xModi.is() )
356 2 : m_bCurrentlyModified = xModi->isModified(); // can only be reset by save
357 : else
358 0 : m_bCurrentlyModified = true;
359 : }
360 2 : InvalidateFeature(ID_BROWSER_SAVEDOC);
361 2 : InvalidateFeature(ID_BROWSER_UNDO);
362 2 : }
363 :
364 8 : Reference< XWindow > SAL_CALL OGenericUnoController::getComponentWindow() throw (RuntimeException, std::exception)
365 : {
366 8 : return VCLUnoHelper::GetInterface( getView() );
367 : }
368 :
369 0 : OUString SAL_CALL OGenericUnoController::getViewControllerName() throw (::com::sun::star::uno::RuntimeException, std::exception)
370 : {
371 0 : return OUString( "Default" );
372 : }
373 :
374 0 : Sequence< PropertyValue > SAL_CALL OGenericUnoController::getCreationArguments() throw (RuntimeException, std::exception)
375 : {
376 : // currently we do not support any creation args, so anything passed to XModel2::createViewController would be
377 : // lost, so we can equally return an empty sequence here
378 0 : return Sequence< PropertyValue >();
379 : }
380 :
381 18 : void OGenericUnoController::attachFrame( const Reference< XFrame >& _rxFrame ) throw( RuntimeException, std::exception )
382 : {
383 18 : SolarMutexGuard aSolarGuard;
384 36 : ::osl::MutexGuard aGuard( getMutex() );
385 :
386 18 : stopFrameListening( m_aCurrentFrame.getFrame() );
387 36 : Reference< XFrame > xFrame = m_aCurrentFrame.attachFrame( _rxFrame );
388 18 : startFrameListening( xFrame );
389 :
390 18 : loadMenu( xFrame );
391 :
392 18 : if ( getView() )
393 31 : getView()->attachFrame( xFrame );
394 18 : }
395 :
396 : struct CommandCollector : public ::std::unary_function< SupportedFeatures::value_type, void>
397 : {
398 : sal_uInt16 m_nFeature;
399 : StringBag& m_rFeatureCommands;
400 606 : CommandCollector( sal_uInt16 _nFeature, StringBag& _rFeatureCommands )
401 : :m_nFeature ( _nFeature )
402 606 : ,m_rFeatureCommands( _rFeatureCommands )
403 : {
404 606 : }
405 :
406 40740 : void operator() ( const SupportedFeatures::value_type& lhs )
407 : {
408 40740 : if ( lhs.second.nFeatureId == m_nFeature )
409 722 : m_rFeatureCommands.insert( lhs.first );
410 40740 : }
411 : };
412 :
413 : namespace
414 : {
415 : typedef ::std::vector< Any > States;
416 :
417 158 : void lcl_notifyMultipleStates( XStatusListener& _rListener, FeatureStateEvent& _rEvent, const States& _rStates )
418 : {
419 948 : for ( States::const_iterator state = _rStates.begin();
420 632 : state != _rStates.end();
421 : ++state
422 : )
423 : {
424 158 : _rEvent.State = *state;
425 158 : _rListener.statusChanged( _rEvent );
426 : }
427 158 : }
428 :
429 638 : void lcl_collectStates( const FeatureState& _rFeatureState, States& _out_rStates )
430 : {
431 : // order matters, due to a bug in framework which resets the check state when any non-boolean event
432 : // arrives
433 : // #i68215# is the bug to (re-)introduce this "ordered" notification here
434 : // #i67882# is the bug which was caused by the real fix which we did in framework
435 : // #i68216# is the bug which requests to fix the code in Draw which relies on
436 : // framework's implementation details
437 638 : if ( !!_rFeatureState.sTitle )
438 59 : _out_rStates.push_back( makeAny( *_rFeatureState.sTitle ) );
439 638 : if ( !!_rFeatureState.bChecked )
440 68 : _out_rStates.push_back( makeAny( *_rFeatureState.bChecked ) );
441 638 : if ( !!_rFeatureState.bInvisible )
442 6 : _out_rStates.push_back( makeAny( Visibility( !*_rFeatureState.bInvisible ) ) );
443 638 : if ( _rFeatureState.aValue.hasValue() )
444 0 : _out_rStates.push_back( _rFeatureState.aValue );
445 638 : if ( _out_rStates.empty() )
446 505 : _out_rStates.push_back( Any() );
447 638 : }
448 : }
449 :
450 706 : void OGenericUnoController::ImplBroadcastFeatureState(const OUString& _rFeature, const Reference< XStatusListener > & xListener, bool _bIgnoreCache)
451 : {
452 706 : sal_uInt16 nFeat = m_aSupportedFeatures[ _rFeature ].nFeatureId;
453 706 : FeatureState aFeatState( GetState( nFeat ) );
454 :
455 706 : FeatureState& rCachedState = m_aStateCache[nFeat]; // creates if necessary
456 706 : if ( !_bIgnoreCache )
457 : {
458 : // check if we really need to notify the listeners : this method may be called much more often than needed, so check
459 : // the cached state of the feature
460 72 : bool bAlreadyCached = ( m_aStateCache.find(nFeat) != m_aStateCache.end() );
461 72 : if ( bAlreadyCached )
462 144 : if ( ( rCachedState.bEnabled == aFeatState.bEnabled )
463 68 : && ( rCachedState.bChecked == aFeatState.bChecked )
464 68 : && ( rCachedState.bInvisible == aFeatState.bInvisible )
465 140 : && ( rCachedState.sTitle == aFeatState.sTitle )
466 : )
467 774 : return;
468 : }
469 638 : rCachedState = aFeatState;
470 :
471 1276 : FeatureStateEvent aEvent;
472 638 : aEvent.FeatureURL.Complete = _rFeature;
473 638 : if (m_xUrlTransformer.is())
474 638 : m_xUrlTransformer->parseStrict(aEvent.FeatureURL);
475 638 : aEvent.Source = static_cast<XDispatch*>(this);
476 638 : aEvent.IsEnabled = aFeatState.bEnabled;
477 :
478 : // collect all states to be notified
479 1276 : States aStates;
480 638 : lcl_collectStates( aFeatState, aStates );
481 :
482 : // a special listener ?
483 638 : if ( xListener.is() )
484 32 : lcl_notifyMultipleStates( *xListener.get(), aEvent, aStates );
485 : else
486 : { // no -> iterate through all listeners responsible for the URL
487 606 : StringBag aFeatureCommands;
488 : ::std::for_each(
489 : m_aSupportedFeatures.begin(),
490 : m_aSupportedFeatures.end(),
491 : CommandCollector( nFeat, aFeatureCommands )
492 606 : );
493 :
494 : // it is possible that listeners are registered or revoked while
495 : // we are notifying them, so we must use a copy of m_arrStatusListener, not
496 : // m_arrStatusListener itself
497 1212 : Dispatch aNotifyLoop( m_arrStatusListener );
498 606 : Dispatch::iterator iterSearch = aNotifyLoop.begin();
499 606 : Dispatch::iterator iterEnd = aNotifyLoop.end();
500 :
501 4138 : while (iterSearch != iterEnd)
502 : {
503 2926 : DispatchTarget& rCurrent = *iterSearch;
504 2926 : if ( aFeatureCommands.find( rCurrent.aURL.Complete ) != aFeatureCommands.end() )
505 : {
506 126 : aEvent.FeatureURL = rCurrent.aURL;
507 126 : lcl_notifyMultipleStates( *rCurrent.xListener.get(), aEvent, aStates );
508 : }
509 2926 : ++iterSearch;
510 606 : }
511 638 : }
512 :
513 : }
514 :
515 0 : bool OGenericUnoController::isFeatureSupported( sal_Int32 _nId )
516 : {
517 : SupportedFeatures::iterator aFeaturePos = ::std::find_if(
518 : m_aSupportedFeatures.begin(),
519 : m_aSupportedFeatures.end(),
520 : ::std::bind2nd( CompareFeatureById(), _nId )
521 0 : );
522 :
523 0 : return ( m_aSupportedFeatures.end() != aFeaturePos && !aFeaturePos->first.isEmpty());
524 : }
525 :
526 11 : void OGenericUnoController::InvalidateFeature_Impl()
527 : {
528 : #ifdef DBG_UTIL
529 : static sal_Int32 s_nRecursions = 0;
530 : ++s_nRecursions;
531 : #endif
532 :
533 11 : bool bEmpty = true;
534 11 : FeatureListener aNextFeature;
535 : {
536 11 : ::osl::MutexGuard aGuard( m_aFeatureMutex);
537 11 : bEmpty = m_aFeaturesToInvalidate.empty();
538 11 : if (!bEmpty)
539 11 : aNextFeature = m_aFeaturesToInvalidate.front();
540 : }
541 94 : while(!bEmpty)
542 : {
543 82 : if ( ALL_FEATURES == aNextFeature.nId )
544 : {
545 10 : InvalidateAll_Impl();
546 20 : break;
547 : }
548 : else
549 : {
550 : SupportedFeatures::iterator aFeaturePos = ::std::find_if(
551 : m_aSupportedFeatures.begin(),
552 : m_aSupportedFeatures.end(),
553 : ::std::bind2nd( CompareFeatureById(), aNextFeature.nId )
554 72 : );
555 :
556 : #if OSL_DEBUG_LEVEL > 0
557 : if ( m_aSupportedFeatures.end() == aFeaturePos )
558 : {
559 : OString sMessage( "OGenericUnoController::InvalidateFeature_Impl: feature id " );
560 : sMessage += OString::number( aNextFeature.nId );
561 : sMessage += OString( " has been invalidated, but is not supported!" );
562 : SAL_WARN("dbaccess.ui", sMessage.getStr() );
563 : }
564 : #endif
565 72 : if ( m_aSupportedFeatures.end() != aFeaturePos )
566 : // we really know this feature
567 72 : ImplBroadcastFeatureState( aFeaturePos->first, aNextFeature.xListener, aNextFeature.bForceBroadcast );
568 : }
569 :
570 72 : ::osl::MutexGuard aGuard( m_aFeatureMutex);
571 72 : m_aFeaturesToInvalidate.pop_front();
572 72 : bEmpty = m_aFeaturesToInvalidate.empty();
573 72 : if (!bEmpty)
574 71 : aNextFeature = m_aFeaturesToInvalidate.front();
575 83 : }
576 :
577 : #ifdef DBG_UTIL
578 : --s_nRecursions;
579 : #endif
580 11 : }
581 :
582 125 : void OGenericUnoController::ImplInvalidateFeature( sal_Int32 _nId, const Reference< XStatusListener >& _xListener, bool _bForceBroadcast )
583 : {
584 : #if OSL_DEBUG_LEVEL > 0
585 : if ( _nId != -1 )
586 : {
587 : SupportedFeatures::iterator aFeaturePos = ::std::find_if(
588 : m_aSupportedFeatures.begin(),
589 : m_aSupportedFeatures.end(),
590 : ::std::bind2nd( CompareFeatureById(), _nId )
591 : );
592 : OSL_ENSURE( aFeaturePos != m_aSupportedFeatures.end(), "OGenericUnoController::ImplInvalidateFeature: invalidating an unsupported feature is suspicious, at least!" );
593 : }
594 : #endif
595 :
596 125 : FeatureListener aListener;
597 125 : aListener.nId = _nId;
598 125 : aListener.xListener = _xListener;
599 125 : aListener.bForceBroadcast = _bForceBroadcast;
600 :
601 : bool bWasEmpty;
602 : {
603 125 : ::osl::MutexGuard aGuard( m_aFeatureMutex );
604 125 : bWasEmpty = m_aFeaturesToInvalidate.empty();
605 125 : m_aFeaturesToInvalidate.push_back( aListener );
606 : }
607 :
608 125 : if ( bWasEmpty )
609 21 : m_aAsyncInvalidateAll.Call();
610 125 : }
611 :
612 98 : void OGenericUnoController::InvalidateFeature(sal_uInt16 _nId, const Reference< XStatusListener > & _xListener, bool _bForceBroadcast)
613 : {
614 98 : ImplInvalidateFeature( _nId, _xListener, _bForceBroadcast );
615 98 : }
616 :
617 27 : void OGenericUnoController::InvalidateAll()
618 : {
619 27 : ImplInvalidateFeature( ALL_FEATURES, NULL, true );
620 27 : }
621 :
622 10 : void OGenericUnoController::InvalidateAll_Impl()
623 : {
624 : // invalidate all supported features
625 :
626 1836 : for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
627 1224 : aIter != m_aSupportedFeatures.end();
628 : ++aIter
629 : )
630 602 : ImplBroadcastFeatureState( aIter->first, NULL, true );
631 :
632 : {
633 10 : ::osl::MutexGuard aGuard( m_aFeatureMutex);
634 : OSL_ENSURE(m_aFeaturesToInvalidate.size(), "OGenericUnoController::InvalidateAll_Impl: to be called from within InvalidateFeature_Impl only!");
635 10 : m_aFeaturesToInvalidate.pop_front();
636 10 : if(!m_aFeaturesToInvalidate.empty())
637 6 : m_aAsyncInvalidateAll.Call();
638 : }
639 10 : }
640 :
641 47 : Reference< XDispatch > OGenericUnoController::queryDispatch(const URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException, std::exception )
642 : {
643 47 : Reference< XDispatch > xReturn;
644 :
645 : OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::queryDispatch: shouldn't this be filled at construction time?" );
646 47 : if ( m_aSupportedFeatures.empty() )
647 0 : fillSupportedFeatures();
648 :
649 : // URL's we can handle ourself?
650 141 : if ( aURL.Complete == ".uno:FormSlots/ConfirmDeletion"
651 220 : || ( ( m_aSupportedFeatures.find( aURL.Complete ) != m_aSupportedFeatures.end() )
652 32 : && !isUserDefinedFeature( aURL.Complete )
653 : )
654 : )
655 : {
656 32 : xReturn = this;
657 : }
658 : // no? -> ask the slave dispatcher
659 15 : else if ( m_xSlaveDispatcher.is() )
660 : {
661 9 : xReturn = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
662 : }
663 :
664 : // outta here
665 47 : return xReturn;
666 : }
667 :
668 0 : Sequence< Reference< XDispatch > > OGenericUnoController::queryDispatches(const Sequence< DispatchDescriptor >& aDescripts) throw( RuntimeException, std::exception )
669 : {
670 0 : Sequence< Reference< XDispatch > > aReturn;
671 0 : sal_Int32 nLen = aDescripts.getLength();
672 0 : if ( nLen )
673 : {
674 0 : aReturn.realloc( nLen );
675 0 : Reference< XDispatch >* pReturn = aReturn.getArray();
676 0 : const Reference< XDispatch >* pReturnEnd = aReturn.getArray() + nLen;
677 0 : const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
678 :
679 0 : for ( ; pReturn != pReturnEnd; ++ pReturn, ++pDescripts )
680 : {
681 0 : *pReturn = queryDispatch( pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags );
682 : }
683 : }
684 :
685 0 : return aReturn;
686 : }
687 :
688 2 : Reference< XDispatchProvider > OGenericUnoController::getSlaveDispatchProvider() throw( RuntimeException, std::exception )
689 : {
690 2 : return m_xSlaveDispatcher;
691 : }
692 :
693 2 : void OGenericUnoController::setSlaveDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider) throw( RuntimeException, std::exception )
694 : {
695 2 : m_xSlaveDispatcher = _xNewProvider;
696 2 : }
697 :
698 1 : Reference< XDispatchProvider > OGenericUnoController::getMasterDispatchProvider() throw( RuntimeException, std::exception )
699 : {
700 1 : return m_xMasterDispatcher;
701 : }
702 :
703 2 : void OGenericUnoController::setMasterDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider) throw( RuntimeException, std::exception )
704 : {
705 2 : m_xMasterDispatcher = _xNewProvider;
706 2 : }
707 :
708 0 : void OGenericUnoController::dispatch(const URL& _aURL, const Sequence< PropertyValue >& aArgs) throw(RuntimeException, std::exception)
709 : {
710 0 : SolarMutexGuard aSolarGuard;
711 : // The SolarMutex is not locked anymore when the framework calls into
712 : // here. So, lock it ourself. The real solution would be to lock it only in the places
713 : // where it's needed, but a) this might turn out difficult, since we then also need to care
714 : // for locking in the proper order (SolarMutex and m_aMutex), and b) this would be too many places
715 : // for the time frame of the fix.
716 : // #i52602#
717 0 : executeChecked(_aURL,aArgs);
718 0 : }
719 :
720 32 : void OGenericUnoController::addStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL) throw(RuntimeException, std::exception)
721 : {
722 : // parse the URL now and here, this saves later parsing in each notification round
723 32 : URL aParsedURL( _rURL );
724 32 : if ( m_xUrlTransformer.is() )
725 32 : m_xUrlTransformer->parseStrict( aParsedURL );
726 :
727 : // remember the listener together with the URL
728 32 : m_arrStatusListener.insert( m_arrStatusListener.end(), DispatchTarget( aParsedURL, aListener ) );
729 :
730 : // initially broadcast the state
731 32 : ImplBroadcastFeatureState( aParsedURL.Complete, aListener, true );
732 : // force the new state to be broadcast to the new listener
733 32 : }
734 :
735 32 : void OGenericUnoController::removeStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL) throw(RuntimeException, std::exception)
736 : {
737 32 : Dispatch::iterator iterSearch = m_arrStatusListener.begin();
738 :
739 32 : bool bRemoveForAll = _rURL.Complete.isEmpty();
740 229 : while ( iterSearch != m_arrStatusListener.end() )
741 : {
742 197 : DispatchTarget& rCurrent = *iterSearch;
743 394 : if ( (rCurrent.xListener == aListener)
744 229 : && ( bRemoveForAll
745 52 : || (rCurrent.aURL.Complete.equals(_rURL.Complete))
746 : )
747 : )
748 : {
749 32 : m_arrStatusListener.erase( iterSearch++ );
750 32 : if (!bRemoveForAll)
751 : // remove the listener only for the given URL, so we can exit the loop after deletion
752 32 : break;
753 : }
754 : else
755 165 : ++iterSearch;
756 : }
757 :
758 : OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::removeStatusListener: shouldn't this be filled at construction time?" );
759 32 : if ( m_aSupportedFeatures.empty() )
760 0 : fillSupportedFeatures();
761 :
762 32 : SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find(_rURL.Complete);
763 32 : if (aIter != m_aSupportedFeatures.end())
764 : { // clear the cache for that feature
765 32 : StateCache::iterator aCachePos = m_aStateCache.find( aIter->second.nFeatureId );
766 32 : if ( aCachePos != m_aStateCache.end() )
767 31 : m_aStateCache.erase( aCachePos );
768 : }
769 :
770 : // now remove the listener from the deque
771 32 : ::osl::MutexGuard aGuard( m_aFeatureMutex );
772 : m_aFeaturesToInvalidate.erase(
773 : ::std::remove_if( m_aFeaturesToInvalidate.begin(),
774 : m_aFeaturesToInvalidate.end(),
775 : ::std::bind2nd(FindFeatureListener(),aListener))
776 32 : ,m_aFeaturesToInvalidate.end());
777 32 : }
778 :
779 12 : void OGenericUnoController::releaseNumberForComponent()
780 : {
781 : try
782 : {
783 12 : Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
784 12 : if ( xUntitledProvider.is() )
785 0 : xUntitledProvider->releaseNumberForComponent(static_cast<XWeak*>(this));
786 : }
787 0 : catch( const Exception& )
788 : {
789 : // NII
790 : }
791 12 : }
792 :
793 12 : void OGenericUnoController::disposing()
794 : {
795 : {
796 12 : EventObject aDisposeEvent;
797 12 : aDisposeEvent.Source = static_cast<XWeak*>(this);
798 24 : Dispatch aStatusListener = m_arrStatusListener;
799 12 : Dispatch::iterator aEnd = aStatusListener.end();
800 13 : for (Dispatch::iterator aIter = aStatusListener.begin(); aIter != aEnd; ++aIter)
801 : {
802 1 : aIter->xListener->disposing(aDisposeEvent);
803 : }
804 24 : m_arrStatusListener.clear();
805 : }
806 :
807 12 : m_xDatabaseContext = NULL;
808 : {
809 12 : ::osl::MutexGuard aGuard( m_aFeatureMutex);
810 12 : m_aAsyncInvalidateAll.CancelCall();
811 12 : m_aFeaturesToInvalidate.clear();
812 : }
813 :
814 12 : releaseNumberForComponent();
815 :
816 : // check out from all the objects we are listening
817 : // the frame
818 12 : stopFrameListening( m_aCurrentFrame.getFrame() );
819 12 : m_aCurrentFrame.attachFrame( NULL );
820 :
821 12 : m_xMasterDispatcher = NULL;
822 12 : m_xSlaveDispatcher = NULL;
823 12 : m_xTitleHelper.clear();
824 12 : m_xUrlTransformer.clear();
825 12 : m_aInitParameters.clear();
826 12 : }
827 :
828 0 : void SAL_CALL OGenericUnoController::addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException, std::exception)
829 : {
830 : // disambiguate
831 0 : OGenericUnoController_Base::WeakComponentImplHelperBase::addEventListener( xListener );
832 0 : }
833 :
834 0 : void SAL_CALL OGenericUnoController::removeEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException, std::exception)
835 : {
836 : // disambiguate
837 0 : OGenericUnoController_Base::WeakComponentImplHelperBase::removeEventListener( xListener );
838 0 : }
839 :
840 6 : void OGenericUnoController::frameAction(const FrameActionEvent& aEvent) throw( RuntimeException, std::exception )
841 : {
842 6 : ::osl::MutexGuard aGuard( getMutex() );
843 6 : if ( aEvent.Frame == m_aCurrentFrame.getFrame() )
844 6 : m_aCurrentFrame.frameAction( aEvent.Action );
845 6 : }
846 :
847 574 : void OGenericUnoController::implDescribeSupportedFeature( const sal_Char* _pAsciiCommandURL,
848 : sal_uInt16 _nFeatureId, sal_Int16 _nCommandGroup )
849 : {
850 : #ifdef DBG_UTIL
851 : OSL_ENSURE( m_bDescribingSupportedFeatures, "OGenericUnoController::implDescribeSupportedFeature: bad timing for this call!" );
852 : #endif
853 : OSL_PRECOND( _nFeatureId < FIRST_USER_DEFINED_FEATURE, "OGenericUnoController::implDescribeSupportedFeature: invalid feature id!" );
854 :
855 574 : ControllerFeature aFeature;
856 574 : aFeature.Command = OUString::createFromAscii( _pAsciiCommandURL );
857 574 : aFeature.nFeatureId = _nFeatureId;
858 574 : aFeature.GroupId = _nCommandGroup;
859 :
860 : #if OSL_DEBUG_LEVEL > 0
861 : OSL_ENSURE( m_aSupportedFeatures.find( aFeature.Command ) == m_aSupportedFeatures.end(),
862 : "OGenericUnoController::implDescribeSupportedFeature: this feature is already there!" );
863 : #endif
864 574 : m_aSupportedFeatures[ aFeature.Command ] = aFeature;
865 574 : }
866 :
867 8 : void OGenericUnoController::describeSupportedFeatures()
868 : {
869 : // add all supported features
870 8 : implDescribeSupportedFeature( ".uno:Copy", ID_BROWSER_COPY, CommandGroup::EDIT );
871 8 : implDescribeSupportedFeature( ".uno:Cut", ID_BROWSER_CUT, CommandGroup::EDIT );
872 8 : implDescribeSupportedFeature( ".uno:Paste", ID_BROWSER_PASTE, CommandGroup::EDIT );
873 8 : implDescribeSupportedFeature( ".uno:ClipboardFormatItems", ID_BROWSER_CLIPBOARD_FORMAT_ITEMS );
874 8 : implDescribeSupportedFeature( ".uno:DSBEditDoc", ID_BROWSER_EDITDOC, CommandGroup::DOCUMENT );
875 8 : }
876 :
877 30 : FeatureState OGenericUnoController::GetState( sal_uInt16 _nId ) const
878 : {
879 30 : FeatureState aReturn;
880 : // (disabled automatically)
881 :
882 30 : switch ( _nId )
883 : {
884 : case ID_BROWSER_UNDO:
885 : case ID_BROWSER_SAVEDOC:
886 0 : aReturn.bEnabled = true;
887 0 : break;
888 : default:
889 30 : aReturn = UserDefinedFeatures::getState( getURLForId( _nId ) );
890 30 : break;
891 : }
892 :
893 30 : return aReturn;
894 : }
895 :
896 0 : void OGenericUnoController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue>& _rArgs )
897 : {
898 : OSL_ENSURE( isUserDefinedFeature( _nId ),
899 : "OGenericUnoController::Execute: responsible for user defined features only!" );
900 :
901 : // user defined features can be handled by dispatch interceptors resp. protocol handlers only.
902 : // So, we need to do a queryDispatch, and dispatch the URL
903 0 : m_pData->m_aUserDefinedFeatures.execute( getURLForId( _nId ), _rArgs );
904 0 : }
905 :
906 30 : URL OGenericUnoController::getURLForId(sal_Int32 _nId) const
907 : {
908 30 : URL aReturn;
909 30 : if ( m_xUrlTransformer.is() )
910 : {
911 : SupportedFeatures::const_iterator aIter = ::std::find_if(
912 : m_aSupportedFeatures.begin(),
913 : m_aSupportedFeatures.end(),
914 : ::std::bind2nd( CompareFeatureById(), _nId )
915 30 : );
916 :
917 30 : if ( m_aSupportedFeatures.end() != aIter && !aIter->first.isEmpty() )
918 : {
919 30 : aReturn.Complete = aIter->first;
920 30 : m_xUrlTransformer->parseStrict( aReturn );
921 : }
922 : }
923 30 : return aReturn;
924 : }
925 :
926 39 : bool OGenericUnoController::isUserDefinedFeature( const sal_uInt16 _nFeatureId )
927 : {
928 39 : return ( _nFeatureId >= FIRST_USER_DEFINED_FEATURE ) && ( _nFeatureId < LAST_USER_DEFINED_FEATURE );
929 : }
930 :
931 32 : bool OGenericUnoController::isUserDefinedFeature( const OUString& _rFeatureURL ) const
932 : {
933 32 : SupportedFeatures::const_iterator pos = m_aSupportedFeatures.find( _rFeatureURL );
934 : OSL_PRECOND( pos != m_aSupportedFeatures.end(),
935 : "OGenericUnoController::isUserDefinedFeature: this is no supported feature at all!" );
936 :
937 32 : return ( pos != m_aSupportedFeatures.end() ) && isUserDefinedFeature( pos->second.nFeatureId );
938 : }
939 :
940 0 : sal_Bool SAL_CALL OGenericUnoController::supportsService(const OUString& ServiceName) throw(RuntimeException, std::exception)
941 : {
942 0 : return cppu::supportsService(this, ServiceName);
943 : }
944 :
945 1 : void OGenericUnoController::startConnectionListening(const Reference< XConnection >& _rxConnection)
946 : {
947 : // we have to remove ourself before dispoing the connection
948 1 : Reference< XComponent > xComponent(_rxConnection, UNO_QUERY);
949 1 : if (xComponent.is())
950 1 : xComponent->addEventListener(static_cast<XFrameActionListener*>(this));
951 1 : }
952 :
953 4 : void OGenericUnoController::stopConnectionListening(const Reference< XConnection >& _rxConnection)
954 : {
955 : // we have to remove ourself before dispoing the connection
956 4 : Reference< XComponent > xComponent(_rxConnection, UNO_QUERY);
957 4 : if (xComponent.is())
958 0 : xComponent->removeEventListener(static_cast<XFrameActionListener*>(this));
959 4 : }
960 :
961 0 : Reference< XConnection > OGenericUnoController::connect( const Reference< XDataSource>& _xDataSource,
962 : ::dbtools::SQLExceptionInfo* _pErrorInfo )
963 : {
964 0 : WaitObject aWaitCursor( getView() );
965 :
966 0 : ODatasourceConnector aConnector( getORB(), getView(), OUString() );
967 0 : Reference< XConnection > xConnection = aConnector.connect( _xDataSource, _pErrorInfo );
968 0 : startConnectionListening( xConnection );
969 :
970 0 : return xConnection;
971 : }
972 :
973 1 : Reference< XConnection > OGenericUnoController::connect( const OUString& _rDataSourceName,
974 : const OUString& _rContextInformation, ::dbtools::SQLExceptionInfo* _pErrorInfo )
975 : {
976 1 : WaitObject aWaitCursor( getView() );
977 :
978 2 : ODatasourceConnector aConnector( getORB(), getView(), _rContextInformation );
979 1 : Reference<XConnection> xConnection = aConnector.connect( _rDataSourceName, _pErrorInfo );
980 1 : startConnectionListening( xConnection );
981 :
982 2 : return xConnection;
983 : }
984 :
985 8 : void OGenericUnoController::setView( const VclPtr<ODataView> &i_rView )
986 : {
987 8 : m_pView = i_rView;
988 8 : }
989 :
990 17 : void OGenericUnoController::clearView()
991 : {
992 17 : m_pView = NULL;
993 17 : }
994 :
995 0 : void OGenericUnoController::showError(const SQLExceptionInfo& _rInfo)
996 : {
997 0 : ::dbaui::showError(_rInfo,getView(),getORB());
998 0 : }
999 :
1000 22 : Reference< XLayoutManager > OGenericUnoController::getLayoutManager(const Reference< XFrame >& _xFrame)
1001 : {
1002 22 : Reference< XPropertySet > xPropSet( _xFrame, UNO_QUERY );
1003 22 : Reference< XLayoutManager > xLayoutManager;
1004 22 : if ( xPropSet.is() )
1005 : {
1006 : try
1007 : {
1008 11 : xLayoutManager.set(xPropSet->getPropertyValue("LayoutManager"),UNO_QUERY);
1009 : }
1010 0 : catch ( Exception& )
1011 : {
1012 : }
1013 : }
1014 22 : return xLayoutManager;
1015 : }
1016 :
1017 17 : void OGenericUnoController::loadMenu(const Reference< XFrame >& _xFrame)
1018 : {
1019 17 : Reference< XLayoutManager > xLayoutManager = getLayoutManager(_xFrame);
1020 17 : if ( xLayoutManager.is() )
1021 : {
1022 7 : xLayoutManager->lock();
1023 7 : xLayoutManager->createElement( OUString( "private:resource/menubar/menubar" ));
1024 7 : xLayoutManager->createElement( OUString( "private:resource/toolbar/toolbar" ));
1025 7 : xLayoutManager->unlock();
1026 7 : xLayoutManager->doLayout();
1027 : }
1028 :
1029 17 : onLoadedMenu( xLayoutManager );
1030 17 : }
1031 :
1032 3 : void OGenericUnoController::onLoadedMenu(const Reference< XLayoutManager >& /*_xLayoutManager*/)
1033 : {
1034 : // not interested in
1035 3 : }
1036 :
1037 0 : void OGenericUnoController::closeTask()
1038 : {
1039 0 : m_aAsyncCloseTask.Call();
1040 0 : }
1041 :
1042 0 : IMPL_LINK_NOARG(OGenericUnoController, OnAsyncCloseTask)
1043 : {
1044 0 : if ( !OGenericUnoController_Base::rBHelper.bInDispose )
1045 : {
1046 : try
1047 : {
1048 0 : Reference< util::XCloseable > xCloseable( m_aCurrentFrame.getFrame(), UNO_QUERY_THROW );
1049 0 : xCloseable->close( sal_False ); // false - holds the owner ship for this frame inside this object!
1050 : }
1051 0 : catch( const Exception& )
1052 : {
1053 : DBG_UNHANDLED_EXCEPTION();
1054 : }
1055 : }
1056 0 : return 0L;
1057 : }
1058 :
1059 0 : Any SAL_CALL OGenericUnoController::getViewData() throw( RuntimeException, std::exception )
1060 : {
1061 0 : return Any();
1062 : }
1063 :
1064 0 : void SAL_CALL OGenericUnoController::restoreViewData(const Any& /*Data*/) throw( RuntimeException, std::exception )
1065 : {
1066 0 : }
1067 :
1068 46 : Reference< XModel > SAL_CALL OGenericUnoController::getModel() throw( RuntimeException, std::exception )
1069 : {
1070 46 : return Reference< XModel >();
1071 : }
1072 :
1073 36 : Reference< XFrame > SAL_CALL OGenericUnoController::getFrame() throw( RuntimeException, std::exception )
1074 : {
1075 36 : ::osl::MutexGuard aGuard( getMutex() );
1076 36 : return m_aCurrentFrame.getFrame();
1077 : }
1078 :
1079 0 : sal_Bool SAL_CALL OGenericUnoController::attachModel(const Reference< XModel > & /*xModel*/) throw( RuntimeException, std::exception )
1080 : {
1081 : SAL_WARN("dbaccess.ui", "OGenericUnoController::attachModel: not supported!" );
1082 0 : return sal_False;
1083 : }
1084 :
1085 0 : void OGenericUnoController::executeUnChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
1086 : {
1087 0 : Execute(_nCommandId, aArgs);
1088 0 : }
1089 :
1090 0 : void OGenericUnoController::executeUnChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
1091 : {
1092 : OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeUnChecked: shouldn't this be filled at construction time?" );
1093 0 : if ( m_aSupportedFeatures.empty() )
1094 0 : fillSupportedFeatures();
1095 :
1096 0 : SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
1097 0 : if (aIter != m_aSupportedFeatures.end())
1098 0 : Execute( aIter->second.nFeatureId, aArgs );
1099 0 : }
1100 :
1101 0 : void OGenericUnoController::executeChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
1102 : {
1103 : OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeChecked: shouldn't this be filled at construction time?" );
1104 0 : if ( m_aSupportedFeatures.empty() )
1105 0 : fillSupportedFeatures();
1106 :
1107 0 : SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
1108 0 : if ( aIter != m_aSupportedFeatures.end() )
1109 : {
1110 0 : sal_uInt16 nFeatureId = aIter->second.nFeatureId;
1111 0 : if ( GetState( nFeatureId ).bEnabled )
1112 0 : Execute( nFeatureId, aArgs );
1113 : }
1114 0 : }
1115 :
1116 : namespace
1117 : {
1118 0 : OUString lcl_getModuleHelpModuleName( const Reference< XFrame >& _rxFrame )
1119 : {
1120 0 : const sal_Char* pReturn = NULL;
1121 :
1122 : try
1123 : {
1124 : // get the model of the document in the given frame
1125 0 : Reference< XController > xController;
1126 0 : if ( _rxFrame.is() )
1127 0 : xController = _rxFrame->getController();
1128 0 : Reference< XModel > xModel;
1129 0 : if ( xController.is() )
1130 0 : xModel = xController->getModel();
1131 0 : Reference< XServiceInfo > xSI( xModel, UNO_QUERY );
1132 :
1133 0 : if ( !xSI.is() )
1134 : { // try to go up the frame hierarchy
1135 :
1136 0 : Reference< XFrame > xParentFrame;
1137 0 : if ( _rxFrame.is() )
1138 0 : xParentFrame.set(_rxFrame->getCreator(), css::uno::UNO_QUERY);
1139 : // did we find a parent frame? Which is no top-level frame?
1140 0 : if ( xParentFrame.is() && !_rxFrame->isTop() )
1141 : // TODO: to prevent framework assertions, re-insert this "isTop" once 98303 is fixed
1142 0 : return lcl_getModuleHelpModuleName( xParentFrame );
1143 : }
1144 : else
1145 : {
1146 : #if OSL_DEBUG_LEVEL > 0
1147 : Sequence< OUString > sServiceNames = xSI->getSupportedServiceNames();
1148 : const OUString* pLoop = sServiceNames.getConstArray();
1149 : for ( sal_Int32 i=0; i<sServiceNames.getLength(); ++i, ++pLoop )
1150 : {
1151 : sal_Int32 nDummy = 0;
1152 : (void)nDummy;
1153 : }
1154 : #endif
1155 :
1156 : // check which service we know ....
1157 : static const sal_Char* pTransTable[] = {
1158 : "com.sun.star.sdb.OfficeDatabaseDocument","sdatabase",
1159 : "com.sun.star.report.ReportDefinition","sdatabase",
1160 : "com.sun.star.text.TextDocument", "swriter",
1161 : "com.sun.star.sheet.SpreadsheetDocument", "scalc",
1162 : "com.sun.star.presentation.PresentationDocument", "simpress",
1163 : "com.sun.star.drawing.DrawingDocument", "sdraw",
1164 : "com.sun.star.formula.FormularProperties", "smath",
1165 : "com.sun.star.chart.ChartDocument", "schart"
1166 : };
1167 : OSL_ENSURE( ( sizeof( pTransTable ) / sizeof( pTransTable[0] ) ) % 2 == 0,
1168 : "lcl_getModuleHelpModuleName: odd size of translation table!" );
1169 :
1170 : // loop through the table
1171 0 : sal_Int32 nTableEntries = ( sizeof( pTransTable ) / sizeof( pTransTable[0] ) ) / 2;
1172 0 : const sal_Char** pDocumentService = pTransTable;
1173 0 : const sal_Char** pHelpModuleName = pTransTable + 1;
1174 0 : for ( sal_Int32 j=0; j<nTableEntries; ++j )
1175 : {
1176 0 : if ( xSI->supportsService( OUString::createFromAscii( *pDocumentService ) ) )
1177 : { // found a table entry which matches the model's services
1178 0 : pReturn = *pHelpModuleName;
1179 0 : break;
1180 : }
1181 :
1182 0 : ++pDocumentService; ++pDocumentService;
1183 0 : ++pHelpModuleName; ++pHelpModuleName;
1184 : }
1185 : }
1186 :
1187 0 : if ( !pReturn )
1188 : {
1189 : // could not determine the document type we're living in
1190 : // ->fallback
1191 0 : SvtModuleOptions aModOpt;
1192 0 : if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
1193 0 : pReturn = "swriter";
1194 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
1195 0 : pReturn = "sdatabase";
1196 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
1197 0 : pReturn = "scalc";
1198 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
1199 0 : pReturn = "simpress";
1200 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
1201 0 : pReturn = "sdraw";
1202 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::MATH ) )
1203 0 : pReturn = "smath";
1204 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::CHART ) )
1205 0 : pReturn = "schart";
1206 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::EModule::BASIC ) )
1207 0 : pReturn = "sbasic";
1208 : else
1209 : {
1210 : SAL_WARN("dbaccess.ui", "lcl_getModuleHelpModuleName: no installed module found" );
1211 0 : }
1212 0 : }
1213 : }
1214 0 : catch( const Exception& )
1215 : {
1216 : DBG_UNHANDLED_EXCEPTION();
1217 : }
1218 :
1219 0 : if ( !pReturn )
1220 0 : pReturn = "swriter";
1221 :
1222 0 : return OUString::createFromAscii( pReturn );
1223 : }
1224 : }
1225 :
1226 0 : void OGenericUnoController::openHelpAgent(OUString const& _suHelpStringURL )
1227 : {
1228 0 : OUString suURL(_suHelpStringURL);
1229 0 : OUString sLanguage( "Language=" );
1230 0 : if (suURL.indexOf(sLanguage) == -1)
1231 : {
1232 0 : AppendConfigToken(suURL, false /* sal_False := add '&' */ );
1233 : }
1234 0 : URL aURL;
1235 0 : aURL.Complete = suURL;
1236 :
1237 0 : openHelpAgent( aURL );
1238 0 : }
1239 :
1240 0 : void OGenericUnoController::openHelpAgent(const OString& _sHelpId)
1241 : {
1242 0 : openHelpAgent( createHelpAgentURL( lcl_getModuleHelpModuleName( getFrame() ), _sHelpId ) );
1243 0 : }
1244 :
1245 0 : void OGenericUnoController::openHelpAgent( const URL& _rURL )
1246 : {
1247 : try
1248 : {
1249 0 : URL aURL( _rURL );
1250 :
1251 0 : if ( m_xUrlTransformer.is() )
1252 0 : m_xUrlTransformer->parseStrict(aURL);
1253 :
1254 0 : Reference< XDispatchProvider > xDispProv( m_aCurrentFrame.getFrame(), UNO_QUERY );
1255 0 : Reference< XDispatch > xHelpDispatch;
1256 0 : if ( xDispProv.is() )
1257 0 : xHelpDispatch = xDispProv->queryDispatch(aURL, OUString( "_helpagent" ), FrameSearchFlag::PARENT | FrameSearchFlag::SELF);
1258 : OSL_ENSURE(xHelpDispatch.is(), "SbaTableQueryBrowser::openHelpAgent: could not get a dispatcher!");
1259 0 : if (xHelpDispatch.is())
1260 : {
1261 0 : xHelpDispatch->dispatch(aURL, Sequence< PropertyValue >());
1262 0 : }
1263 : }
1264 0 : catch( const Exception& )
1265 : {
1266 : DBG_UNHANDLED_EXCEPTION();
1267 : }
1268 0 : }
1269 :
1270 0 : Reference< awt::XWindow> OGenericUnoController::getTopMostContainerWindow() const
1271 : {
1272 0 : Reference< ::com::sun::star::awt::XWindow> xWindow;
1273 :
1274 : // get the top most window
1275 0 : Reference< XFrame > xFrame( m_aCurrentFrame.getFrame() );
1276 0 : if ( xFrame.is() )
1277 : {
1278 0 : xWindow = xFrame->getContainerWindow();
1279 :
1280 0 : while ( xFrame.is() && !xFrame->isTop() )
1281 : {
1282 0 : xFrame.set( xFrame->getCreator(), UNO_QUERY );
1283 : }
1284 0 : if ( xFrame.is() )
1285 0 : xWindow = xFrame->getContainerWindow();
1286 : }
1287 0 : return xWindow;
1288 : }
1289 :
1290 34 : Reference< XTitle > OGenericUnoController::impl_getTitleHelper_throw()
1291 : {
1292 34 : SolarMutexGuard aSolarGuard;
1293 68 : ::osl::MutexGuard aGuard( getMutex() );
1294 :
1295 34 : if ( ! m_xTitleHelper.is ())
1296 : {
1297 13 : Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
1298 26 : Reference< XController > xThis(static_cast< XController* >(this), UNO_QUERY_THROW);
1299 :
1300 13 : ::framework::TitleHelper* pHelper = new ::framework::TitleHelper( m_xContext );
1301 13 : m_xTitleHelper.set( static_cast< ::cppu::OWeakObject* >(pHelper), UNO_QUERY_THROW);
1302 :
1303 13 : pHelper->setOwner (xThis );
1304 26 : pHelper->connectWithUntitledNumbers (xUntitledProvider);
1305 : }
1306 :
1307 68 : return m_xTitleHelper;
1308 : }
1309 :
1310 : // XTitle
1311 26 : OUString SAL_CALL OGenericUnoController::getTitle()
1312 : throw (RuntimeException, std::exception)
1313 : {
1314 26 : ::osl::MutexGuard aGuard( getMutex() );
1315 26 : if ( m_bExternalTitle )
1316 0 : return impl_getTitleHelper_throw()->getTitle ();
1317 26 : return getPrivateTitle() + impl_getTitleHelper_throw()->getTitle ();
1318 : }
1319 :
1320 : // XTitle
1321 0 : void SAL_CALL OGenericUnoController::setTitle(const OUString& sTitle)
1322 : throw (RuntimeException, std::exception)
1323 : {
1324 0 : SolarMutexGuard aSolarGuard;
1325 0 : ::osl::MutexGuard aGuard( getMutex() );
1326 0 : m_bExternalTitle = true;
1327 0 : impl_getTitleHelper_throw()->setTitle (sTitle);
1328 0 : }
1329 :
1330 : // XTitleChangeBroadcaster
1331 8 : void SAL_CALL OGenericUnoController::addTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
1332 : throw (RuntimeException, std::exception)
1333 : {
1334 8 : Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
1335 8 : if (xBroadcaster.is ())
1336 8 : xBroadcaster->addTitleChangeListener (xListener);
1337 8 : }
1338 :
1339 0 : void SAL_CALL OGenericUnoController::removeTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
1340 : throw (RuntimeException, std::exception)
1341 : {
1342 0 : Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
1343 0 : if (xBroadcaster.is ())
1344 0 : xBroadcaster->removeTitleChangeListener (xListener);
1345 0 : }
1346 :
1347 : // XUserInputInterception
1348 0 : void SAL_CALL OGenericUnoController::addKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException, std::exception)
1349 : {
1350 0 : if ( _rxHandler.is() )
1351 0 : m_pData->m_aUserInputInterception.addKeyHandler( _rxHandler );
1352 0 : }
1353 :
1354 0 : void SAL_CALL OGenericUnoController::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException, std::exception)
1355 : {
1356 0 : m_pData->m_aUserInputInterception.removeKeyHandler( _rxHandler );
1357 0 : }
1358 :
1359 0 : void SAL_CALL OGenericUnoController::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException, std::exception)
1360 : {
1361 0 : if ( _rxHandler.is() )
1362 0 : m_pData->m_aUserInputInterception.addMouseClickHandler( _rxHandler );
1363 0 : }
1364 :
1365 0 : void SAL_CALL OGenericUnoController::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException, std::exception)
1366 : {
1367 0 : m_pData->m_aUserInputInterception.removeMouseClickHandler( _rxHandler );
1368 0 : }
1369 :
1370 0 : void OGenericUnoController::executeChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
1371 : {
1372 0 : if ( isCommandEnabled(_nCommandId) )
1373 0 : Execute(_nCommandId, aArgs);
1374 0 : }
1375 :
1376 3 : bool OGenericUnoController::isCommandEnabled(sal_uInt16 _nCommandId) const
1377 : {
1378 3 : return GetState( _nCommandId ).bEnabled;
1379 : }
1380 :
1381 0 : sal_uInt16 OGenericUnoController::registerCommandURL( const OUString& _rCompleteCommandURL )
1382 : {
1383 0 : if ( _rCompleteCommandURL.isEmpty() )
1384 0 : return 0;
1385 :
1386 0 : SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL );
1387 0 : if ( aIter != m_aSupportedFeatures.end() )
1388 0 : return aIter->second.nFeatureId;
1389 :
1390 : // this is a previously unkwnon command
1391 0 : sal_uInt16 nFeatureId = FIRST_USER_DEFINED_FEATURE;
1392 0 : while ( isFeatureSupported( nFeatureId ) && ( nFeatureId < LAST_USER_DEFINED_FEATURE ) )
1393 0 : ++nFeatureId;
1394 0 : if ( nFeatureId == LAST_USER_DEFINED_FEATURE )
1395 : {
1396 : SAL_WARN("dbaccess.ui", "OGenericUnoController::registerCommandURL: no more space for user defined features!" );
1397 0 : return 0L;
1398 : }
1399 :
1400 0 : ControllerFeature aFeature;
1401 0 : aFeature.Command = _rCompleteCommandURL;
1402 0 : aFeature.nFeatureId = nFeatureId;
1403 0 : aFeature.GroupId = CommandGroup::INTERNAL;
1404 0 : m_aSupportedFeatures[ aFeature.Command ] = aFeature;
1405 :
1406 0 : return nFeatureId;
1407 : }
1408 :
1409 0 : void OGenericUnoController::notifyHiContrastChanged()
1410 : {
1411 0 : }
1412 :
1413 0 : bool OGenericUnoController::isDataSourceReadOnly() const
1414 : {
1415 0 : return false;
1416 : }
1417 :
1418 63 : Reference< XController > OGenericUnoController::getXController() throw( RuntimeException )
1419 : {
1420 63 : return this;
1421 : }
1422 :
1423 0 : bool OGenericUnoController::interceptUserInput( const NotifyEvent& _rEvent )
1424 : {
1425 0 : return m_pData->m_aUserInputInterception.handleNotifyEvent( _rEvent );
1426 : }
1427 :
1428 0 : bool OGenericUnoController::isCommandChecked(sal_uInt16 _nCommandId) const
1429 : {
1430 0 : FeatureState aState = GetState( _nCommandId );
1431 :
1432 0 : return aState.bChecked && *aState.bChecked;
1433 : }
1434 :
1435 3 : bool OGenericUnoController::isCommandEnabled( const OUString& _rCompleteCommandURL ) const
1436 : {
1437 : OSL_ENSURE( !_rCompleteCommandURL.isEmpty(), "OGenericUnoController::isCommandEnabled: Empty command url!" );
1438 :
1439 3 : bool bIsEnabled = false;
1440 3 : SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL );
1441 3 : if ( aIter != m_aSupportedFeatures.end() )
1442 3 : bIsEnabled = isCommandEnabled( aIter->second.nFeatureId );
1443 :
1444 3 : return bIsEnabled;
1445 : }
1446 :
1447 0 : Sequence< ::sal_Int16 > SAL_CALL OGenericUnoController::getSupportedCommandGroups() throw (RuntimeException, std::exception)
1448 : {
1449 0 : CommandHashMap aCmdHashMap;
1450 0 : for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
1451 0 : aIter != m_aSupportedFeatures.end();
1452 : ++aIter
1453 : )
1454 0 : if ( aIter->second.GroupId != CommandGroup::INTERNAL )
1455 0 : aCmdHashMap.insert( CommandHashMap::value_type( aIter->second.GroupId, 0 ));
1456 :
1457 0 : Sequence< sal_Int16 > aCommandGroups( aCmdHashMap.size() );
1458 : ::std::transform( aCmdHashMap.begin(),
1459 : aCmdHashMap.end(),
1460 : aCommandGroups.getArray(),
1461 : ::o3tl::select1st< CommandHashMap::value_type >()
1462 0 : );
1463 :
1464 0 : return aCommandGroups;
1465 : }
1466 :
1467 : namespace
1468 : {
1469 : //Current c++0x draft (apparently) has std::identity, but not operator()
1470 : template<typename T> struct SGI_identity : public std::unary_function<T,T>
1471 : {
1472 0 : T& operator()(T& x) const { return x; }
1473 : const T& operator()(const T& x) const { return x; }
1474 : };
1475 : }
1476 :
1477 0 : Sequence< DispatchInformation > SAL_CALL OGenericUnoController::getConfigurableDispatchInformation( ::sal_Int16 CommandGroup ) throw (RuntimeException, std::exception)
1478 : {
1479 0 : DispatchInfoList aInformationList;
1480 0 : DispatchInformation aDispatchInfo;
1481 0 : for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin();
1482 0 : aIter != m_aSupportedFeatures.end();
1483 : ++aIter
1484 : )
1485 : {
1486 0 : if ( sal_Int16( aIter->second.GroupId ) == CommandGroup )
1487 : {
1488 0 : aDispatchInfo = aIter->second;
1489 0 : aInformationList.push_back( aDispatchInfo );
1490 : }
1491 : }
1492 :
1493 0 : Sequence< DispatchInformation > aInformation( aInformationList.size() );
1494 : ::std::transform( aInformationList.begin(),
1495 : aInformationList.end(),
1496 : aInformation.getArray(),
1497 : SGI_identity< DispatchInformation >()
1498 0 : );
1499 :
1500 0 : return aInformation;
1501 : }
1502 :
1503 8 : void OGenericUnoController::fillSupportedFeatures()
1504 : {
1505 : #ifdef DBG_UTIL
1506 : m_bDescribingSupportedFeatures = true;
1507 : #endif
1508 8 : describeSupportedFeatures();
1509 : #ifdef DBG_UTIL
1510 : m_bDescribingSupportedFeatures = false;
1511 : #endif
1512 8 : }
1513 :
1514 12 : void SAL_CALL OGenericUnoController::dispose() throw(::com::sun::star::uno::RuntimeException, std::exception)
1515 : {
1516 12 : SolarMutexGuard aSolarGuard;
1517 12 : OGenericUnoController_Base::dispose();
1518 12 : }
1519 :
1520 36 : } // namespace dbaui
1521 :
1522 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|