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