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