LibreOffice Module sc (master)  1
dispuno.cxx
Go to the documentation of this file.
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>
22 #include <svl/hint.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 const char cURLInsertColumns[] = ".uno:DataSourceBrowser/InsertColumns"; //data into text
37 const char cURLDocDataSource[] = ".uno:DataSourceBrowser/DocumentDataSource";
38 
39 static uno::Reference<view::XSelectionSupplier> lcl_GetSelectionSupplier( const SfxViewShell* pViewShell )
40 {
41  if ( pViewShell )
42  {
43  SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
44  if (pViewFrame)
45  {
46  return uno::Reference<view::XSelectionSupplier>( pViewFrame->GetFrame().GetController(), uno::UNO_QUERY );
47  }
48  }
49  return uno::Reference<view::XSelectionSupplier>();
50 }
51 
53  pViewShell( pViewSh )
54 {
55  if ( !pViewShell )
56  return;
57 
58  m_xIntercepted.set(uno::Reference<frame::XDispatchProviderInterception>(pViewShell->GetViewFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY));
59  if (m_xIntercepted.is())
60  {
61  osl_atomic_increment( &m_refCount );
62 
63  m_xIntercepted->registerDispatchProviderInterceptor(
64  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 a fallback for requests we (i.e. our master) cannot fulfill
67  uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
68  if (xInterceptedComponent.is())
69  xInterceptedComponent->addEventListener(static_cast<lang::XEventListener*>(this));
70 
71  osl_atomic_decrement( &m_refCount );
72  }
73 
75 }
76 
78 {
79  if (pViewShell)
81 }
82 
84 {
85  if ( rHint.GetId() == SfxHintId::Dying )
86  pViewShell = nullptr;
87 }
88 
89 // XDispatchProvider
90 
91 uno::Reference<frame::XDispatch> SAL_CALL ScDispatchProviderInterceptor::queryDispatch(
92  const util::URL& aURL, const OUString& aTargetFrameName,
93  sal_Int32 nSearchFlags )
94 {
95  SolarMutexGuard aGuard;
96 
97  uno::Reference<frame::XDispatch> xResult;
98  // create some dispatch ...
99  if ( pViewShell && (
100  aURL.Complete == cURLInsertColumns ||
101  aURL.Complete == cURLDocDataSource ) )
102  {
103  if (!m_xMyDispatch.is())
105  xResult = m_xMyDispatch;
106  }
107 
108  // ask our slave provider
109  if (!xResult.is() && m_xSlaveDispatcher.is())
110  xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
111 
112  return xResult;
113 }
114 
115 uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL
117  const uno::Sequence<frame::DispatchDescriptor>& aDescripts )
118 {
119  SolarMutexGuard aGuard;
120 
121  uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength());
122  std::transform(aDescripts.begin(), aDescripts.end(), aReturn.begin(),
123  [this](const frame::DispatchDescriptor& rDescr) -> uno::Reference<frame::XDispatch> {
124  return queryDispatch(rDescr.FeatureURL, rDescr.FrameName, rDescr.SearchFlags); });
125  return aReturn;
126 }
127 
128 // XDispatchProviderInterceptor
129 
130 uno::Reference<frame::XDispatchProvider> SAL_CALL
132 {
133  SolarMutexGuard aGuard;
134  return m_xSlaveDispatcher;
135 }
136 
138  const uno::Reference<frame::XDispatchProvider>& xNewDispatchProvider )
139 {
140  SolarMutexGuard aGuard;
141  m_xSlaveDispatcher.set(xNewDispatchProvider);
142 }
143 
144 uno::Reference<frame::XDispatchProvider> SAL_CALL
146 {
147  SolarMutexGuard aGuard;
148  return m_xMasterDispatcher;
149 }
150 
152  const uno::Reference<frame::XDispatchProvider>& xNewSupplier )
153 {
154  SolarMutexGuard aGuard;
155  m_xMasterDispatcher.set(xNewSupplier);
156 }
157 
158 // XEventListener
159 
160 void SAL_CALL ScDispatchProviderInterceptor::disposing( const lang::EventObject& /* Source */ )
161 {
162  SolarMutexGuard aGuard;
163 
164  if (m_xIntercepted.is())
165  {
166  m_xIntercepted->releaseDispatchProviderInterceptor(
167  static_cast<frame::XDispatchProviderInterceptor*>(this));
168  uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
169  if (xInterceptedComponent.is())
170  xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
171 
172  m_xMyDispatch = nullptr;
173  }
174  m_xIntercepted = nullptr;
175 }
176 
178  pViewShell( pViewSh ),
179  bListeningToView( false )
180 {
181  if (pViewShell)
183 }
184 
186 {
187  if (pViewShell)
189 
191  {
192  uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
193  if ( xSupplier.is() )
194  xSupplier->removeSelectionChangeListener(this);
195  }
196 }
197 
199 {
200  if ( rHint.GetId() == SfxHintId::Dying )
201  pViewShell = nullptr;
202 }
203 
204 // XDispatch
205 
206 void SAL_CALL ScDispatch::dispatch( const util::URL& aURL,
207  const uno::Sequence<beans::PropertyValue>& aArgs )
208 {
209  SolarMutexGuard aGuard;
210 
211  bool bDone = false;
212  if ( pViewShell && aURL.Complete == cURLInsertColumns )
213  {
214  ScViewData& rViewData = pViewShell->GetViewData();
215  ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
216 
217  ScDBDocFunc aFunc( *rViewData.GetDocShell() );
218  aFunc.DoImportUno( aPos, aArgs );
219  bDone = true;
220  }
221  // cURLDocDataSource is never dispatched
222 
223  if (!bDone)
224  throw uno::RuntimeException();
225 }
226 
227 static void lcl_FillDataSource( frame::FeatureStateEvent& rEvent, const ScImportParam& rParam )
228 {
229  rEvent.IsEnabled = rParam.bImport;
230 
231  svx::ODataAccessDescriptor aDescriptor;
232  if ( rParam.bImport )
233  {
234  sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
235  ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
237 
238  aDescriptor.setDataSource(rParam.aDBName);
241  }
242  else
243  {
244  // descriptor has to be complete anyway
245 
246  aDescriptor[svx::DataAccessDescriptorProperty::DataSource] <<= OUString();
247  aDescriptor[svx::DataAccessDescriptorProperty::Command] <<= OUString();
249  }
250  rEvent.State <<= aDescriptor.createPropertyValueSequence();
251 }
252 
254  const uno::Reference<frame::XStatusListener>& xListener,
255  const util::URL& aURL)
256 {
257  SolarMutexGuard aGuard;
258 
259  if (!pViewShell)
260  throw uno::RuntimeException();
261 
262  // initial state
263  frame::FeatureStateEvent aEvent;
264  aEvent.IsEnabled = true;
265  aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
266  aEvent.FeatureURL = aURL;
267 
268  if ( aURL.Complete == cURLDocDataSource )
269  {
270  aDataSourceListeners.emplace_back( xListener );
271 
272  if (!bListeningToView)
273  {
274  uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
275  if ( xSupplier.is() )
276  xSupplier->addSelectionChangeListener(this);
277  bListeningToView = true;
278  }
279 
280  ScDBData* pDBData = pViewShell->GetDBData(false,SC_DB_OLD);
281  if ( pDBData )
282  pDBData->GetImportParam( aLastImport );
283  lcl_FillDataSource( aEvent, aLastImport ); // modifies State, IsEnabled
284  }
286 
287  xListener->statusChanged( aEvent );
288 }
289 
291  const uno::Reference<frame::XStatusListener>& xListener,
292  const util::URL& aURL )
293 {
294  SolarMutexGuard aGuard;
295 
296  if ( aURL.Complete != cURLDocDataSource )
297  return;
298 
299  sal_uInt16 nCount = aDataSourceListeners.size();
300  for ( sal_uInt16 n=nCount; n--; )
301  {
302  uno::Reference<frame::XStatusListener>& rObj = aDataSourceListeners[n];
303  if ( rObj == xListener )
304  {
305  aDataSourceListeners.erase( aDataSourceListeners.begin() + n );
306  break;
307  }
308  }
309 
310  if ( aDataSourceListeners.empty() && pViewShell )
311  {
312  uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell ));
313  if ( xSupplier.is() )
314  xSupplier->removeSelectionChangeListener(this);
315  bListeningToView = false;
316  }
317 }
318 
319 // XSelectionChangeListener
320 
321 void SAL_CALL ScDispatch::selectionChanged( const css::lang::EventObject& /* aEvent */ )
322 {
323  // currently only called for URL cURLDocDataSource
324 
325  if ( !pViewShell )
326  return;
327 
328  ScImportParam aNewImport;
329  ScDBData* pDBData = pViewShell->GetDBData(false,SC_DB_OLD);
330  if ( pDBData )
331  pDBData->GetImportParam( aNewImport );
332 
333  // notify listeners only if data source has changed
334  if ( !(aNewImport.bImport != aLastImport.bImport ||
335  aNewImport.aDBName != aLastImport.aDBName ||
336  aNewImport.aStatement != aLastImport.aStatement ||
337  aNewImport.bSql != aLastImport.bSql ||
338  aNewImport.nType != aLastImport.nType) )
339  return;
340 
341  frame::FeatureStateEvent aEvent;
342  aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
343  aEvent.FeatureURL.Complete = cURLDocDataSource;
344 
345  lcl_FillDataSource( aEvent, aNewImport ); // modifies State, IsEnabled
346 
347  for (uno::Reference<frame::XStatusListener> & xDataSourceListener : aDataSourceListeners)
348  xDataSourceListener->statusChanged( aEvent );
349 
350  aLastImport = aNewImport;
351 }
352 
353 // XEventListener
354 
355 void SAL_CALL ScDispatch::disposing( const css::lang::EventObject& rSource )
356 {
357  uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY);
358  xSupplier->removeSelectionChangeListener(this);
359  bListeningToView = false;
360 
361  lang::EventObject aEvent;
362  aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
363  for (uno::Reference<frame::XStatusListener> & xDataSourceListener : aDataSourceListeners)
364  xDataSourceListener->disposing( aEvent );
365 
366  pViewShell = nullptr;
367 }
368 
369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxViewFrame * GetViewFrame() const
virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xControl, const css::util::URL &aURL) override
Definition: dispuno.cxx:290
virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xControl, const css::util::URL &aURL) override
Definition: dispuno.cxx:253
virtual void SAL_CALL setSlaveDispatchProvider(const css::uno::Reference< css::frame::XDispatchProvider > &xNewDispatchProvider) override
Definition: dispuno.cxx:137
ScDBData * GetDBData(bool bMarkArea=true, ScGetDBMode eMode=SC_DB_MAKE, ScGetDBSelection eSel=ScGetDBSelection::Keep)
Definition: dbfunc.cxx:80
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch(const css::util::URL &aURL, const OUString &aTargetFrameName, sal_Int32 nSearchFlags) override
XDispatchProvider.
Definition: dispuno.cxx:91
void setDataSource(const OUString &_sDataSourceNameOrLocation)
OUString aDBName
Definition: global.hxx:456
virtual void SAL_CALL selectionChanged(const css::lang::EventObject &aEvent) override
XSelectionChangeListener.
Definition: dispuno.cxx:321
ULONG m_refCount
SCROW GetCurY() const
Definition: viewdata.hxx:402
sal_Int64 n
don't create
Definition: global.hxx:396
css::uno::Reference< css::frame::XDispatchProvider > m_xMasterDispatcher
Definition: dispuno.hxx:44
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
ScDispatch(ScTabViewShell *pViewSh)
Definition: dispuno.cxx:177
virtual void SAL_CALL setMasterDispatchProvider(const css::uno::Reference< css::frame::XDispatchProvider > &xNewSupplier) override
Definition: dispuno.cxx:151
css::uno::Sequence< css::beans::PropertyValue > const & createPropertyValueSequence()
ScImportParam aLastImport
Definition: dispuno.hxx:86
SfxHintId GetId() const
std::vector< css::uno::Reference< css::frame::XStatusListener > > aDataSourceListeners
Definition: dispuno.hxx:85
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: dispuno.cxx:198
SfxFrame & GetFrame() const
int nCount
const char cURLDocDataSource[]
Definition: dispuno.cxx:37
ScViewData & GetViewData()
Definition: tabview.hxx:332
static void lcl_FillDataSource(frame::FeatureStateEvent &rEvent, const ScImportParam &rParam)
Definition: dispuno.cxx:227
OUString aStatement
Definition: global.hxx:457
virtual ~ScDispatchProviderInterceptor() override
Definition: dispuno.cxx:77
virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getSlaveDispatchProvider() override
XDispatchProviderInterceptor.
Definition: dispuno.cxx:131
ScTabViewShell * pViewShell
Definition: dispuno.hxx:37
void DoImportUno(const ScAddress &rPos, const css::uno::Sequence< css::beans::PropertyValue > &aArgs)
Definition: dbdocimp.cxx:107
void GetImportParam(ScImportParam &rImportParam) const
Definition: dbdata.cxx:466
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: dispuno.cxx:83
ScDispatchProviderInterceptor(ScTabViewShell *pViewSh)
Definition: dispuno.cxx:52
sal_uInt8 nType
Definition: global.hxx:460
virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getMasterDispatchProvider() override
Definition: dispuno.cxx:145
css::uno::Reference< css::frame::XDispatch > m_xMyDispatch
own dispatch
Definition: dispuno.hxx:47
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
XEventListener.
Definition: dispuno.cxx:355
css::uno::Reference< css::frame::XController > GetController() const
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:401
css::uno::Reference< css::frame::XDispatchProviderInterception > m_xIntercepted
the component which's dispatches we're intercepting
Definition: dispuno.hxx:40
const char cURLInsertColumns[]
Definition: dispuno.cxx:36
bool bImport
Definition: global.hxx:455
ScTabViewShell * pViewShell
Definition: dispuno.hxx:83
virtual void SAL_CALL dispatch(const css::util::URL &aURL, const css::uno::Sequence< css::beans::PropertyValue > &aArgs) override
XDispatch.
Definition: dispuno.cxx:206
css::uno::Reference< css::frame::XDispatchProvider > m_xSlaveDispatcher
chaining
Definition: dispuno.hxx:43
static uno::Reference< view::XSelectionSupplier > lcl_GetSelectionSupplier(const SfxViewShell *pViewShell)
Definition: dispuno.cxx:39
bool bListeningToView
Definition: dispuno.hxx:87
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
XEventListener.
Definition: dispuno.cxx:160
virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches(const css::uno::Sequence< css::frame::DispatchDescriptor > &aDescripts) override
Definition: dispuno.cxx:116
AnyEventRef aEvent
virtual ~ScDispatch() override
Definition: dispuno.cxx:185
SCCOL GetCurX() const
Definition: viewdata.hxx:401