1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dispuno.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 #include <sfx2/viewfrm.hxx>
37 #include <comphelper/uno3.hxx>
38 #include <svx/dataaccessdescriptor.hxx>
39 #include <svtools/smplhint.hxx>
41 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
42 #include <com/sun/star/view/XSelectionSupplier.hpp>
43 #include <com/sun/star/sdb/CommandType.hpp>
45 #include "dispuno.hxx"
46 #include "unoguard.hxx"
47 #include "tabvwsh.hxx"
48 #include "dbdocfun.hxx"
49 #include "dbcolect.hxx"
51 using namespace com::sun::star
;
53 //------------------------------------------------------------------------
55 const char* cURLInsertColumns
= ".uno:DataSourceBrowser/InsertColumns"; //data into text
56 const char* cURLDocDataSource
= ".uno:DataSourceBrowser/DocumentDataSource";
58 //------------------------------------------------------------------------
60 SV_IMPL_PTRARR( XStatusListenerArr_Impl
, XStatusListenerPtr
);
62 //------------------------------------------------------------------------
64 uno::Reference
<view::XSelectionSupplier
> lcl_GetSelectionSupplier( SfxViewShell
* pViewShell
)
68 SfxViewFrame
* pViewFrame
= pViewShell
->GetViewFrame();
71 SfxFrame
* pFrame
= pViewFrame
->GetFrame();
73 return uno::Reference
<view::XSelectionSupplier
>( pFrame
->GetController(), uno::UNO_QUERY
);
76 return uno::Reference
<view::XSelectionSupplier
>();
79 //------------------------------------------------------------------------
82 ScDispatchProviderInterceptor::ScDispatchProviderInterceptor(ScTabViewShell
* pViewSh
) :
87 SfxFrame
* pFrame
= pViewShell
->GetViewFrame()->GetFrame();
88 m_xIntercepted
.set(uno::Reference
<frame::XDispatchProviderInterception
>(pFrame
->GetFrameInterface(), uno::UNO_QUERY
));
89 if (m_xIntercepted
.is())
91 comphelper::increment( m_refCount
);
93 m_xIntercepted
->registerDispatchProviderInterceptor(
94 static_cast<frame::XDispatchProviderInterceptor
*>(this));
95 // this should make us the top-level dispatch-provider for the component, via a call to our
96 // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill
97 uno::Reference
<lang::XComponent
> xInterceptedComponent(m_xIntercepted
, uno::UNO_QUERY
);
98 if (xInterceptedComponent
.is())
99 xInterceptedComponent
->addEventListener(static_cast<lang::XEventListener
*>(this));
101 comphelper::decrement( m_refCount
);
104 StartListening(*pViewShell
);
108 ScDispatchProviderInterceptor::~ScDispatchProviderInterceptor()
111 EndListening(*pViewShell
);
114 void ScDispatchProviderInterceptor::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
116 if ( rHint
.ISA( SfxSimpleHint
) &&
117 ((const SfxSimpleHint
&)rHint
).GetId() == SFX_HINT_DYING
)
123 uno::Reference
<frame::XDispatch
> SAL_CALL
ScDispatchProviderInterceptor::queryDispatch(
124 const util::URL
& aURL
, const rtl::OUString
& aTargetFrameName
,
125 sal_Int32 nSearchFlags
)
126 throw(uno::RuntimeException
)
130 uno::Reference
<frame::XDispatch
> xResult
;
131 // create some dispatch ...
133 !aURL
.Complete
.compareToAscii(cURLInsertColumns
) ||
134 !aURL
.Complete
.compareToAscii(cURLDocDataSource
) ) )
136 if (!m_xMyDispatch
.is())
137 m_xMyDispatch
= new ScDispatch( pViewShell
);
138 xResult
= m_xMyDispatch
;
141 // ask our slave provider
142 if (!xResult
.is() && m_xSlaveDispatcher
.is())
143 xResult
= m_xSlaveDispatcher
->queryDispatch(aURL
, aTargetFrameName
, nSearchFlags
);
148 uno::Sequence
< uno::Reference
<frame::XDispatch
> > SAL_CALL
149 ScDispatchProviderInterceptor::queryDispatches(
150 const uno::Sequence
<frame::DispatchDescriptor
>& aDescripts
)
151 throw(uno::RuntimeException
)
155 uno::Sequence
< uno::Reference
< frame::XDispatch
> > aReturn(aDescripts
.getLength());
156 uno::Reference
< frame::XDispatch
>* pReturn
= aReturn
.getArray();
157 const frame::DispatchDescriptor
* pDescripts
= aDescripts
.getConstArray();
158 for (sal_Int16 i
=0; i
<aDescripts
.getLength(); ++i
, ++pReturn
, ++pDescripts
)
160 *pReturn
= queryDispatch(pDescripts
->FeatureURL
,
161 pDescripts
->FrameName
, pDescripts
->SearchFlags
);
166 // XDispatchProviderInterceptor
168 uno::Reference
<frame::XDispatchProvider
> SAL_CALL
169 ScDispatchProviderInterceptor::getSlaveDispatchProvider()
170 throw(uno::RuntimeException
)
173 return m_xSlaveDispatcher
;
176 void SAL_CALL
ScDispatchProviderInterceptor::setSlaveDispatchProvider(
177 const uno::Reference
<frame::XDispatchProvider
>& xNewDispatchProvider
)
178 throw(uno::RuntimeException
)
181 m_xSlaveDispatcher
.set(xNewDispatchProvider
);
184 uno::Reference
<frame::XDispatchProvider
> SAL_CALL
185 ScDispatchProviderInterceptor::getMasterDispatchProvider()
186 throw(uno::RuntimeException
)
189 return m_xMasterDispatcher
;
192 void SAL_CALL
ScDispatchProviderInterceptor::setMasterDispatchProvider(
193 const uno::Reference
<frame::XDispatchProvider
>& xNewSupplier
)
194 throw(uno::RuntimeException
)
197 m_xMasterDispatcher
.set(xNewSupplier
);
202 void SAL_CALL
ScDispatchProviderInterceptor::disposing( const lang::EventObject
& /* Source */ )
203 throw(::com::sun::star::uno::RuntimeException
)
207 if (m_xIntercepted
.is())
209 m_xIntercepted
->releaseDispatchProviderInterceptor(
210 static_cast<frame::XDispatchProviderInterceptor
*>(this));
211 uno::Reference
<lang::XComponent
> xInterceptedComponent(m_xIntercepted
, uno::UNO_QUERY
);
212 if (xInterceptedComponent
.is())
213 xInterceptedComponent
->removeEventListener(static_cast<lang::XEventListener
*>(this));
215 m_xMyDispatch
= NULL
;
217 m_xIntercepted
= NULL
;
220 //------------------------------------------------------------------------
222 ScDispatch::ScDispatch(ScTabViewShell
* pViewSh
) :
223 pViewShell( pViewSh
),
224 bListeningToView( FALSE
)
227 StartListening(*pViewShell
);
230 ScDispatch::~ScDispatch()
233 EndListening(*pViewShell
);
235 if (bListeningToView
&& pViewShell
)
237 uno::Reference
<view::XSelectionSupplier
> xSupplier(lcl_GetSelectionSupplier( pViewShell
));
238 if ( xSupplier
.is() )
239 xSupplier
->removeSelectionChangeListener(this);
243 void ScDispatch::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
245 if ( rHint
.ISA( SfxSimpleHint
) &&
246 ((const SfxSimpleHint
&)rHint
).GetId() == SFX_HINT_DYING
)
252 void SAL_CALL
ScDispatch::dispatch( const util::URL
& aURL
,
253 const uno::Sequence
<beans::PropertyValue
>& aArgs
)
254 throw(uno::RuntimeException
)
259 if ( pViewShell
&& !aURL
.Complete
.compareToAscii(cURLInsertColumns
) )
261 ScViewData
* pViewData
= pViewShell
->GetViewData();
262 ScAddress
aPos( pViewData
->GetCurX(), pViewData
->GetCurY(), pViewData
->GetTabNo() );
264 ScDBDocFunc
aFunc( *pViewData
->GetDocShell() );
265 bDone
= aFunc
.DoImportUno( aPos
, aArgs
);
267 // cURLDocDataSource is never dispatched
270 throw uno::RuntimeException();
273 void lcl_FillDataSource( frame::FeatureStateEvent
& rEvent
, const ScImportParam
& rParam
)
275 rEvent
.IsEnabled
= rParam
.bImport
;
277 ::svx::ODataAccessDescriptor aDescriptor
;
278 if ( rParam
.bImport
)
280 sal_Int32 nType
= rParam
.bSql
? sdb::CommandType::COMMAND
:
281 ( (rParam
.nType
== ScDbQuery
) ? sdb::CommandType::QUERY
:
282 sdb::CommandType::TABLE
);
284 aDescriptor
.setDataSource(rtl::OUString( rParam
.aDBName
));
285 aDescriptor
[svx::daCommand
] <<= rtl::OUString( rParam
.aStatement
);
286 aDescriptor
[svx::daCommandType
] <<= nType
;
290 // descriptor has to be complete anyway
292 rtl::OUString aEmpty
;
293 aDescriptor
[svx::daDataSource
] <<= aEmpty
;
294 aDescriptor
[svx::daCommand
] <<= aEmpty
;
295 aDescriptor
[svx::daCommandType
] <<= (sal_Int32
)sdb::CommandType::TABLE
;
297 rEvent
.State
<<= aDescriptor
.createPropertyValueSequence();
300 void SAL_CALL
ScDispatch::addStatusListener(
301 const uno::Reference
<frame::XStatusListener
>& xListener
,
302 const util::URL
& aURL
)
303 throw(uno::RuntimeException
)
308 throw uno::RuntimeException();
311 frame::FeatureStateEvent aEvent
;
312 aEvent
.IsEnabled
= sal_True
;
313 aEvent
.Source
.set(static_cast<cppu::OWeakObject
*>(this));
314 aEvent
.FeatureURL
= aURL
;
316 if ( !aURL
.Complete
.compareToAscii(cURLDocDataSource
) )
318 uno::Reference
<frame::XStatusListener
>* pObj
=
319 new uno::Reference
<frame::XStatusListener
>( xListener
);
320 aDataSourceListeners
.Insert( pObj
, aDataSourceListeners
.Count() );
322 if (!bListeningToView
)
324 uno::Reference
<view::XSelectionSupplier
> xSupplier(lcl_GetSelectionSupplier( pViewShell
));
325 if ( xSupplier
.is() )
326 xSupplier
->addSelectionChangeListener(this);
327 bListeningToView
= sal_True
;
330 ScDBData
* pDBData
= pViewShell
->GetDBData(FALSE
,SC_DB_OLD
);
332 pDBData
->GetImportParam( aLastImport
);
333 lcl_FillDataSource( aEvent
, aLastImport
); // modifies State, IsEnabled
335 //! else add to listener for "enabled" changes?
337 xListener
->statusChanged( aEvent
);
340 void SAL_CALL
ScDispatch::removeStatusListener(
341 const uno::Reference
<frame::XStatusListener
>& xListener
,
342 const util::URL
& aURL
)
343 throw(uno::RuntimeException
)
347 if ( !aURL
.Complete
.compareToAscii(cURLDocDataSource
) )
349 USHORT nCount
= aDataSourceListeners
.Count();
350 for ( USHORT n
=nCount
; n
--; )
352 uno::Reference
<frame::XStatusListener
> *pObj
= aDataSourceListeners
[n
];
353 if ( *pObj
== xListener
)
355 aDataSourceListeners
.DeleteAndDestroy( n
);
360 if ( aDataSourceListeners
.Count() == 0 && pViewShell
)
362 uno::Reference
<view::XSelectionSupplier
> xSupplier(lcl_GetSelectionSupplier( pViewShell
));
363 if ( xSupplier
.is() )
364 xSupplier
->removeSelectionChangeListener(this);
365 bListeningToView
= sal_False
;
370 // XSelectionChangeListener
372 void SAL_CALL
ScDispatch::selectionChanged( const ::com::sun::star::lang::EventObject
& /* aEvent */ )
373 throw (::com::sun::star::uno::RuntimeException
)
375 // currently only called for URL cURLDocDataSource
379 ScImportParam aNewImport
;
380 ScDBData
* pDBData
= pViewShell
->GetDBData(FALSE
,SC_DB_OLD
);
382 pDBData
->GetImportParam( aNewImport
);
384 // notify listeners only if data source has changed
385 if ( aNewImport
.bImport
!= aLastImport
.bImport
||
386 aNewImport
.aDBName
!= aLastImport
.aDBName
||
387 aNewImport
.aStatement
!= aLastImport
.aStatement
||
388 aNewImport
.bSql
!= aLastImport
.bSql
||
389 aNewImport
.nType
!= aLastImport
.nType
)
391 frame::FeatureStateEvent aEvent
;
392 aEvent
.Source
.set(static_cast<cppu::OWeakObject
*>(this));
393 aEvent
.FeatureURL
.Complete
= rtl::OUString::createFromAscii( cURLDocDataSource
);
395 lcl_FillDataSource( aEvent
, aNewImport
); // modifies State, IsEnabled
397 for ( USHORT n
=0; n
<aDataSourceListeners
.Count(); n
++ )
398 (*aDataSourceListeners
[n
])->statusChanged( aEvent
);
400 aLastImport
= aNewImport
;
407 void SAL_CALL
ScDispatch::disposing( const ::com::sun::star::lang::EventObject
& rSource
)
408 throw (::com::sun::star::uno::RuntimeException
)
410 uno::Reference
<view::XSelectionSupplier
> xSupplier(rSource
.Source
, uno::UNO_QUERY
);
411 xSupplier
->removeSelectionChangeListener(this);
412 bListeningToView
= sal_False
;
414 lang::EventObject aEvent
;
415 aEvent
.Source
.set(static_cast<cppu::OWeakObject
*>(this));
416 for ( USHORT n
=0; n
<aDataSourceListeners
.Count(); n
++ )
417 (*aDataSourceListeners
[n
])->disposing( aEvent
);