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