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