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