xref: /trunk/main/sc/source/ui/unoobj/dispuno.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 fulfill
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 {
117     ScUnoGuard aGuard;
118 
119     uno::Reference<frame::XDispatch> xResult;
120     // create some dispatch ...
121     if ( pViewShell && (
122         !aURL.Complete.compareToAscii(cURLInsertColumns) ||
123         !aURL.Complete.compareToAscii(cURLDocDataSource) ) )
124     {
125         if (!m_xMyDispatch.is())
126             m_xMyDispatch = new ScDispatch( pViewShell );
127         xResult = m_xMyDispatch;
128     }
129 
130     // ask our slave provider
131     if (!xResult.is() && m_xSlaveDispatcher.is())
132         xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
133 
134     return xResult;
135 }
136 
137 uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL
queryDispatches(const uno::Sequence<frame::DispatchDescriptor> & aDescripts)138                         ScDispatchProviderInterceptor::queryDispatches(
139                         const uno::Sequence<frame::DispatchDescriptor>& aDescripts )
140 {
141     ScUnoGuard aGuard;
142 
143     uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength());
144     uno::Reference< frame::XDispatch>* pReturn = aReturn.getArray();
145     const frame::DispatchDescriptor* pDescripts = aDescripts.getConstArray();
146     for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts)
147     {
148         *pReturn = queryDispatch(pDescripts->FeatureURL,
149                 pDescripts->FrameName, pDescripts->SearchFlags);
150     }
151     return aReturn;
152 }
153 
154 // XDispatchProviderInterceptor
155 
156 uno::Reference<frame::XDispatchProvider> SAL_CALL
getSlaveDispatchProvider()157                         ScDispatchProviderInterceptor::getSlaveDispatchProvider()
158 {
159     ScUnoGuard aGuard;
160     return m_xSlaveDispatcher;
161 }
162 
setSlaveDispatchProvider(const uno::Reference<frame::XDispatchProvider> & xNewDispatchProvider)163 void SAL_CALL ScDispatchProviderInterceptor::setSlaveDispatchProvider(
164                         const uno::Reference<frame::XDispatchProvider>& xNewDispatchProvider )
165 {
166     ScUnoGuard aGuard;
167     m_xSlaveDispatcher.set(xNewDispatchProvider);
168 }
169 
170 uno::Reference<frame::XDispatchProvider> SAL_CALL
getMasterDispatchProvider()171                         ScDispatchProviderInterceptor::getMasterDispatchProvider()
172 {
173     ScUnoGuard aGuard;
174     return m_xMasterDispatcher;
175 }
176 
setMasterDispatchProvider(const uno::Reference<frame::XDispatchProvider> & xNewSupplier)177 void SAL_CALL ScDispatchProviderInterceptor::setMasterDispatchProvider(
178                         const uno::Reference<frame::XDispatchProvider>& xNewSupplier )
179 {
180     ScUnoGuard aGuard;
181     m_xMasterDispatcher.set(xNewSupplier);
182 }
183 
184 // XEventListener
185 
disposing(const lang::EventObject &)186 void SAL_CALL ScDispatchProviderInterceptor::disposing( const lang::EventObject& /* Source */ )
187 {
188     ScUnoGuard aGuard;
189 
190     if (m_xIntercepted.is())
191     {
192         m_xIntercepted->releaseDispatchProviderInterceptor(
193                 static_cast<frame::XDispatchProviderInterceptor*>(this));
194         uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
195         if (xInterceptedComponent.is())
196             xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
197 
198         m_xMyDispatch = NULL;
199     }
200     m_xIntercepted = NULL;
201 }
202 
203 //------------------------------------------------------------------------
204 
ScDispatch(ScTabViewShell * pViewSh)205 ScDispatch::ScDispatch(ScTabViewShell* pViewSh) :
206     pViewShell( pViewSh ),
207     bListeningToView( sal_False )
208 {
209     if (pViewShell)
210         StartListening(*pViewShell);
211 }
212 
~ScDispatch()213 ScDispatch::~ScDispatch()
214 {
215     if (pViewShell)
216         EndListening(*pViewShell);
217 
218     if (bListeningToView && pViewShell)
219     {
220         uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
221         if ( xSupplier.is() )
222             xSupplier->removeSelectionChangeListener(this);
223     }
224 }
225 
Notify(SfxBroadcaster &,const SfxHint & rHint)226 void ScDispatch::Notify( SfxBroadcaster&, const SfxHint& rHint )
227 {
228     if ( rHint.ISA( SfxSimpleHint ) &&
229             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
230         pViewShell = NULL;
231 }
232 
233 // XDispatch
234 
dispatch(const util::URL & aURL,const uno::Sequence<beans::PropertyValue> & aArgs)235 void SAL_CALL ScDispatch::dispatch( const util::URL& aURL,
236                                 const uno::Sequence<beans::PropertyValue>& aArgs )
237 {
238     ScUnoGuard aGuard;
239 
240     sal_Bool bDone = sal_False;
241     if ( pViewShell && !aURL.Complete.compareToAscii(cURLInsertColumns) )
242     {
243         ScViewData* pViewData = pViewShell->GetViewData();
244         ScAddress aPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
245 
246         ScDBDocFunc aFunc( *pViewData->GetDocShell() );
247         bDone = aFunc.DoImportUno( aPos, aArgs );
248     }
249     // cURLDocDataSource is never dispatched
250 
251     if (!bDone)
252         throw uno::RuntimeException();
253 }
254 
lcl_FillDataSource(frame::FeatureStateEvent & rEvent,const ScImportParam & rParam)255 void lcl_FillDataSource( frame::FeatureStateEvent& rEvent, const ScImportParam& rParam )
256 {
257     rEvent.IsEnabled = rParam.bImport;
258 
259     ::svx::ODataAccessDescriptor aDescriptor;
260     if ( rParam.bImport )
261     {
262         sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
263                     ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
264                                                     sdb::CommandType::TABLE );
265 
266         aDescriptor.setDataSource(rtl::OUString( rParam.aDBName ));
267         aDescriptor[svx::daCommand]     <<= rtl::OUString( rParam.aStatement );
268         aDescriptor[svx::daCommandType] <<= nType;
269     }
270     else
271     {
272         //  descriptor has to be complete anyway
273 
274         rtl::OUString aEmpty;
275         aDescriptor[svx::daDataSource]  <<= aEmpty;
276         aDescriptor[svx::daCommand]     <<= aEmpty;
277         aDescriptor[svx::daCommandType] <<= (sal_Int32)sdb::CommandType::TABLE;
278     }
279     rEvent.State <<= aDescriptor.createPropertyValueSequence();
280 }
281 
addStatusListener(const uno::Reference<frame::XStatusListener> & xListener,const util::URL & aURL)282 void SAL_CALL ScDispatch::addStatusListener(
283                                 const uno::Reference<frame::XStatusListener>& xListener,
284                                 const util::URL& aURL )
285 {
286     ScUnoGuard aGuard;
287 
288     if (!pViewShell)
289         throw uno::RuntimeException();
290 
291     //  initial state
292     frame::FeatureStateEvent aEvent;
293     aEvent.IsEnabled = sal_True;
294     aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
295     aEvent.FeatureURL = aURL;
296 
297     if ( !aURL.Complete.compareToAscii(cURLDocDataSource) )
298     {
299         uno::Reference<frame::XStatusListener>* pObj =
300                 new uno::Reference<frame::XStatusListener>( xListener );
301         aDataSourceListeners.Insert( pObj, aDataSourceListeners.Count() );
302 
303         if (!bListeningToView)
304         {
305             uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
306             if ( xSupplier.is() )
307                 xSupplier->addSelectionChangeListener(this);
308             bListeningToView = sal_True;
309         }
310 
311         ScDBData* pDBData = pViewShell->GetDBData(sal_False,SC_DB_OLD);
312         if ( pDBData )
313             pDBData->GetImportParam( aLastImport );
314         lcl_FillDataSource( aEvent, aLastImport );          // modifies State, IsEnabled
315     }
316     //! else add to listener for "enabled" changes?
317 
318     xListener->statusChanged( aEvent );
319 }
320 
removeStatusListener(const uno::Reference<frame::XStatusListener> & xListener,const util::URL & aURL)321 void SAL_CALL ScDispatch::removeStatusListener(
322                                 const uno::Reference<frame::XStatusListener>& xListener,
323                                 const util::URL& aURL )
324 {
325     ScUnoGuard aGuard;
326 
327     if ( !aURL.Complete.compareToAscii(cURLDocDataSource) )
328     {
329         sal_uInt16 nCount = aDataSourceListeners.Count();
330         for ( sal_uInt16 n=nCount; n--; )
331         {
332             uno::Reference<frame::XStatusListener> *pObj = aDataSourceListeners[n];
333             if ( *pObj == xListener )
334             {
335                 aDataSourceListeners.DeleteAndDestroy( n );
336                 break;
337             }
338         }
339 
340         if ( aDataSourceListeners.Count() == 0 && pViewShell )
341         {
342             uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
343             if ( xSupplier.is() )
344                 xSupplier->removeSelectionChangeListener(this);
345             bListeningToView = sal_False;
346         }
347     }
348 }
349 
350 // XSelectionChangeListener
351 
selectionChanged(const::com::sun::star::lang::EventObject &)352 void SAL_CALL ScDispatch::selectionChanged( const ::com::sun::star::lang::EventObject& /* aEvent */ )
353 {
354     //  currently only called for URL cURLDocDataSource
355 
356     if ( pViewShell )
357     {
358         ScImportParam aNewImport;
359         ScDBData* pDBData = pViewShell->GetDBData(sal_False,SC_DB_OLD);
360         if ( pDBData )
361             pDBData->GetImportParam( aNewImport );
362 
363         //  notify listeners only if data source has changed
364         if ( aNewImport.bImport    != aLastImport.bImport ||
365              aNewImport.aDBName    != aLastImport.aDBName ||
366              aNewImport.aStatement != aLastImport.aStatement ||
367              aNewImport.bSql       != aLastImport.bSql ||
368              aNewImport.nType      != aLastImport.nType )
369         {
370             frame::FeatureStateEvent aEvent;
371             aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
372             aEvent.FeatureURL.Complete = rtl::OUString::createFromAscii( cURLDocDataSource );
373 
374             lcl_FillDataSource( aEvent, aNewImport );       // modifies State, IsEnabled
375 
376             for ( sal_uInt16 n=0; n<aDataSourceListeners.Count(); n++ )
377                 (*aDataSourceListeners[n])->statusChanged( aEvent );
378 
379             aLastImport = aNewImport;
380         }
381     }
382 }
383 
384 // XEventListener
385 
disposing(const::com::sun::star::lang::EventObject & rSource)386 void SAL_CALL ScDispatch::disposing( const ::com::sun::star::lang::EventObject& rSource )
387 {
388     uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY);
389     xSupplier->removeSelectionChangeListener(this);
390     bListeningToView = sal_False;
391 
392     lang::EventObject aEvent;
393     aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
394     for ( sal_uInt16 n=0; n<aDataSourceListeners.Count(); n++ )
395         (*aDataSourceListeners[n])->disposing( aEvent );
396 
397     pViewShell = NULL;
398 }
399