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