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