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 <config_features.h>
21 :
22 : #include <tools/debug.hxx>
23 : #include <svl/eitem.hxx>
24 : #include <svl/stritem.hxx>
25 : #include <svl/intitem.hxx>
26 : #include <svl/itemset.hxx>
27 : #include <svl/visitem.hxx>
28 : #include <svtools/javacontext.hxx>
29 : #include <svl/itempool.hxx>
30 : #include <tools/urlobj.hxx>
31 : #include <com/sun/star/util/URLTransformer.hpp>
32 : #include <com/sun/star/util/XURLTransformer.hpp>
33 : #include <com/sun/star/frame/Desktop.hpp>
34 : #include <com/sun/star/frame/XController.hpp>
35 : #include <com/sun/star/frame/XFrameActionListener.hpp>
36 : #include <com/sun/star/frame/XComponentLoader.hpp>
37 : #include <com/sun/star/frame/XFrame.hpp>
38 : #include <com/sun/star/frame/FrameActionEvent.hpp>
39 : #include <com/sun/star/frame/FrameAction.hpp>
40 : #include <com/sun/star/frame/status/ItemStatus.hpp>
41 : #include <com/sun/star/frame/status/ItemState.hpp>
42 : #include <com/sun/star/frame/DispatchResultState.hpp>
43 : #include <com/sun/star/frame/ModuleManager.hpp>
44 : #include <com/sun/star/frame/status/Visibility.hpp>
45 : #include <comphelper/processfactory.hxx>
46 : #include <comphelper/sequence.hxx>
47 : #include <officecfg/Office/Common.hxx>
48 : #include <osl/mutex.hxx>
49 : #include <uno/current_context.hxx>
50 : #include <vcl/svapp.hxx>
51 :
52 : #include <sfx2/app.hxx>
53 : #include <sfx2/unoctitm.hxx>
54 : #include <sfx2/viewfrm.hxx>
55 : #include <sfx2/frame.hxx>
56 : #include <sfx2/ctrlitem.hxx>
57 : #include <sfx2/sfxuno.hxx>
58 : #include <sfx2/bindings.hxx>
59 : #include <sfx2/dispatch.hxx>
60 : #include <sfx2/sfxsids.hrc>
61 : #include <sfx2/request.hxx>
62 : #include "statcach.hxx"
63 : #include <sfx2/msgpool.hxx>
64 : #include <sfx2/objsh.hxx>
65 :
66 : #include <boost/scoped_ptr.hpp>
67 :
68 : #include <iostream>
69 :
70 : using namespace ::com::sun::star;
71 : using namespace ::com::sun::star::uno;
72 : using namespace ::com::sun::star::util;
73 :
74 : enum URLTypeId
75 : {
76 : URLType_BOOL,
77 : URLType_BYTE,
78 : URLType_SHORT,
79 : URLType_LONG,
80 : URLType_HYPER,
81 : URLType_STRING,
82 : URLType_FLOAT,
83 : URLType_DOUBLE,
84 : URLType_COUNT
85 : };
86 :
87 : const char* URLTypeNames[URLType_COUNT] =
88 : {
89 : "bool",
90 : "byte",
91 : "short",
92 : "long",
93 : "hyper",
94 : "string",
95 : "float",
96 : "double"
97 : };
98 :
99 0 : SfxUnoControllerItem::SfxUnoControllerItem( SfxControllerItem *pItem, SfxBindings& rBind, const OUString& rCmd )
100 : : pCtrlItem( pItem )
101 0 : , pBindings( &rBind )
102 : {
103 : DBG_ASSERT( !pCtrlItem || !pCtrlItem->IsBound(), "ControllerItem is incorrect!" );
104 :
105 0 : aCommand.Complete = rCmd;
106 0 : Reference< XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
107 0 : xTrans->parseStrict( aCommand );
108 0 : pBindings->RegisterUnoController_Impl( this );
109 0 : }
110 :
111 0 : SfxUnoControllerItem::~SfxUnoControllerItem()
112 : {
113 : // tell bindings to forget this controller ( if still connected )
114 0 : if ( pBindings )
115 0 : pBindings->ReleaseUnoController_Impl( this );
116 0 : }
117 :
118 0 : void SfxUnoControllerItem::UnBind()
119 : {
120 : // connection to SfxControllerItem is lost
121 0 : pCtrlItem = NULL;
122 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
123 0 : ReleaseDispatch();
124 0 : }
125 :
126 0 : void SAL_CALL SfxUnoControllerItem::statusChanged(const ::com::sun::star::frame::FeatureStateEvent& rEvent) throw ( ::com::sun::star::uno::RuntimeException, std::exception )
127 : {
128 0 : SolarMutexGuard aGuard;
129 : DBG_ASSERT( pCtrlItem, "dispatch implementation didn't respect our previous removeStatusListener call!" );
130 :
131 0 : if ( rEvent.Requery )
132 : {
133 : // Error can only happen if the old Dispatch is implemented incorrectly
134 : // i.e. removeStatusListener did not work. But such things can happen...
135 : // So protect before ReleaseDispatch from release!
136 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
137 0 : ReleaseDispatch();
138 0 : if ( pCtrlItem )
139 0 : GetNewDispatch(); // asynchronous ??
140 : }
141 0 : else if ( pCtrlItem )
142 : {
143 0 : SfxItemState eState = SfxItemState::DISABLED;
144 0 : SfxPoolItem* pItem = NULL;
145 0 : if ( rEvent.IsEnabled )
146 : {
147 0 : eState = SfxItemState::DEFAULT;
148 0 : ::com::sun::star::uno::Type pType = rEvent.State.getValueType();
149 :
150 0 : if ( pType == cppu::UnoType< bool >::get() )
151 : {
152 0 : bool bTemp = false;
153 0 : rEvent.State >>= bTemp ;
154 0 : pItem = new SfxBoolItem( pCtrlItem->GetId(), bTemp );
155 : }
156 0 : else if ( pType == cppu::UnoType< ::cppu::UnoUnsignedShortType >::get() )
157 : {
158 0 : sal_uInt16 nTemp = 0;
159 0 : rEvent.State >>= nTemp ;
160 0 : pItem = new SfxUInt16Item( pCtrlItem->GetId(), nTemp );
161 : }
162 0 : else if ( pType == cppu::UnoType<sal_uInt32>::get() )
163 : {
164 0 : sal_uInt32 nTemp = 0;
165 0 : rEvent.State >>= nTemp ;
166 0 : pItem = new SfxUInt32Item( pCtrlItem->GetId(), nTemp );
167 : }
168 0 : else if ( pType == cppu::UnoType<OUString>::get() )
169 : {
170 0 : OUString sTemp ;
171 0 : rEvent.State >>= sTemp ;
172 0 : pItem = new SfxStringItem( pCtrlItem->GetId(), sTemp );
173 : }
174 : else
175 0 : pItem = new SfxVoidItem( pCtrlItem->GetId() );
176 : }
177 :
178 0 : pCtrlItem->StateChanged( pCtrlItem->GetId(), eState, pItem );
179 0 : delete pItem;
180 0 : }
181 0 : }
182 :
183 0 : void SAL_CALL SfxUnoControllerItem::disposing( const ::com::sun::star::lang::EventObject& ) throw ( ::com::sun::star::uno::RuntimeException, std::exception )
184 : {
185 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
186 0 : ReleaseDispatch();
187 0 : }
188 :
189 0 : void SfxUnoControllerItem::ReleaseDispatch()
190 : {
191 0 : if ( xDispatch.is() )
192 : {
193 0 : xDispatch->removeStatusListener( (::com::sun::star::frame::XStatusListener*) this, aCommand );
194 0 : xDispatch = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
195 : }
196 0 : }
197 :
198 0 : void SfxUnoControllerItem::GetNewDispatch()
199 : {
200 0 : if ( !pBindings )
201 : {
202 : // Bindings released
203 : OSL_FAIL( "Tried to get dispatch, but no Bindings!" );
204 0 : return;
205 : }
206 :
207 : // forget old dispatch
208 0 : xDispatch = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
209 :
210 : // no arms, no cookies !
211 0 : if ( !pBindings->GetDispatcher_Impl() || !pBindings->GetDispatcher_Impl()->GetFrame() )
212 0 : return;
213 :
214 0 : SfxFrame& rFrame = pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame();
215 0 : SfxFrame *pParent = rFrame.GetParentFrame();
216 0 : if ( pParent )
217 : // parent may intercept
218 0 : xDispatch = TryGetDispatch( pParent );
219 :
220 0 : if ( !xDispatch.is() )
221 : {
222 : // no interception
223 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = rFrame.GetFrameInterface();
224 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, ::com::sun::star::uno::UNO_QUERY );
225 0 : if ( xProv.is() )
226 0 : xDispatch = xProv->queryDispatch( aCommand, OUString(), 0 );
227 : }
228 :
229 0 : if ( xDispatch.is() )
230 0 : xDispatch->addStatusListener( (::com::sun::star::frame::XStatusListener*) this, aCommand );
231 0 : else if ( pCtrlItem )
232 0 : pCtrlItem->StateChanged( pCtrlItem->GetId(), SfxItemState::DISABLED, NULL );
233 : }
234 :
235 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > SfxUnoControllerItem::TryGetDispatch( SfxFrame *pFrame )
236 : {
237 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
238 0 : SfxFrame *pParent = pFrame->GetParentFrame();
239 0 : if ( pParent )
240 : // parent may intercept
241 0 : xDisp = TryGetDispatch( pParent );
242 :
243 : // only components may intercept
244 0 : if ( !xDisp.is() && pFrame->HasComponent() )
245 : {
246 : // no interception
247 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = pFrame->GetFrameInterface();
248 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, ::com::sun::star::uno::UNO_QUERY );
249 0 : if ( xProv.is() )
250 0 : xDisp = xProv->queryDispatch( aCommand, OUString(), 0 );
251 : }
252 :
253 0 : return xDisp;
254 : }
255 :
256 0 : void SfxUnoControllerItem::ReleaseBindings()
257 : {
258 : // connection to binding is lost; so forget the binding and the dispatch
259 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
260 0 : ReleaseDispatch();
261 0 : if ( pBindings )
262 0 : pBindings->ReleaseUnoController_Impl( this );
263 0 : pBindings = NULL;
264 0 : }
265 :
266 168 : void SfxStatusDispatcher::ReleaseAll()
267 : {
268 168 : ::com::sun::star::lang::EventObject aObject;
269 168 : aObject.Source = (::cppu::OWeakObject*) this;
270 168 : aListeners.disposeAndClear( aObject );
271 168 : }
272 :
273 0 : void SAL_CALL SfxStatusDispatcher::dispatch( const ::com::sun::star::util::URL&, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& ) throw ( ::com::sun::star::uno::RuntimeException, std::exception )
274 : {
275 0 : }
276 :
277 0 : void SAL_CALL SfxStatusDispatcher::dispatchWithNotification(
278 : const ::com::sun::star::util::URL&,
279 : const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >&,
280 : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchResultListener >& ) throw( ::com::sun::star::uno::RuntimeException, std::exception )
281 : {
282 0 : }
283 :
284 130775 : SfxStatusDispatcher::SfxStatusDispatcher()
285 130775 : : aListeners( aMutex )
286 : {
287 130775 : }
288 :
289 0 : void SAL_CALL SfxStatusDispatcher::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException, std::exception )
290 : {
291 0 : aListeners.addInterface( aURL.Complete, aListener );
292 0 : if ( aURL.Complete.equalsAscii(".uno:LifeTime") )
293 : {
294 0 : ::com::sun::star::frame::FeatureStateEvent aEvent;
295 0 : aEvent.FeatureURL = aURL;
296 0 : aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
297 0 : aEvent.IsEnabled = sal_True;
298 0 : aEvent.Requery = sal_False;
299 0 : aListener->statusChanged( aEvent );
300 : }
301 0 : }
302 :
303 144987 : void SAL_CALL SfxStatusDispatcher::removeStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL ) throw ( ::com::sun::star::uno::RuntimeException, std::exception )
304 : {
305 144987 : aListeners.removeInterface( aURL.Complete, aListener );
306 144987 : }
307 :
308 :
309 : // XUnoTunnel
310 170954 : sal_Int64 SAL_CALL SfxOfficeDispatch::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException, std::exception)
311 : {
312 170954 : if ( aIdentifier == impl_getStaticIdentifier() )
313 170954 : return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ));
314 : else
315 0 : return 0;
316 : }
317 :
318 130227 : SfxOfficeDispatch::SfxOfficeDispatch( SfxBindings& rBindings, SfxDispatcher* pDispat, const SfxSlot* pSlot, const ::com::sun::star::util::URL& rURL )
319 : {
320 : // this object is an adapter that shows a ::com::sun::star::frame::XDispatch-Interface to the outside and uses a SfxControllerItem to monitor a state
321 130227 : pControllerItem = new SfxDispatchController_Impl( this, &rBindings, pDispat, pSlot, rURL );
322 130227 : }
323 :
324 245 : SfxOfficeDispatch::SfxOfficeDispatch( SfxDispatcher* pDispat, const SfxSlot* pSlot, const ::com::sun::star::util::URL& rURL )
325 : {
326 : // this object is an adapter that shows a ::com::sun::star::frame::XDispatch-Interface to the outside and uses a SfxControllerItem to monitor a state
327 245 : pControllerItem = new SfxDispatchController_Impl( this, NULL, pDispat, pSlot, rURL );
328 245 : }
329 :
330 391416 : SfxOfficeDispatch::~SfxOfficeDispatch()
331 : {
332 130472 : if ( pControllerItem )
333 : {
334 : // when dispatch object is released, destroy its connection to this object and destroy it
335 130472 : pControllerItem->UnBindController();
336 130472 : delete pControllerItem;
337 : }
338 260944 : }
339 :
340 341908 : const ::com::sun::star::uno::Sequence< sal_Int8 >& SfxOfficeDispatch::impl_getStaticIdentifier()
341 : {
342 : // {38 57 CA 80 09 36 11 d4 83 FE 00 50 04 52 6B 21}
343 : static const sal_uInt8 pGUID[16] = { 0x38, 0x57, 0xCA, 0x80, 0x09, 0x36, 0x11, 0xd4, 0x83, 0xFE, 0x00, 0x50, 0x04, 0x52, 0x6B, 0x21 };
344 341908 : static ::com::sun::star::uno::Sequence< sal_Int8 > seqID((const sal_Int8*)pGUID,16) ;
345 341908 : return seqID ;
346 : }
347 :
348 :
349 288 : void SAL_CALL SfxOfficeDispatch::dispatch( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs ) throw ( ::com::sun::star::uno::RuntimeException, std::exception )
350 : {
351 : // ControllerItem is the Impl class
352 288 : if ( pControllerItem )
353 : {
354 : #if HAVE_FEATURE_JAVA
355 : // The JavaContext contains an interaction handler which is used when
356 : // the creation of a Java Virtual Machine fails. The second parameter
357 : // indicates, that there shall only be one user notification (message box)
358 : // even if the same error (interaction) reoccurs. The effect is, that if a
359 : // user selects a menu entry than they may get only one notification that
360 : // a JRE is not selected.
361 : com::sun::star::uno::ContextLayer layer(
362 : new svt::JavaContext( com::sun::star::uno::getCurrentContext(),
363 288 : true) );
364 : #endif
365 288 : pControllerItem->dispatch( aURL, aArgs, ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchResultListener >() );
366 : }
367 288 : }
368 :
369 10 : void SAL_CALL SfxOfficeDispatch::dispatchWithNotification( const ::com::sun::star::util::URL& aURL,
370 : const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs,
371 : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchResultListener >& rListener ) throw( ::com::sun::star::uno::RuntimeException, std::exception )
372 : {
373 : // ControllerItem is the Impl class
374 10 : if ( pControllerItem )
375 : {
376 : #if HAVE_FEATURE_JAVA
377 : // see comment for SfxOfficeDispatch::dispatch
378 : com::sun::star::uno::ContextLayer layer(
379 : new svt::JavaContext( com::sun::star::uno::getCurrentContext(),
380 10 : true) );
381 : #endif
382 10 : pControllerItem->dispatch( aURL, aArgs, rListener );
383 : }
384 10 : }
385 :
386 140869 : void SAL_CALL SfxOfficeDispatch::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException, std::exception )
387 : {
388 140869 : GetListeners().addInterface( aURL.Complete, aListener );
389 140869 : if ( pControllerItem )
390 : {
391 : // ControllerItem is the Impl class
392 140869 : pControllerItem->addStatusListener( aListener, aURL );
393 : }
394 140869 : }
395 :
396 170105 : SfxDispatcher* SfxOfficeDispatch::GetDispatcher_Impl()
397 : {
398 170105 : return pControllerItem->GetDispatcher();
399 : }
400 :
401 131 : void SfxOfficeDispatch::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
402 : {
403 131 : if ( pControllerItem )
404 131 : pControllerItem->SetFrame( xFrame );
405 131 : }
406 :
407 130472 : void SfxOfficeDispatch::SetMasterUnoCommand( bool bSet )
408 : {
409 130472 : if ( pControllerItem )
410 130472 : pControllerItem->setMasterSlaveCommand( bSet );
411 130472 : }
412 :
413 : // Determine if URL contains a master/slave command which must be handled a little bit different
414 322105 : bool SfxOfficeDispatch::IsMasterUnoCommand( const ::com::sun::star::util::URL& aURL )
415 : {
416 322105 : return aURL.Protocol == ".uno:" && ( aURL.Path.indexOf( '.' ) > 0 );
417 : }
418 :
419 317486 : OUString SfxOfficeDispatch::GetMasterUnoCommand( const ::com::sun::star::util::URL& aURL )
420 : {
421 317486 : OUString aMasterCommand;
422 317486 : if ( IsMasterUnoCommand( aURL ))
423 : {
424 114 : sal_Int32 nIndex = aURL.Path.indexOf( '.' );
425 114 : if ( nIndex > 0 )
426 114 : aMasterCommand = aURL.Path.copy( 0, nIndex );
427 : }
428 :
429 317486 : return aMasterCommand;
430 : }
431 :
432 130472 : SfxDispatchController_Impl::SfxDispatchController_Impl(
433 : SfxOfficeDispatch* pDisp,
434 : SfxBindings* pBind,
435 : SfxDispatcher* pDispat,
436 : const SfxSlot* pSlot,
437 : const ::com::sun::star::util::URL& rURL )
438 : : aDispatchURL( rURL )
439 : , pDispatcher( pDispat )
440 : , pBindings( pBind )
441 : , pLastState( 0 )
442 130472 : , nSlot( pSlot->GetSlotId() )
443 : , pDispatch( pDisp )
444 : , bMasterSlave( false )
445 : , bVisible( true )
446 260944 : , pUnoName( pSlot->pUnoName )
447 : {
448 130472 : if ( aDispatchURL.Protocol == "slot:" && pUnoName )
449 : {
450 0 : OStringBuffer aTmp(".uno:");
451 0 : aTmp.append(pUnoName);
452 0 : aDispatchURL.Complete = OStringToOUString(aTmp.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
453 0 : Reference< XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
454 0 : xTrans->parseStrict( aDispatchURL );
455 : }
456 :
457 130472 : SetId( nSlot );
458 130472 : if ( pBindings )
459 : {
460 : // Bind immediately to enable the cache to recycle dispatches when asked for the same command
461 : // a command in "slot" or in ".uno" notation must be treated as identical commands!
462 130227 : pBindings->ENTERREGISTRATIONS();
463 130227 : BindInternal_Impl( nSlot, pBindings );
464 130227 : pBindings->LEAVEREGISTRATIONS();
465 : }
466 130472 : }
467 :
468 391416 : SfxDispatchController_Impl::~SfxDispatchController_Impl()
469 : {
470 130472 : if ( pLastState && !IsInvalidItem( pLastState ) )
471 25464 : delete pLastState;
472 :
473 130472 : if ( pDispatch )
474 : {
475 : // disconnect
476 0 : pDispatch->pControllerItem = NULL;
477 :
478 : // force all listeners to release the dispatch object
479 0 : ::com::sun::star::lang::EventObject aObject;
480 0 : aObject.Source = (::cppu::OWeakObject*) pDispatch;
481 0 : pDispatch->GetListeners().disposeAndClear( aObject );
482 : }
483 260944 : }
484 :
485 131 : void SfxDispatchController_Impl::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _xFrame)
486 : {
487 131 : xFrame = _xFrame;
488 131 : }
489 :
490 130472 : void SfxDispatchController_Impl::setMasterSlaveCommand( bool bSet )
491 : {
492 130472 : bMasterSlave = bSet;
493 130472 : }
494 :
495 130472 : void SfxDispatchController_Impl::UnBindController()
496 : {
497 130472 : pDispatch = NULL;
498 130472 : if ( IsBound() )
499 : {
500 0 : GetBindings().ENTERREGISTRATIONS();
501 0 : SfxControllerItem::UnBind();
502 0 : GetBindings().LEAVEREGISTRATIONS();
503 : }
504 130472 : }
505 :
506 0 : void SfxDispatchController_Impl::addParametersToArgs( const com::sun::star::util::URL& aURL, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ) const
507 : {
508 : // Extract the parameter from the URL and put them into the property value sequence
509 0 : sal_Int32 nQueryIndex = aURL.Complete.indexOf( '?' );
510 0 : if ( nQueryIndex > 0 )
511 : {
512 0 : OUString aParamString( aURL.Complete.copy( nQueryIndex+1 ));
513 0 : sal_Int32 nIndex = 0;
514 0 : do
515 : {
516 0 : OUString aToken = aParamString.getToken( 0, '&', nIndex );
517 :
518 0 : sal_Int32 nParmIndex = 0;
519 0 : OUString aParamType;
520 0 : OUString aParamName = aToken.getToken( 0, '=', nParmIndex );
521 0 : OUString aValue = (nParmIndex!=-1) ? aToken.getToken( 0, '=', nParmIndex ) : OUString();
522 :
523 0 : if ( !aParamName.isEmpty() )
524 : {
525 0 : nParmIndex = 0;
526 0 : aToken = aParamName;
527 0 : aParamName = aToken.getToken( 0, ':', nParmIndex );
528 0 : aParamType = (nParmIndex!=-1) ? aToken.getToken( 0, ':', nParmIndex ) : OUString();
529 : }
530 :
531 0 : sal_Int32 nLen = rArgs.getLength();
532 0 : rArgs.realloc( nLen+1 );
533 0 : rArgs[nLen].Name = aParamName;
534 :
535 0 : if ( aParamType.isEmpty() )
536 : {
537 : // Default: LONG
538 0 : rArgs[nLen].Value <<= aValue.toInt32();
539 : }
540 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_BOOL], 4 ))
541 : {
542 : // sal_Bool support
543 0 : rArgs[nLen].Value <<= aValue.toBoolean();
544 : }
545 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_BYTE], 4 ))
546 : {
547 : // sal_uInt8 support
548 0 : rArgs[nLen].Value <<= sal_Int8( aValue.toInt32() );
549 : }
550 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_LONG], 4 ))
551 : {
552 : // LONG support
553 0 : rArgs[nLen].Value <<= aValue.toInt32();
554 : }
555 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_SHORT], 5 ))
556 : {
557 : // SHORT support
558 0 : rArgs[nLen].Value <<= sal_Int8( aValue.toInt32() );
559 : }
560 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_HYPER], 5 ))
561 : {
562 : // HYPER support
563 0 : rArgs[nLen].Value <<= aValue.toInt64();
564 : }
565 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_FLOAT], 5 ))
566 : {
567 : // FLOAT support
568 0 : rArgs[nLen].Value <<= aValue.toFloat();
569 : }
570 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_STRING], 6 ))
571 : {
572 : // STRING support
573 0 : rArgs[nLen].Value <<= OUString( INetURLObject::decode( aValue, '%', INetURLObject::DECODE_WITH_CHARSET ));
574 : }
575 0 : else if ( aParamType.equalsAsciiL( URLTypeNames[URLType_DOUBLE], 6))
576 : {
577 : // DOUBLE support
578 0 : rArgs[nLen].Value <<= aValue.toDouble();
579 0 : }
580 : }
581 0 : while ( nIndex >= 0 );
582 : }
583 0 : }
584 :
585 12717 : SfxMapUnit SfxDispatchController_Impl::GetCoreMetric( SfxItemPool& rPool, sal_uInt16 nSlotId )
586 : {
587 12717 : sal_uInt16 nWhich = rPool.GetWhich( nSlotId );
588 12717 : return rPool.GetMetric( nWhich );
589 : }
590 :
591 0 : OUString SfxDispatchController_Impl::getSlaveCommand( const ::com::sun::star::util::URL& rURL )
592 : {
593 0 : OUString aSlaveCommand;
594 0 : sal_Int32 nIndex = rURL.Path.indexOf( '.' );
595 0 : if (( nIndex > 0 ) && ( nIndex < rURL.Path.getLength() ))
596 0 : aSlaveCommand = rURL.Path.copy( nIndex+1 );
597 0 : return aSlaveCommand;
598 : }
599 :
600 : namespace {
601 :
602 : /// Class that collects the usage information - how many times what .uno: command was used.
603 : class UsageInfo {
604 :
605 : typedef std::map<OUString, int> UsageMap;
606 :
607 : /// Command vs. how many times it was used
608 : UsageMap maUsage;
609 :
610 : public:
611 0 : UsageInfo()
612 0 : {
613 0 : load();
614 0 : }
615 :
616 0 : ~UsageInfo()
617 0 : {
618 0 : save();
619 0 : }
620 :
621 : /// Increment command's use.
622 : void increment(const OUString &rCommand);
623 :
624 : /// Load the usage data from the previous session.
625 : void load();
626 :
627 : /// Save the usage data for the next session.
628 : void save();
629 : };
630 :
631 0 : void UsageInfo::increment(const OUString &rCommand)
632 : {
633 0 : UsageMap::iterator it = maUsage.find(rCommand);
634 :
635 0 : if (it != maUsage.end())
636 0 : ++(it->second);
637 : else
638 0 : maUsage[rCommand] = 1;
639 0 : }
640 :
641 0 : void UsageInfo::load()
642 : {
643 : // TODO - do the real loading here
644 0 : }
645 :
646 0 : void UsageInfo::save()
647 : {
648 0 : if (!officecfg::Office::Common::Misc::CollectUsageInformation::get())
649 0 : return;
650 :
651 : // TODO - do a real saving here, not only dump to the screen
652 0 : std::cerr << "Usage information:" << std::endl;
653 0 : for (UsageMap::const_iterator it = maUsage.begin(); it != maUsage.end(); ++it)
654 : {
655 0 : std::cerr << it->first << ';' << it->second << std::endl;
656 : }
657 0 : std::cerr << "Usage information end" << std::endl;
658 : }
659 :
660 : class theUsageInfo : public rtl::Static<UsageInfo, theUsageInfo> {};
661 :
662 : /// Extracts information about the command + args, and stores that.
663 298 : void collectUsageInformation(const util::URL& rURL, const uno::Sequence<beans::PropertyValue>& rArgs)
664 : {
665 298 : if (!officecfg::Office::Common::Misc::CollectUsageInformation::get())
666 596 : return;
667 :
668 0 : OUStringBuffer aBuffer;
669 :
670 : // app identification [uh, several UNO calls :-(]
671 0 : uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
672 0 : uno::Reference<frame::XModuleManager2> xModuleManager(frame::ModuleManager::create(xContext));
673 0 : uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(xContext);
674 0 : uno::Reference<frame::XFrame> xFrame = xDesktop->getCurrentFrame();
675 :
676 0 : OUString aModule(xModuleManager->identify(xFrame));
677 0 : sal_Int32 nLastDot = aModule.lastIndexOf('.');
678 0 : if (nLastDot >= 0)
679 0 : aModule = aModule.copy(nLastDot + 1);
680 :
681 0 : aBuffer.append(aModule);
682 0 : aBuffer.append(';');
683 :
684 : // command
685 0 : aBuffer.append(rURL.Protocol);
686 0 : aBuffer.append(rURL.Path);
687 0 : sal_Int32 nCount = rArgs.getLength();
688 :
689 : // parameters - only their names, not the values (could be sensitive!)
690 0 : if (nCount > 0)
691 : {
692 0 : aBuffer.append('(');
693 0 : for (sal_Int32 n = 0; n < nCount; n++)
694 : {
695 0 : const ::com::sun::star::beans::PropertyValue& rProp = rArgs[n];
696 0 : if (n > 0)
697 0 : aBuffer.append(',');
698 0 : aBuffer.append(rProp.Name);
699 : }
700 0 : aBuffer.append(')');
701 : }
702 :
703 0 : OUString aCommand(aBuffer.makeStringAndClear());
704 :
705 : // store
706 0 : theUsageInfo::get().increment(aCommand);
707 : }
708 :
709 : }
710 :
711 298 : void SAL_CALL SfxDispatchController_Impl::dispatch( const ::com::sun::star::util::URL& aURL,
712 : const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs,
713 : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchResultListener >& rListener )
714 : throw (css::uno::RuntimeException, std::exception)
715 : {
716 298 : collectUsageInformation(aURL, aArgs);
717 :
718 298 : SolarMutexGuard aGuard;
719 298 : if (
720 894 : pDispatch &&
721 : (
722 596 : (aURL.Protocol == ".uno:" && aURL.Path == aDispatchURL.Path) ||
723 0 : (aURL.Protocol == "slot:" && aURL.Path.toInt32() == GetId())
724 : )
725 : )
726 : {
727 298 : if ( !pDispatcher && pBindings )
728 0 : pDispatcher = GetBindings().GetDispatcher_Impl();
729 :
730 298 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lNewArgs;
731 298 : sal_Int32 nCount = aArgs.getLength();
732 :
733 : // Support for URL based arguments
734 596 : INetURLObject aURLObj( aURL.Complete );
735 298 : if ( aURLObj.HasParam() )
736 0 : addParametersToArgs( aURL, lNewArgs );
737 :
738 : // Try to find call mode and frame name inside given arguments...
739 298 : SfxCallMode nCall = SfxCallMode::RECORD;
740 298 : sal_Int32 nMarkArg = -1;
741 :
742 : // Filter arguments which shouldn't be part of the sequence property value
743 298 : sal_uInt16 nModifier(0);
744 596 : std::vector< ::com::sun::star::beans::PropertyValue > aAddArgs;
745 558 : for( sal_Int32 n=0; n<nCount; n++ )
746 : {
747 260 : const ::com::sun::star::beans::PropertyValue& rProp = aArgs[n];
748 260 : if( rProp.Name == "SynchronMode" )
749 : {
750 : bool bTemp;
751 10 : if( rProp.Value >>= bTemp )
752 10 : nCall = bTemp ? SfxCallMode::SYNCHRON : SfxCallMode::ASYNCHRON;
753 : }
754 250 : else if( rProp.Name == "Bookmark" )
755 : {
756 0 : nMarkArg = n;
757 0 : aAddArgs.push_back( aArgs[n] );
758 : }
759 250 : else if( rProp.Name == "KeyModifier" )
760 4 : rProp.Value >>= nModifier;
761 : else
762 246 : aAddArgs.push_back( aArgs[n] );
763 : }
764 :
765 : // Add needed arguments to sequence property value
766 298 : sal_uInt32 nAddArgs = aAddArgs.size();
767 298 : if ( nAddArgs > 0 )
768 : {
769 246 : sal_uInt32 nIndex( lNewArgs.getLength() );
770 :
771 246 : lNewArgs.realloc( lNewArgs.getLength()+aAddArgs.size() );
772 492 : for ( sal_uInt32 i = 0; i < nAddArgs; i++ )
773 246 : lNewArgs[nIndex++] = aAddArgs[i];
774 : }
775 :
776 : // Overwrite possible detected sychron argument, if real listener exists (currently no other way)
777 298 : if ( rListener.is() )
778 10 : nCall = SfxCallMode::SYNCHRON;
779 :
780 298 : if( GetId() == SID_JUMPTOMARK && nMarkArg == - 1 )
781 : {
782 : // we offer dispatches for SID_JUMPTOMARK if the URL points to a bookmark inside the document
783 : // so we must retrieve this as an argument from the parsed URL
784 0 : lNewArgs.realloc( lNewArgs.getLength()+1 );
785 0 : nMarkArg = lNewArgs.getLength()-1;
786 0 : lNewArgs[nMarkArg].Name = "Bookmark";
787 0 : lNewArgs[nMarkArg].Value <<= aURL.Mark;
788 : }
789 :
790 596 : css::uno::Reference< css::frame::XFrame > xFrameRef(xFrame.get(), css::uno::UNO_QUERY);
791 298 : if (! xFrameRef.is() && pDispatcher)
792 : {
793 298 : SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
794 298 : if (pViewFrame)
795 298 : xFrameRef = pViewFrame->GetFrame().GetFrameInterface();
796 : }
797 :
798 298 : bool bSuccess = false;
799 298 : const SfxPoolItem* pItem = NULL;
800 298 : SfxMapUnit eMapUnit( SFX_MAPUNIT_100TH_MM );
801 :
802 : // Extra scope so that aInternalSet is destroyed before
803 : // rListener->dispatchFinished potentially calls
804 : // framework::Desktop::terminate -> SfxApplication::Deinitialize ->
805 : // ~CntItemPool:
806 298 : if (pDispatcher)
807 : {
808 298 : SfxAllItemSet aInternalSet( SfxGetpApp()->GetPool() );
809 298 : if (xFrameRef.is()) // an empty set is no problem ... but an empty frame reference can be a problem !
810 298 : aInternalSet.Put( SfxUnoFrameItem( SID_FILLFRAME, xFrameRef ) );
811 :
812 298 : SfxShell* pShell( 0 );
813 : // #i102619# Retrieve metric from shell before execution - the shell could be destroyed after execution
814 298 : if ( pDispatcher->GetBindings() )
815 : {
816 298 : if ( !pDispatcher->IsLocked( GetId() ) )
817 : {
818 298 : const SfxSlot *pSlot = 0;
819 596 : if ( pDispatcher->GetShellAndSlot_Impl( GetId(), &pShell, &pSlot, false,
820 596 : SfxCallMode::MODAL==(nCall&SfxCallMode::MODAL), false ) )
821 : {
822 298 : if ( bMasterSlave )
823 : {
824 : // Extract slave command and add argument to the args list. Master slot MUST
825 : // have a argument that has the same name as the master slot and type is SfxStringItem.
826 0 : sal_Int32 nIndex = lNewArgs.getLength();
827 0 : lNewArgs.realloc( nIndex+1 );
828 0 : lNewArgs[nIndex].Name = OUString::createFromAscii( pSlot->pUnoName );
829 0 : lNewArgs[nIndex].Value = makeAny( SfxDispatchController_Impl::getSlaveCommand( aDispatchURL ));
830 : }
831 :
832 298 : eMapUnit = GetCoreMetric( pShell->GetPool(), GetId() );
833 298 : boost::scoped_ptr<SfxAllItemSet> xSet(new SfxAllItemSet(pShell->GetPool()));
834 298 : TransformParameters(GetId(), lNewArgs, *xSet, pSlot);
835 298 : if (xSet->Count())
836 : {
837 : // execute with arguments - call directly
838 246 : pItem = pDispatcher->Execute(GetId(), nCall, xSet.get(), &aInternalSet, nModifier);
839 246 : bSuccess = (pItem != NULL);
840 : }
841 : else
842 : {
843 : // Be sure to delete this before we send a dispatch
844 : // request, which will destroy the current shell.
845 52 : xSet.reset();
846 :
847 : // execute using bindings, enables support for toggle/enum etc.
848 52 : SfxRequest aReq( GetId(), nCall, pShell->GetPool() );
849 52 : aReq.SetModifier( nModifier );
850 52 : aReq.SetInternalArgs_Impl(aInternalSet);
851 52 : pDispatcher->GetBindings()->Execute_Impl( aReq, pSlot, pShell );
852 52 : pItem = aReq.GetReturnValue();
853 52 : bSuccess = aReq.IsDone() || pItem != NULL;
854 298 : }
855 : }
856 : #ifdef DBG_UTIL
857 : else
858 : DBG_WARNING("MacroPlayer: Unknown slot dispatched!");
859 : #endif
860 : }
861 : }
862 : else
863 : {
864 0 : eMapUnit = GetCoreMetric( SfxGetpApp()->GetPool(), GetId() );
865 : // AppDispatcher
866 0 : SfxAllItemSet aSet( SfxGetpApp()->GetPool() );
867 0 : TransformParameters( GetId(), lNewArgs, aSet );
868 :
869 0 : if ( aSet.Count() )
870 0 : pItem = pDispatcher->Execute( GetId(), nCall, &aSet, &aInternalSet, nModifier );
871 : else
872 : // SfxRequests take empty sets as argument sets, GetArgs() returning non-zero!
873 0 : pItem = pDispatcher->Execute( GetId(), nCall, 0, &aInternalSet, nModifier );
874 :
875 : // no bindings, no invalidate ( usually done in SfxDispatcher::Call_Impl()! )
876 0 : if ( SfxApplication::Get() )
877 : {
878 0 : SfxDispatcher* pAppDispat = SfxGetpApp()->GetAppDispatcher_Impl();
879 0 : if ( pAppDispat )
880 : {
881 0 : const SfxPoolItem* pState=0;
882 0 : SfxItemState eState = pDispatcher->QueryState( GetId(), pState );
883 0 : StateChanged( GetId(), eState, pState );
884 : }
885 : }
886 :
887 0 : bSuccess = (pItem != NULL);
888 298 : }
889 : }
890 :
891 298 : if ( rListener.is() )
892 : {
893 10 : ::com::sun::star::frame::DispatchResultEvent aEvent;
894 10 : if ( bSuccess )
895 2 : aEvent.State = com::sun::star::frame::DispatchResultState::SUCCESS;
896 : else
897 8 : aEvent.State = com::sun::star::frame::DispatchResultState::FAILURE;
898 :
899 10 : aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
900 10 : if ( bSuccess && pItem && !pItem->ISA(SfxVoidItem) )
901 : {
902 2 : sal_uInt16 nSubId( 0 );
903 2 : if ( eMapUnit == SFX_MAPUNIT_TWIP )
904 0 : nSubId |= CONVERT_TWIPS;
905 2 : pItem->QueryValue( aEvent.Result, (sal_uInt8)nSubId );
906 : }
907 :
908 10 : rListener->dispatchFinished( aEvent );
909 298 : }
910 298 : }
911 298 : }
912 :
913 170105 : SfxDispatcher* SfxDispatchController_Impl::GetDispatcher()
914 : {
915 170105 : if ( !pDispatcher && pBindings )
916 0 : pDispatcher = GetBindings().GetDispatcher_Impl();
917 170105 : return pDispatcher;
918 : }
919 :
920 140869 : void SAL_CALL SfxDispatchController_Impl::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException )
921 : {
922 140869 : SolarMutexGuard aGuard;
923 140869 : if ( !pDispatch )
924 140869 : return;
925 :
926 : // Use alternative QueryState call to have a valid UNO representation of the state.
927 281738 : ::com::sun::star::uno::Any aState;
928 140869 : if ( !pDispatcher && pBindings )
929 0 : pDispatcher = GetBindings().GetDispatcher_Impl();
930 140869 : SfxItemState eState = pDispatcher ? pDispatcher->QueryState( GetId(), aState ) : SfxItemState::DONTCARE;
931 :
932 140869 : if ( eState == SfxItemState::DONTCARE )
933 : {
934 : // Use special uno struct to transport don't care state
935 0 : ::com::sun::star::frame::status::ItemStatus aItemStatus;
936 0 : aItemStatus.State = ::com::sun::star::frame::status::ItemState::DONT_CARE;
937 0 : aState = makeAny( aItemStatus );
938 : }
939 :
940 281738 : ::com::sun::star::frame::FeatureStateEvent aEvent;
941 140869 : aEvent.FeatureURL = aURL;
942 140869 : aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
943 140869 : aEvent.Requery = sal_False;
944 140869 : if ( bVisible )
945 : {
946 140869 : aEvent.IsEnabled = eState != SfxItemState::DISABLED;
947 140869 : aEvent.State = aState;
948 : }
949 : else
950 : {
951 0 : ::com::sun::star::frame::status::Visibility aVisibilityStatus;
952 0 : aVisibilityStatus.bVisible = sal_False;
953 :
954 : // MBA: we might decide to *not* disable "invisible" slots, but this would be
955 : // a change that needs to adjust at least the testtool
956 0 : aEvent.IsEnabled = sal_False;
957 0 : aEvent.State = makeAny( aVisibilityStatus );
958 : }
959 :
960 281738 : aListener->statusChanged( aEvent );
961 : }
962 :
963 29453 : void SfxDispatchController_Impl::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState, SfxSlotServer* pSlotServ )
964 : {
965 29453 : if ( !pDispatch )
966 29453 : return;
967 :
968 : // Bindings instance notifies controller about a state change, listeners must be notified also
969 : // Don't cache visibility state changes as they are volatile. We need our real state to send it
970 : // to our controllers after visibility is set to true.
971 29453 : bool bNotify = true;
972 29453 : if ( pState && !IsInvalidItem( pState ) )
973 : {
974 25820 : if ( !pState->ISA( SfxVisibilityItem ) )
975 : {
976 25820 : bool bBothAvailable = pLastState && !IsInvalidItem(pLastState);
977 25820 : if ( bBothAvailable )
978 338 : bNotify = pState->Type() != pLastState->Type() || *pState != *pLastState;
979 25820 : if ( pLastState && !IsInvalidItem( pLastState ) )
980 338 : delete pLastState;
981 25820 : pLastState = !IsInvalidItem(pState) ? pState->Clone() : pState;
982 25820 : bVisible = true;
983 : }
984 : else
985 0 : bVisible = static_cast<const SfxVisibilityItem *>(pState)->GetValue();
986 : }
987 : else
988 : {
989 3633 : if ( pLastState && !IsInvalidItem( pLastState ) )
990 18 : delete pLastState;
991 3633 : pLastState = pState;
992 : }
993 :
994 29453 : ::cppu::OInterfaceContainerHelper* pContnr = pDispatch->GetListeners().getContainer ( aDispatchURL.Complete );
995 29453 : if ( bNotify && pContnr )
996 : {
997 21760 : ::com::sun::star::uno::Any aState;
998 21760 : if ( ( eState >= SfxItemState::DEFAULT ) && pState && !IsInvalidItem( pState ) && !pState->ISA(SfxVoidItem) )
999 : {
1000 : // Retrieve metric from pool to have correct sub ID when calling QueryValue
1001 12419 : sal_uInt16 nSubId( 0 );
1002 12419 : SfxMapUnit eMapUnit( SFX_MAPUNIT_100TH_MM );
1003 :
1004 : // retrieve the core metric
1005 : // it's enough to check the objectshell, the only shell that does not use the pool of the document
1006 : // is SfxViewFrame, but it hasn't any metric parameters
1007 : // TODO/LATER: what about the FormShell? Does it use any metric data?! Perhaps it should use the Pool of the document!
1008 12419 : if ( pSlotServ && pDispatcher )
1009 : {
1010 12419 : SfxShell* pShell = pDispatcher->GetShell( pSlotServ->GetShellLevel() );
1011 : DBG_ASSERT( pShell, "Can't get core metric without shell!" );
1012 12419 : if ( pShell )
1013 12419 : eMapUnit = GetCoreMetric( pShell->GetPool(), nSID );
1014 : }
1015 :
1016 12419 : if ( eMapUnit == SFX_MAPUNIT_TWIP )
1017 11470 : nSubId |= CONVERT_TWIPS;
1018 :
1019 12419 : pState->QueryValue( aState, (sal_uInt8)nSubId );
1020 : }
1021 9341 : else if ( eState == SfxItemState::DONTCARE )
1022 : {
1023 : // Use special uno struct to transport don't care state
1024 10 : ::com::sun::star::frame::status::ItemStatus aItemStatus;
1025 10 : aItemStatus.State = ::com::sun::star::frame::status::ItemState::DONT_CARE;
1026 10 : aState = makeAny( aItemStatus );
1027 : }
1028 :
1029 43520 : ::com::sun::star::frame::FeatureStateEvent aEvent;
1030 21760 : aEvent.FeatureURL = aDispatchURL;
1031 21760 : aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
1032 21760 : aEvent.IsEnabled = eState != SfxItemState::DISABLED;
1033 21760 : aEvent.Requery = sal_False;
1034 21760 : aEvent.State = aState;
1035 :
1036 43520 : ::cppu::OInterfaceIteratorHelper aIt( *pContnr );
1037 70817 : while( aIt.hasMoreElements() )
1038 : {
1039 : try
1040 : {
1041 27297 : static_cast< ::com::sun::star::frame::XStatusListener *>(aIt.next())->statusChanged( aEvent );
1042 : }
1043 0 : catch (const ::com::sun::star::uno::RuntimeException&)
1044 : {
1045 0 : aIt.remove();
1046 : }
1047 21760 : }
1048 : }
1049 : }
1050 :
1051 0 : void SfxDispatchController_Impl::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
1052 : {
1053 0 : StateChanged( nSID, eState, pState, 0 );
1054 951 : }
1055 :
1056 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|