xref: /aoo41x/main/sc/source/ui/unoobj/dispuno.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 #include <sfx2/viewfrm.hxx>
34 #include <comphelper/uno3.hxx>
35 #include <svx/dataaccessdescriptor.hxx>
36 #include <svl/smplhint.hxx>
37 
38 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
39 #include <com/sun/star/view/XSelectionSupplier.hpp>
40 #include <com/sun/star/sdb/CommandType.hpp>
41 
42 #include "dispuno.hxx"
43 #include "unoguard.hxx"
44 #include "tabvwsh.hxx"
45 #include "dbdocfun.hxx"
46 #include "dbcolect.hxx"
47 
48 using namespace com::sun::star;
49 
50 //------------------------------------------------------------------------
51 
52 const char* cURLInsertColumns = ".uno:DataSourceBrowser/InsertColumns"; //data into text
53 const char* cURLDocDataSource = ".uno:DataSourceBrowser/DocumentDataSource";
54 
55 //------------------------------------------------------------------------
56 
57 SV_IMPL_PTRARR( XStatusListenerArr_Impl, XStatusListenerPtr );
58 
59 //------------------------------------------------------------------------
60 
61 uno::Reference<view::XSelectionSupplier> lcl_GetSelectionSupplier( SfxViewShell* pViewShell )
62 {
63 	if ( pViewShell )
64 	{
65 		SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
66 		if (pViewFrame)
67 		{
68 			return uno::Reference<view::XSelectionSupplier>( pViewFrame->GetFrame().GetController(), uno::UNO_QUERY );
69 		}
70 	}
71 	return uno::Reference<view::XSelectionSupplier>();
72 }
73 
74 //------------------------------------------------------------------------
75 
76 
77 ScDispatchProviderInterceptor::ScDispatchProviderInterceptor(ScTabViewShell* pViewSh) :
78 	pViewShell( pViewSh )
79 {
80 	if ( pViewShell )
81 	{
82 		m_xIntercepted.set(uno::Reference<frame::XDispatchProviderInterception>(pViewShell->GetViewFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY));
83 		if (m_xIntercepted.is())
84 		{
85 			comphelper::increment( m_refCount );
86 
87 			m_xIntercepted->registerDispatchProviderInterceptor(
88 						static_cast<frame::XDispatchProviderInterceptor*>(this));
89 			// this should make us the top-level dispatch-provider for the component, via a call to our
90 			// setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill
91 			uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
92 			if (xInterceptedComponent.is())
93 				xInterceptedComponent->addEventListener(static_cast<lang::XEventListener*>(this));
94 
95 			comphelper::decrement( m_refCount );
96 		}
97 
98 		StartListening(*pViewShell);
99 	}
100 }
101 
102 ScDispatchProviderInterceptor::~ScDispatchProviderInterceptor()
103 {
104 	if (pViewShell)
105 		EndListening(*pViewShell);
106 }
107 
108 void ScDispatchProviderInterceptor::Notify( SfxBroadcaster&, const SfxHint& rHint )
109 {
110 	if ( rHint.ISA( SfxSimpleHint ) &&
111 			((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
112 		pViewShell = NULL;
113 }
114 
115 // XDispatchProvider
116 
117 uno::Reference<frame::XDispatch> SAL_CALL ScDispatchProviderInterceptor::queryDispatch(
118 						const util::URL& aURL, const rtl::OUString& aTargetFrameName,
119 						sal_Int32 nSearchFlags )
120 						throw(uno::RuntimeException)
121 {
122 	ScUnoGuard aGuard;
123 
124 	uno::Reference<frame::XDispatch> xResult;
125 	// create some dispatch ...
126 	if ( pViewShell && (
127 		!aURL.Complete.compareToAscii(cURLInsertColumns) ||
128 		!aURL.Complete.compareToAscii(cURLDocDataSource) ) )
129 	{
130 		if (!m_xMyDispatch.is())
131 			m_xMyDispatch = new ScDispatch( pViewShell );
132 		xResult = m_xMyDispatch;
133 	}
134 
135 	// ask our slave provider
136 	if (!xResult.is() && m_xSlaveDispatcher.is())
137 		xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
138 
139 	return xResult;
140 }
141 
142 uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL
143 						ScDispatchProviderInterceptor::queryDispatches(
144 						const uno::Sequence<frame::DispatchDescriptor>& aDescripts )
145 						throw(uno::RuntimeException)
146 {
147 	ScUnoGuard aGuard;
148 
149 	uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength());
150 	uno::Reference< frame::XDispatch>* pReturn = aReturn.getArray();
151 	const frame::DispatchDescriptor* pDescripts = aDescripts.getConstArray();
152 	for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts)
153 	{
154 		*pReturn = queryDispatch(pDescripts->FeatureURL,
155 				pDescripts->FrameName, pDescripts->SearchFlags);
156 	}
157 	return aReturn;
158 }
159 
160 // XDispatchProviderInterceptor
161 
162 uno::Reference<frame::XDispatchProvider> SAL_CALL
163 						ScDispatchProviderInterceptor::getSlaveDispatchProvider()
164 						throw(uno::RuntimeException)
165 {
166 	ScUnoGuard aGuard;
167 	return m_xSlaveDispatcher;
168 }
169 
170 void SAL_CALL ScDispatchProviderInterceptor::setSlaveDispatchProvider(
171 						const uno::Reference<frame::XDispatchProvider>& xNewDispatchProvider )
172 						throw(uno::RuntimeException)
173 {
174 	ScUnoGuard aGuard;
175 	m_xSlaveDispatcher.set(xNewDispatchProvider);
176 }
177 
178 uno::Reference<frame::XDispatchProvider> SAL_CALL
179 						ScDispatchProviderInterceptor::getMasterDispatchProvider()
180 						throw(uno::RuntimeException)
181 {
182 	ScUnoGuard aGuard;
183 	return m_xMasterDispatcher;
184 }
185 
186 void SAL_CALL ScDispatchProviderInterceptor::setMasterDispatchProvider(
187 						const uno::Reference<frame::XDispatchProvider>& xNewSupplier )
188 						throw(uno::RuntimeException)
189 {
190 	ScUnoGuard aGuard;
191 	m_xMasterDispatcher.set(xNewSupplier);
192 }
193 
194 // XEventListener
195 
196 void SAL_CALL ScDispatchProviderInterceptor::disposing( const lang::EventObject& /* Source */ )
197 								throw(::com::sun::star::uno::RuntimeException)
198 {
199 	ScUnoGuard aGuard;
200 
201 	if (m_xIntercepted.is())
202 	{
203 		m_xIntercepted->releaseDispatchProviderInterceptor(
204 				static_cast<frame::XDispatchProviderInterceptor*>(this));
205 		uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
206 		if (xInterceptedComponent.is())
207 			xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
208 
209 		m_xMyDispatch = NULL;
210 	}
211 	m_xIntercepted = NULL;
212 }
213 
214 //------------------------------------------------------------------------
215 
216 ScDispatch::ScDispatch(ScTabViewShell* pViewSh) :
217 	pViewShell( pViewSh ),
218 	bListeningToView( sal_False )
219 {
220 	if (pViewShell)
221 		StartListening(*pViewShell);
222 }
223 
224 ScDispatch::~ScDispatch()
225 {
226 	if (pViewShell)
227 		EndListening(*pViewShell);
228 
229     if (bListeningToView && pViewShell)
230     {
231         uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
232         if ( xSupplier.is() )
233 	        xSupplier->removeSelectionChangeListener(this);
234     }
235 }
236 
237 void ScDispatch::Notify( SfxBroadcaster&, const SfxHint& rHint )
238 {
239 	if ( rHint.ISA( SfxSimpleHint ) &&
240 			((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
241 		pViewShell = NULL;
242 }
243 
244 // XDispatch
245 
246 void SAL_CALL ScDispatch::dispatch( const util::URL& aURL,
247 								const uno::Sequence<beans::PropertyValue>& aArgs )
248 								throw(uno::RuntimeException)
249 {
250 	ScUnoGuard aGuard;
251 
252 	sal_Bool bDone = sal_False;
253 	if ( pViewShell && !aURL.Complete.compareToAscii(cURLInsertColumns) )
254 	{
255 		ScViewData* pViewData = pViewShell->GetViewData();
256 		ScAddress aPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
257 
258 		ScDBDocFunc aFunc( *pViewData->GetDocShell() );
259 		bDone = aFunc.DoImportUno( aPos, aArgs );
260 	}
261 	// cURLDocDataSource is never dispatched
262 
263 	if (!bDone)
264 		throw uno::RuntimeException();
265 }
266 
267 void lcl_FillDataSource( frame::FeatureStateEvent& rEvent, const ScImportParam& rParam )
268 {
269     rEvent.IsEnabled = rParam.bImport;
270 
271     ::svx::ODataAccessDescriptor aDescriptor;
272     if ( rParam.bImport )
273     {
274         sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
275                     ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
276                                                     sdb::CommandType::TABLE );
277 
278 		aDescriptor.setDataSource(rtl::OUString( rParam.aDBName ));
279         aDescriptor[svx::daCommand]     <<= rtl::OUString( rParam.aStatement );
280         aDescriptor[svx::daCommandType] <<= nType;
281     }
282     else
283     {
284         //  descriptor has to be complete anyway
285 
286         rtl::OUString aEmpty;
287         aDescriptor[svx::daDataSource]  <<= aEmpty;
288         aDescriptor[svx::daCommand]     <<= aEmpty;
289         aDescriptor[svx::daCommandType] <<= (sal_Int32)sdb::CommandType::TABLE;
290     }
291     rEvent.State <<= aDescriptor.createPropertyValueSequence();
292 }
293 
294 void SAL_CALL ScDispatch::addStatusListener(
295                                 const uno::Reference<frame::XStatusListener>& xListener,
296                                 const util::URL& aURL )
297                                 throw(uno::RuntimeException)
298 {
299     ScUnoGuard aGuard;
300 
301     if (!pViewShell)
302         throw uno::RuntimeException();
303 
304     //  initial state
305     frame::FeatureStateEvent aEvent;
306     aEvent.IsEnabled = sal_True;
307     aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
308     aEvent.FeatureURL = aURL;
309 
310     if ( !aURL.Complete.compareToAscii(cURLDocDataSource) )
311     {
312         uno::Reference<frame::XStatusListener>* pObj =
313                 new uno::Reference<frame::XStatusListener>( xListener );
314         aDataSourceListeners.Insert( pObj, aDataSourceListeners.Count() );
315 
316         if (!bListeningToView)
317         {
318             uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
319             if ( xSupplier.is() )
320                 xSupplier->addSelectionChangeListener(this);
321             bListeningToView = sal_True;
322         }
323 
324         ScDBData* pDBData = pViewShell->GetDBData(sal_False,SC_DB_OLD);
325         if ( pDBData )
326             pDBData->GetImportParam( aLastImport );
327         lcl_FillDataSource( aEvent, aLastImport );          // modifies State, IsEnabled
328     }
329     //! else add to listener for "enabled" changes?
330 
331     xListener->statusChanged( aEvent );
332 }
333 
334 void SAL_CALL ScDispatch::removeStatusListener(
335                                 const uno::Reference<frame::XStatusListener>& xListener,
336                                 const util::URL& aURL )
337                                 throw(uno::RuntimeException)
338 {
339     ScUnoGuard aGuard;
340 
341     if ( !aURL.Complete.compareToAscii(cURLDocDataSource) )
342     {
343         sal_uInt16 nCount = aDataSourceListeners.Count();
344         for ( sal_uInt16 n=nCount; n--; )
345         {
346             uno::Reference<frame::XStatusListener> *pObj = aDataSourceListeners[n];
347             if ( *pObj == xListener )
348             {
349                 aDataSourceListeners.DeleteAndDestroy( n );
350                 break;
351             }
352         }
353 
354         if ( aDataSourceListeners.Count() == 0 && pViewShell )
355         {
356             uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
357             if ( xSupplier.is() )
358                 xSupplier->removeSelectionChangeListener(this);
359             bListeningToView = sal_False;
360         }
361     }
362 }
363 
364 // XSelectionChangeListener
365 
366 void SAL_CALL ScDispatch::selectionChanged( const ::com::sun::star::lang::EventObject& /* aEvent */ )
367                                 throw (::com::sun::star::uno::RuntimeException)
368 {
369     //  currently only called for URL cURLDocDataSource
370 
371     if ( pViewShell )
372     {
373         ScImportParam aNewImport;
374         ScDBData* pDBData = pViewShell->GetDBData(sal_False,SC_DB_OLD);
375         if ( pDBData )
376             pDBData->GetImportParam( aNewImport );
377 
378         //  notify listeners only if data source has changed
379         if ( aNewImport.bImport    != aLastImport.bImport ||
380              aNewImport.aDBName    != aLastImport.aDBName ||
381              aNewImport.aStatement != aLastImport.aStatement ||
382              aNewImport.bSql       != aLastImport.bSql ||
383              aNewImport.nType      != aLastImport.nType )
384         {
385             frame::FeatureStateEvent aEvent;
386             aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
387             aEvent.FeatureURL.Complete = rtl::OUString::createFromAscii( cURLDocDataSource );
388 
389             lcl_FillDataSource( aEvent, aNewImport );       // modifies State, IsEnabled
390 
391             for ( sal_uInt16 n=0; n<aDataSourceListeners.Count(); n++ )
392                 (*aDataSourceListeners[n])->statusChanged( aEvent );
393 
394             aLastImport = aNewImport;
395         }
396     }
397 }
398 
399 // XEventListener
400 
401 void SAL_CALL ScDispatch::disposing( const ::com::sun::star::lang::EventObject& rSource )
402                                 throw (::com::sun::star::uno::RuntimeException)
403 {
404     uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY);
405     xSupplier->removeSelectionChangeListener(this);
406     bListeningToView = sal_False;
407 
408     lang::EventObject aEvent;
409     aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
410     for ( sal_uInt16 n=0; n<aDataSourceListeners.Count(); n++ )
411         (*aDataSourceListeners[n])->disposing( aEvent );
412 
413     pViewShell = NULL;
414 }
415 
416