LibreOffice Module sw (master)  1
unodispatch.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 <config_features.h>
21 #include <config_fuzzers.h>
22 
23 #include <com/sun/star/frame/XFrame.hpp>
24 #include <com/sun/star/view/XSelectionSupplier.hpp>
25 
26 #include <sfx2/viewfrm.hxx>
27 #include <sfx2/dispatch.hxx>
30 #include <osl/diagnose.h>
31 #include <unodispatch.hxx>
32 #include <view.hxx>
33 #include <cmdid.h>
34 #include <wrtsh.hxx>
35 #include <dbmgr.hxx>
36 
37 using namespace ::com::sun::star;
38 
39 const char cURLFormLetter[] = ".uno:DataSourceBrowser/FormLetter";
40 const char cURLInsertContent[] = ".uno:DataSourceBrowser/InsertContent";//data into fields
41 const char cURLInsertColumns[] = ".uno:DataSourceBrowser/InsertColumns";//data into text
42 const char cURLDocumentDataSource[] = ".uno:DataSourceBrowser/DocumentDataSource";//current data source of the document
43 const char cInternalDBChangeNotification[] = ".uno::Writer/DataSourceChanged";
44 
46  m_pView(&rVw)
47 {
48  uno::Reference< frame::XFrame> xUnoFrame = m_pView->GetViewFrame()->GetFrame().GetFrameInterface();
49  m_xIntercepted.set(xUnoFrame, uno::UNO_QUERY);
50  if(m_xIntercepted.is())
51  {
52  osl_atomic_increment(&m_refCount);
53  m_xIntercepted->registerDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this));
54  // this should make us the top-level dispatch-provider for the component, via a call to our
55  // setDispatchProvider we should have got a fallback for requests we (i.e. our master) cannot fulfill
56  uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
57  if (xInterceptedComponent.is())
58  xInterceptedComponent->addEventListener(static_cast<lang::XEventListener*>(this));
59  osl_atomic_decrement(&m_refCount);
60  }
61 }
62 
64 {
65 }
66 
67 uno::Reference< frame::XDispatch > SwXDispatchProviderInterceptor::queryDispatch(
68  const util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags )
69 {
71  uno::Reference< frame::XDispatch> xResult;
72  // create some dispatch ...
73  if(m_pView && aURL.Complete.startsWith(".uno:DataSourceBrowser/"))
74  {
75  if(aURL.Complete == cURLFormLetter ||
76  aURL.Complete == cURLInsertContent ||
77  aURL.Complete == cURLInsertColumns ||
78  aURL.Complete == cURLDocumentDataSource)
79  {
80  if(!m_xDispatch.is())
82  xResult = m_xDispatch;
83  }
84  }
85 
86  // ask our slave provider
87  if (!xResult.is() && m_xSlaveDispatcher.is())
88  xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
89 
90  return xResult;
91 }
92 
93 uno::Sequence<OUString> SAL_CALL SwXDispatchProviderInterceptor::getInterceptedURLs()
94 {
95  uno::Sequence<OUString> aRet =
96  {
97  OUString(".uno:DataSourceBrowser/*")
98  };
99 
100  return aRet;
101 }
102 
103 uno::Sequence< uno::Reference< frame::XDispatch > > SwXDispatchProviderInterceptor::queryDispatches(
104  const uno::Sequence< frame::DispatchDescriptor >& aDescripts )
105 {
107  uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength());
108  std::transform(aDescripts.begin(), aDescripts.end(), aReturn.begin(),
109  [this](const frame::DispatchDescriptor& rDescr) -> uno::Reference<frame::XDispatch> {
110  return queryDispatch(rDescr.FeatureURL, rDescr.FrameName, rDescr.SearchFlags); });
111  return aReturn;
112 }
113 
114 uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getSlaveDispatchProvider( )
115 {
117  return m_xSlaveDispatcher;
118 }
119 
121  const uno::Reference< frame::XDispatchProvider >& xNewDispatchProvider )
122 {
124  m_xSlaveDispatcher = xNewDispatchProvider;
125 }
126 
127 uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getMasterDispatchProvider( )
128 {
130  return m_xMasterDispatcher;
131 }
132 
134  const uno::Reference< frame::XDispatchProvider >& xNewSupplier )
135 {
137  m_xMasterDispatcher = xNewSupplier;
138 }
139 
140 void SwXDispatchProviderInterceptor::disposing( const lang::EventObject& )
141 {
143  if (m_xIntercepted.is())
144  {
145  m_xIntercepted->releaseDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this));
146  uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
147  if (xInterceptedComponent.is())
148  xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
149  m_xDispatch = nullptr;
150  }
151  m_xIntercepted = nullptr;
152 }
153 
154 const uno::Sequence< sal_Int8 > & SwXDispatchProviderInterceptor::getUnoTunnelId()
155 {
156  static const comphelper::UnoIdInit theSwXDispatchProviderInterceptorUnoTunnelId;
157  return theSwXDispatchProviderInterceptorUnoTunnelId.getSeq();
158 }
159 
161  const uno::Sequence< sal_Int8 >& aIdentifier )
162 {
163  return comphelper::getSomethingImpl(aIdentifier, this);
164 }
165 
167 {
169  if (m_xIntercepted.is())
170  {
171  m_xIntercepted->releaseDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this));
172  uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
173  if (xInterceptedComponent.is())
174  xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
175  m_xDispatch = nullptr;
176  }
177  m_xIntercepted = nullptr;
178  m_pView = nullptr;
179 }
180 
182  m_pView(&rVw),
183  m_bOldEnable(false),
184  m_bListenerAdded(false)
185 {
186 }
187 
189 {
191  {
192  uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
193  uno::Reference<view::XSelectionChangeListener> xThis = this;
194  xSupplier->removeSelectionChangeListener(xThis);
195  }
196 }
197 
198 void SwXDispatch::dispatch(const util::URL& aURL,
199  const uno::Sequence< beans::PropertyValue >& aArgs)
200 {
201  if(!m_pView)
202  throw uno::RuntimeException();
203 #if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
204  (void) aArgs;
205  if (false)
206  {
207  }
208 #else
209  SwWrtShell& rSh = m_pView->GetWrtShell();
210  SwDBManager* pDBManager = rSh.GetDBManager();
211  if(aURL.Complete == cURLInsertContent)
212  {
213  svx::ODataAccessDescriptor aDescriptor(aArgs);
214  SwMergeDescriptor aMergeDesc( DBMGR_MERGE, rSh, aDescriptor );
215  pDBManager->Merge(aMergeDesc);
216  }
217  else if(aURL.Complete == cURLInsertColumns)
218  {
219  SwDBManager::InsertText(rSh, aArgs);
220  }
221  else if(aURL.Complete == cURLFormLetter)
222  {
223  SfxUnoAnyItem aDBProperties(FN_PARAM_DATABASE_PROPERTIES, uno::makeAny(aArgs));
226  SfxCallMode::ASYNCHRON,
227  { &aDBProperties });
228  }
229 #endif
230  else if(aURL.Complete == cURLDocumentDataSource)
231  {
232  OSL_FAIL("SwXDispatch::dispatch: this URL is not to be dispatched!");
233  }
234  else if(aURL.Complete == cInternalDBChangeNotification)
235  {
236  frame::FeatureStateEvent aEvent;
237  aEvent.Source = *static_cast<cppu::OWeakObject*>(this);
238 
240  svx::ODataAccessDescriptor aDescriptor;
241  aDescriptor.setDataSource(rData.sDataSource);
244 
245  aEvent.State <<= aDescriptor.createPropertyValueSequence();
246  aEvent.IsEnabled = !rData.sDataSource.isEmpty();
247 
248  // calls to statusChanged may call addStatusListener or removeStatusListener
249  // so copy m_aStatusListenerVector on stack
250  auto copyStatusListenerVector = m_aStatusListenerVector;
251  for (auto & status : copyStatusListenerVector)
252  {
253  if(status.aURL.Complete == cURLDocumentDataSource)
254  {
255  aEvent.FeatureURL = status.aURL;
256  status.xListener->statusChanged( aEvent );
257  }
258  }
259  }
260  else
261  throw uno::RuntimeException();
262 
263 }
264 
266  const uno::Reference< frame::XStatusListener >& xControl, const util::URL& aURL )
267 {
268  if(!m_pView)
269  throw uno::RuntimeException();
271  bool bEnable = ShellMode::Text == eMode ||
272  ShellMode::ListText == eMode ||
273  ShellMode::TableText == eMode ||
274  ShellMode::TableListText == eMode;
275 
276  m_bOldEnable = bEnable;
277  frame::FeatureStateEvent aEvent;
278  aEvent.IsEnabled = bEnable;
279  aEvent.Source = *static_cast<cppu::OWeakObject*>(this);
280  aEvent.FeatureURL = aURL;
281 
282  // one of the URLs requires a special state...
283  if (aURL.Complete == cURLDocumentDataSource)
284  {
286 
287  svx::ODataAccessDescriptor aDescriptor;
288  aDescriptor.setDataSource(rData.sDataSource);
291 
292  aEvent.State <<= aDescriptor.createPropertyValueSequence();
293  aEvent.IsEnabled = !rData.sDataSource.isEmpty();
294  }
295 
296  xControl->statusChanged( aEvent );
297 
298  StatusStruct_Impl aStatus;
299  aStatus.xListener = xControl;
300  aStatus.aURL = aURL;
301  m_aStatusListenerVector.emplace_back(aStatus);
302 
303  if(!m_bListenerAdded)
304  {
305  uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
306  uno::Reference<view::XSelectionChangeListener> xThis = this;
307  xSupplier->addSelectionChangeListener(xThis);
308  m_bListenerAdded = true;
309  }
310 }
311 
313  const uno::Reference< frame::XStatusListener >& xControl, const util::URL& )
314 {
316  std::remove_if(m_aStatusListenerVector.begin(), m_aStatusListenerVector.end(),
317  [&](const StatusStruct_Impl& status) { return status.xListener.get() == xControl.get(); }),
319  if(m_aStatusListenerVector.empty() && m_pView)
320  {
321  uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
322  uno::Reference<view::XSelectionChangeListener> xThis = this;
323  xSupplier->removeSelectionChangeListener(xThis);
324  m_bListenerAdded = false;
325  }
326 }
327 
328 void SwXDispatch::selectionChanged( const lang::EventObject& )
329 {
331  bool bEnable = ShellMode::Text == eMode ||
332  ShellMode::ListText == eMode ||
333  ShellMode::TableText == eMode ||
334  ShellMode::TableListText == eMode;
335  if(bEnable == m_bOldEnable)
336  return;
337 
338  m_bOldEnable = bEnable;
339  frame::FeatureStateEvent aEvent;
340  aEvent.IsEnabled = bEnable;
341  aEvent.Source = *static_cast<cppu::OWeakObject*>(this);
342 
343  // calls to statusChanged may call addStatusListener or removeStatusListener
344  // so copy m_aStatusListenerVector on stack
345  auto copyStatusListenerVector = m_aStatusListenerVector;
346  for (auto & status : copyStatusListenerVector)
347  {
348  aEvent.FeatureURL = status.aURL;
349  if (status.aURL.Complete != cURLDocumentDataSource)
350  // the document's data source does not depend on the selection, so it's state does not change here
351  status.xListener->statusChanged( aEvent );
352  }
353 }
354 
355 void SwXDispatch::disposing( const lang::EventObject& rSource )
356 {
357  uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY);
358  uno::Reference<view::XSelectionChangeListener> xThis = this;
359  xSupplier->removeSelectionChangeListener(xThis);
360  m_bListenerAdded = false;
361 
362  lang::EventObject aObject;
363  aObject.Source = static_cast<cppu::OWeakObject*>(this);
364  // calls to statusChanged may call addStatusListener or removeStatusListener
365  // so copy m_aStatusListenerVector on stack
366  auto copyStatusListenerVector = m_aStatusListenerVector;
367  for (auto & status : copyStatusListenerVector)
368  {
369  status.xListener->disposing(aObject);
370  }
371  m_pView = nullptr;
372 }
373 
375 {
377 }
378 
380 {
381 }
382 
384 {
385 }
386 
387 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const char cURLInsertContent[]
Definition: unodispatch.cxx:40
SfxViewFrame * GetViewFrame() const
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
exports com.sun.star.frame. status
sal_Int32 nCommandType
Definition: swdbdata.hxx:32
const char cURLDocumentDataSource[]
Definition: unodispatch.cxx:42
void setDataSource(const OUString &_sDataSourceNameOrLocation)
SwXDispatch(SwView &rView)
virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getSlaveDispatchProvider() override
css::uno::Reference< css::frame::XDispatch > m_xDispatch
Definition: unodispatch.hxx:61
ULONG m_refCount
SfxDispatcher * GetDispatcher()
virtual ~SwXDispatchProviderInterceptor() override
Definition: unodispatch.cxx:63
OUString sDataSource
Definition: swdbdata.hxx:30
css::uno::Reference< css::frame::XDispatchProviderInterception > m_xIntercepted
Definition: unodispatch.hxx:55
const ContentProperties & rData
virtual void SAL_CALL setSlaveDispatchProvider(const css::uno::Reference< css::frame::XDispatchProvider > &xNewDispatchProvider) override
Data records in fields.
Definition: dbmgr.hxx:88
css::uno::Sequence< css::beans::PropertyValue > const & createPropertyValueSequence()
static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId()
SwWrtShell & GetWrtShell() const
Definition: view.hxx:413
#define FN_PARAM_DATABASE_PROPERTIES
Definition: cmdid.h:821
css::uno::Reference< css::frame::XStatusListener > xListener
Definition: unodispatch.hxx:95
Used by the UI to modify the document model.
Definition: wrtsh.hxx:93
virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches(const css::uno::Sequence< css::frame::DispatchDescriptor > &aDescripts) override
SfxFrame & GetFrame() const
Mode eMode
ShellMode
Definition: view.hxx:85
std::vector< StatusStruct_Impl > m_aStatusListenerVector
const char cURLInsertColumns[]
Definition: unodispatch.cxx:41
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
css::uno::Reference< css::frame::XDispatchProvider > m_xMasterDispatcher
Definition: unodispatch.hxx:59
const css::uno::Sequence< sal_Int8 > & getSeq() const
bool Merge(const SwMergeDescriptor &rMergeDesc)
Merging of data records into fields.
Definition: dbmgr.cxx:416
SwDBManager * GetDBManager() const
For evaluation of DB fields (new DB-manager).
Definition: edfld.cxx:327
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
css::util::URL aURL
Definition: unodispatch.hxx:96
static const char * GetDBChangeURL()
Mutex aLock
virtual css::uno::Sequence< OUString > SAL_CALL getInterceptedURLs() override
Definition: unodispatch.cxx:93
bool m_bListenerAdded
const char cInternalDBChangeNotification[]
Definition: unodispatch.cxx:43
virtual ~SwXDispatch() override
static void InsertText(SwWrtShell &rSh, const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Definition: dbmgr.cxx:3018
SwDBData const & GetDBData() const
Database information.
Definition: edfld.cxx:290
virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch(const css::util::URL &aURL, const OUString &aTargetFrameName, sal_Int32 nSearchFlags) override
Definition: unodispatch.cxx:67
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
virtual void SAL_CALL dispatch(const css::util::URL &aURL, const css::uno::Sequence< css::beans::PropertyValue > &aArgs) override
virtual void SAL_CALL setMasterDispatchProvider(const css::uno::Reference< css::frame::XDispatchProvider > &xNewSupplier) override
virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xControl, const css::util::URL &aURL) override
SwXDispatchProviderInterceptor(SwView &rView)
Definition: unodispatch.cxx:45
css::uno::Reference< css::frame::XDispatchProvider > m_xSlaveDispatcher
Definition: unodispatch.hxx:58
sal_Int64 getSomethingImpl(const css::uno::Sequence< sal_Int8 > &rId, T *pThis, FallbackToGetSomethingOf< Base >={})
virtual void SAL_CALL selectionChanged(const css::lang::EventObject &aEvent) override
virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 > &aIdentifier) override
const char cURLFormLetter[]
Definition: unodispatch.cxx:39
css::view::XSelectionSupplier * GetUNOObject()
Definition: view0.cxx:111
SwView * m_pView
virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xControl, const css::util::URL &aURL) override
ShellMode GetShellMode() const
Definition: view0.cxx:106
OUString sCommand
Definition: swdbdata.hxx:31
virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getMasterDispatchProvider() override
#define FN_MAILMERGE_WIZARD
Definition: cmdid.h:228
AnyEventRef aEvent
Definition: view.hxx:144
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo