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 <sfx2/viewfrm.hxx>
21 : #include <comphelper/uno3.hxx>
22 : #include <svx/dataaccessdescriptor.hxx>
23 : #include <svl/smplhint.hxx>
24 : #include <vcl/svapp.hxx>
25 :
26 : #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
27 : #include <com/sun/star/view/XSelectionSupplier.hpp>
28 : #include <com/sun/star/sdb/CommandType.hpp>
29 :
30 : #include "dispuno.hxx"
31 : #include "tabvwsh.hxx"
32 : #include "dbdocfun.hxx"
33 : #include "dbdata.hxx"
34 :
35 : using namespace com::sun::star;
36 :
37 : static const char* cURLInsertColumns = ".uno:DataSourceBrowser/InsertColumns"; //data into text
38 : static const char* cURLDocDataSource = ".uno:DataSourceBrowser/DocumentDataSource";
39 :
40 0 : static uno::Reference<view::XSelectionSupplier> lcl_GetSelectionSupplier( SfxViewShell* pViewShell )
41 : {
42 0 : if ( pViewShell )
43 : {
44 0 : SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
45 0 : if (pViewFrame)
46 : {
47 0 : return uno::Reference<view::XSelectionSupplier>( pViewFrame->GetFrame().GetController(), uno::UNO_QUERY );
48 : }
49 : }
50 0 : return uno::Reference<view::XSelectionSupplier>();
51 : }
52 :
53 546 : ScDispatchProviderInterceptor::ScDispatchProviderInterceptor(ScTabViewShell* pViewSh) :
54 546 : pViewShell( pViewSh )
55 : {
56 546 : if ( pViewShell )
57 : {
58 546 : m_xIntercepted.set(uno::Reference<frame::XDispatchProviderInterception>(pViewShell->GetViewFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY));
59 546 : if (m_xIntercepted.is())
60 : {
61 546 : comphelper::increment( m_refCount );
62 :
63 546 : m_xIntercepted->registerDispatchProviderInterceptor(
64 546 : static_cast<frame::XDispatchProviderInterceptor*>(this));
65 : // this should make us the top-level dispatch-provider for the component, via a call to our
66 : // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fulfill
67 546 : uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
68 546 : if (xInterceptedComponent.is())
69 546 : xInterceptedComponent->addEventListener(static_cast<lang::XEventListener*>(this));
70 :
71 546 : comphelper::decrement( m_refCount );
72 : }
73 :
74 546 : StartListening(*pViewShell);
75 : }
76 546 : }
77 :
78 1638 : ScDispatchProviderInterceptor::~ScDispatchProviderInterceptor()
79 : {
80 546 : if (pViewShell)
81 0 : EndListening(*pViewShell);
82 1092 : }
83 :
84 546 : void ScDispatchProviderInterceptor::Notify( SfxBroadcaster&, const SfxHint& rHint )
85 : {
86 546 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
87 546 : if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
88 546 : pViewShell = NULL;
89 546 : }
90 :
91 : // XDispatchProvider
92 :
93 47493 : uno::Reference<frame::XDispatch> SAL_CALL ScDispatchProviderInterceptor::queryDispatch(
94 : const util::URL& aURL, const OUString& aTargetFrameName,
95 : sal_Int32 nSearchFlags )
96 : throw(uno::RuntimeException, std::exception)
97 : {
98 47493 : SolarMutexGuard aGuard;
99 :
100 47493 : uno::Reference<frame::XDispatch> xResult;
101 : // create some dispatch ...
102 93228 : if ( pViewShell && (
103 91470 : aURL.Complete.equalsAscii(cURLInsertColumns) ||
104 45735 : aURL.Complete.equalsAscii(cURLDocDataSource) ) )
105 : {
106 0 : if (!m_xMyDispatch.is())
107 0 : m_xMyDispatch = new ScDispatch( pViewShell );
108 0 : xResult = m_xMyDispatch;
109 : }
110 :
111 : // ask our slave provider
112 47493 : if (!xResult.is() && m_xSlaveDispatcher.is())
113 47493 : xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
114 :
115 47493 : return xResult;
116 : }
117 :
118 : uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL
119 0 : ScDispatchProviderInterceptor::queryDispatches(
120 : const uno::Sequence<frame::DispatchDescriptor>& aDescripts )
121 : throw(uno::RuntimeException, std::exception)
122 : {
123 0 : SolarMutexGuard aGuard;
124 :
125 0 : uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength());
126 0 : uno::Reference< frame::XDispatch>* pReturn = aReturn.getArray();
127 0 : const frame::DispatchDescriptor* pDescripts = aDescripts.getConstArray();
128 0 : for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts)
129 : {
130 0 : *pReturn = queryDispatch(pDescripts->FeatureURL,
131 0 : pDescripts->FrameName, pDescripts->SearchFlags);
132 : }
133 0 : return aReturn;
134 : }
135 :
136 : // XDispatchProviderInterceptor
137 :
138 : uno::Reference<frame::XDispatchProvider> SAL_CALL
139 546 : ScDispatchProviderInterceptor::getSlaveDispatchProvider()
140 : throw(uno::RuntimeException, std::exception)
141 : {
142 546 : SolarMutexGuard aGuard;
143 546 : return m_xSlaveDispatcher;
144 : }
145 :
146 1092 : void SAL_CALL ScDispatchProviderInterceptor::setSlaveDispatchProvider(
147 : const uno::Reference<frame::XDispatchProvider>& xNewDispatchProvider )
148 : throw(uno::RuntimeException, std::exception)
149 : {
150 1092 : SolarMutexGuard aGuard;
151 1092 : m_xSlaveDispatcher.set(xNewDispatchProvider);
152 1092 : }
153 :
154 : uno::Reference<frame::XDispatchProvider> SAL_CALL
155 546 : ScDispatchProviderInterceptor::getMasterDispatchProvider()
156 : throw(uno::RuntimeException, std::exception)
157 : {
158 546 : SolarMutexGuard aGuard;
159 546 : return m_xMasterDispatcher;
160 : }
161 :
162 1092 : void SAL_CALL ScDispatchProviderInterceptor::setMasterDispatchProvider(
163 : const uno::Reference<frame::XDispatchProvider>& xNewSupplier )
164 : throw(uno::RuntimeException, std::exception)
165 : {
166 1092 : SolarMutexGuard aGuard;
167 1092 : m_xMasterDispatcher.set(xNewSupplier);
168 1092 : }
169 :
170 : // XEventListener
171 :
172 546 : void SAL_CALL ScDispatchProviderInterceptor::disposing( const lang::EventObject& /* Source */ )
173 : throw(::com::sun::star::uno::RuntimeException, std::exception)
174 : {
175 546 : SolarMutexGuard aGuard;
176 :
177 546 : if (m_xIntercepted.is())
178 : {
179 546 : m_xIntercepted->releaseDispatchProviderInterceptor(
180 546 : static_cast<frame::XDispatchProviderInterceptor*>(this));
181 546 : uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
182 546 : if (xInterceptedComponent.is())
183 546 : xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
184 :
185 546 : m_xMyDispatch = NULL;
186 : }
187 546 : m_xIntercepted = NULL;
188 546 : }
189 :
190 0 : ScDispatch::ScDispatch(ScTabViewShell* pViewSh) :
191 : pViewShell( pViewSh ),
192 0 : bListeningToView( false )
193 : {
194 0 : if (pViewShell)
195 0 : StartListening(*pViewShell);
196 0 : }
197 :
198 0 : ScDispatch::~ScDispatch()
199 : {
200 0 : if (pViewShell)
201 0 : EndListening(*pViewShell);
202 :
203 0 : if (bListeningToView && pViewShell)
204 : {
205 0 : uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
206 0 : if ( xSupplier.is() )
207 0 : xSupplier->removeSelectionChangeListener(this);
208 : }
209 0 : }
210 :
211 0 : void ScDispatch::Notify( SfxBroadcaster&, const SfxHint& rHint )
212 : {
213 0 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
214 0 : if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
215 0 : pViewShell = NULL;
216 0 : }
217 :
218 : // XDispatch
219 :
220 0 : void SAL_CALL ScDispatch::dispatch( const util::URL& aURL,
221 : const uno::Sequence<beans::PropertyValue>& aArgs )
222 : throw(uno::RuntimeException, std::exception)
223 : {
224 0 : SolarMutexGuard aGuard;
225 :
226 0 : bool bDone = false;
227 0 : if ( pViewShell && aURL.Complete.equalsAscii(cURLInsertColumns) )
228 : {
229 0 : ScViewData& rViewData = pViewShell->GetViewData();
230 0 : ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
231 :
232 0 : ScDBDocFunc aFunc( *rViewData.GetDocShell() );
233 0 : bDone = aFunc.DoImportUno( aPos, aArgs );
234 : }
235 : // cURLDocDataSource is never dispatched
236 :
237 0 : if (!bDone)
238 0 : throw uno::RuntimeException();
239 0 : }
240 :
241 0 : static void lcl_FillDataSource( frame::FeatureStateEvent& rEvent, const ScImportParam& rParam )
242 : {
243 0 : rEvent.IsEnabled = rParam.bImport;
244 :
245 0 : ::svx::ODataAccessDescriptor aDescriptor;
246 0 : if ( rParam.bImport )
247 : {
248 : sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
249 0 : ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
250 0 : sdb::CommandType::TABLE );
251 :
252 0 : aDescriptor.setDataSource(rParam.aDBName);
253 0 : aDescriptor[svx::daCommand] <<= rParam.aStatement;
254 0 : aDescriptor[svx::daCommandType] <<= nType;
255 : }
256 : else
257 : {
258 : // descriptor has to be complete anyway
259 :
260 0 : OUString aEmpty;
261 0 : aDescriptor[svx::daDataSource] <<= aEmpty;
262 0 : aDescriptor[svx::daCommand] <<= aEmpty;
263 0 : aDescriptor[svx::daCommandType] <<= (sal_Int32)sdb::CommandType::TABLE;
264 : }
265 0 : rEvent.State <<= aDescriptor.createPropertyValueSequence();
266 0 : }
267 :
268 0 : void SAL_CALL ScDispatch::addStatusListener(
269 : const uno::Reference<frame::XStatusListener>& xListener,
270 : const util::URL& aURL)
271 : throw(uno::RuntimeException, std::exception)
272 : {
273 0 : SolarMutexGuard aGuard;
274 :
275 0 : if (!pViewShell)
276 0 : throw uno::RuntimeException();
277 :
278 : // initial state
279 0 : frame::FeatureStateEvent aEvent;
280 0 : aEvent.IsEnabled = sal_True;
281 0 : aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
282 0 : aEvent.FeatureURL = aURL;
283 :
284 0 : if ( aURL.Complete.equalsAscii(cURLDocDataSource) )
285 : {
286 : uno::Reference<frame::XStatusListener>* pObj =
287 0 : new uno::Reference<frame::XStatusListener>( xListener );
288 0 : aDataSourceListeners.push_back( pObj );
289 :
290 0 : if (!bListeningToView)
291 : {
292 0 : uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
293 0 : if ( xSupplier.is() )
294 0 : xSupplier->addSelectionChangeListener(this);
295 0 : bListeningToView = true;
296 : }
297 :
298 0 : ScDBData* pDBData = pViewShell->GetDBData(false,SC_DB_OLD);
299 0 : if ( pDBData )
300 0 : pDBData->GetImportParam( aLastImport );
301 0 : lcl_FillDataSource( aEvent, aLastImport ); // modifies State, IsEnabled
302 : }
303 : //! else add to listener for "enabled" changes?
304 :
305 0 : xListener->statusChanged( aEvent );
306 0 : }
307 :
308 0 : void SAL_CALL ScDispatch::removeStatusListener(
309 : const uno::Reference<frame::XStatusListener>& xListener,
310 : const util::URL& aURL )
311 : throw(uno::RuntimeException, std::exception)
312 : {
313 0 : SolarMutexGuard aGuard;
314 :
315 0 : if ( aURL.Complete.equalsAscii(cURLDocDataSource) )
316 : {
317 0 : sal_uInt16 nCount = aDataSourceListeners.size();
318 0 : for ( sal_uInt16 n=nCount; n--; )
319 : {
320 0 : uno::Reference<frame::XStatusListener>& rObj = aDataSourceListeners[n];
321 0 : if ( rObj == xListener )
322 : {
323 0 : aDataSourceListeners.erase( aDataSourceListeners.begin() + n );
324 0 : break;
325 : }
326 : }
327 :
328 0 : if ( aDataSourceListeners.empty() && pViewShell )
329 : {
330 0 : uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
331 0 : if ( xSupplier.is() )
332 0 : xSupplier->removeSelectionChangeListener(this);
333 0 : bListeningToView = false;
334 : }
335 0 : }
336 0 : }
337 :
338 : // XSelectionChangeListener
339 :
340 0 : void SAL_CALL ScDispatch::selectionChanged( const ::com::sun::star::lang::EventObject& /* aEvent */ )
341 : throw (::com::sun::star::uno::RuntimeException, std::exception)
342 : {
343 : // currently only called for URL cURLDocDataSource
344 :
345 0 : if ( pViewShell )
346 : {
347 0 : ScImportParam aNewImport;
348 0 : ScDBData* pDBData = pViewShell->GetDBData(false,SC_DB_OLD);
349 0 : if ( pDBData )
350 0 : pDBData->GetImportParam( aNewImport );
351 :
352 : // notify listeners only if data source has changed
353 0 : if ( aNewImport.bImport != aLastImport.bImport ||
354 0 : aNewImport.aDBName != aLastImport.aDBName ||
355 0 : aNewImport.aStatement != aLastImport.aStatement ||
356 0 : aNewImport.bSql != aLastImport.bSql ||
357 0 : aNewImport.nType != aLastImport.nType )
358 : {
359 0 : frame::FeatureStateEvent aEvent;
360 0 : aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
361 0 : aEvent.FeatureURL.Complete = OUString::createFromAscii( cURLDocDataSource );
362 :
363 0 : lcl_FillDataSource( aEvent, aNewImport ); // modifies State, IsEnabled
364 :
365 0 : for ( sal_uInt16 n=0; n<aDataSourceListeners.size(); n++ )
366 0 : aDataSourceListeners[n]->statusChanged( aEvent );
367 :
368 0 : aLastImport = aNewImport;
369 0 : }
370 : }
371 0 : }
372 :
373 : // XEventListener
374 :
375 0 : void SAL_CALL ScDispatch::disposing( const ::com::sun::star::lang::EventObject& rSource )
376 : throw (::com::sun::star::uno::RuntimeException, std::exception)
377 : {
378 0 : uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY);
379 0 : xSupplier->removeSelectionChangeListener(this);
380 0 : bListeningToView = false;
381 :
382 0 : lang::EventObject aEvent;
383 0 : aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
384 0 : for ( sal_uInt16 n=0; n<aDataSourceListeners.size(); n++ )
385 0 : aDataSourceListeners[n]->disposing( aEvent );
386 :
387 0 : pViewShell = NULL;
388 228 : }
389 :
390 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|