LibreOffice Module svx (master)  1
fmexch.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 <fmexch.hxx>
21 
22 #include <sot/formats.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/diagnose_ex.h>
25 
26 namespace svxform
27 {
28  using namespace ::com::sun::star::uno;
29  using namespace ::com::sun::star::datatransfer;
30 
31  OLocalExchange::OLocalExchange( )
32  :m_bDragging( false )
33  ,m_bClipboardOwner( false )
34  {
35  }
36 
37  void OLocalExchange::copyToClipboard(const GrantAccess&)
38  {
39  if ( m_bClipboardOwner )
40  { // simulate a lostOwnership to notify parties interested in
41  m_aClipboardListener.Call( *this );
42  }
43 
44  m_bClipboardOwner = true;
45  CopyToClipboard(GetSystemClipboard());
46  }
47 
48  void OLocalExchange::clear()
49  {
50  if ( !isClipboardOwner() )
51  return;
52 
53  try
54  {
55  Reference< clipboard::XClipboard > xClipBoard( getOwnClipboard() );
56  if ( xClipBoard.is() )
57  xClipBoard->setContents( nullptr, nullptr );
58  }
59  catch( const Exception& )
60  {
62  }
63  m_bClipboardOwner = false;
64  }
65 
66  void SAL_CALL OLocalExchange::lostOwnership( const Reference< clipboard::XClipboard >& _rxClipboard, const Reference< XTransferable >& _rxTrans )
67  {
68  TransferDataContainer::implCallOwnLostOwnership( _rxClipboard, _rxTrans );
69  m_bClipboardOwner = false;
70 
71  m_aClipboardListener.Call( *this );
72  }
73 
74  void OLocalExchange::setDragging(bool bDragging)
75  {
76  m_bDragging = bDragging;
77  }
78 
79  void OLocalExchange::DragFinished( sal_Int8 nDropAction )
80  {
82  setDragging(false);
83  }
84 
85  bool OLocalExchange::hasFormat( const DataFlavorExVector& _rFormats, SotClipboardFormatId _nFormatId )
86  {
87  return std::any_of(_rFormats.begin(), _rFormats.end(),
88  [&_nFormatId](const DataFlavorEx& rFormat) { return rFormat.mnSotId == _nFormatId; });
89  }
90 
91  bool OLocalExchange::GetData( const css::datatransfer::DataFlavor& /*_rFlavor*/, const OUString& /*rDestDoc*/ )
92  {
93  return false; // do not have any formats by default
94  }
95 
96  OControlTransferData::OControlTransferData( )
97  : m_bFocusEntry(false)
98  {
99  }
100 
101  OControlTransferData::OControlTransferData( const Reference< XTransferable >& _rxTransferable )
102  : m_bFocusEntry(false)
103  {
104  TransferableDataHelper aExchangedData( _rxTransferable );
105 
106  // try the formats we know
107  if ( OControlExchange::hasControlPathFormat( aExchangedData.GetDataFlavorExVector() ) )
108  { // paths to the controls, relative to a root
109  Sequence< Any > aControlPathData;
110  if ( aExchangedData.GetAny(OControlExchange::getControlPathFormatId(), OUString()) >>= aControlPathData )
111  {
112  DBG_ASSERT( aControlPathData.getLength() >= 2, "OControlTransferData::OControlTransferData: invalid data for the control path format!" );
113  if ( aControlPathData.getLength() >= 2 )
114  {
115  aControlPathData[0] >>= m_xFormsRoot;
116  aControlPathData[1] >>= m_aControlPaths;
117  }
118  }
119  else
120  {
121  OSL_FAIL( "OControlTransferData::OControlTransferData: invalid data for the control path format (2)!" );
122  }
123  }
124  if ( OControlExchange::hasHiddenControlModelsFormat( aExchangedData.GetDataFlavorExVector() ) )
125  { // sequence of models of hidden controls
126  aExchangedData.GetAny(OControlExchange::getHiddenControlModelsFormatId(), OUString()) >>= m_aHiddenControlModels;
127  }
128 
129  updateFormats( );
130  }
131 
132 
134  {
135  _rFlavor.mnSotId = nId;
136  return SotExchange::GetFormatDataFlavor( _rFlavor.mnSotId, _rFlavor );
137  }
138 
139 
141  {
142  m_aCurrentFormats.clear();
143  m_aCurrentFormats.reserve( 3 );
144 
145  DataFlavorEx aFlavor;
146 
147  if ( m_aHiddenControlModels.hasElements() )
148  {
150  m_aCurrentFormats.push_back( aFlavor );
151  }
152 
153  if ( m_xFormsRoot.is() && m_aControlPaths.hasElements() )
154  {
156  m_aCurrentFormats.push_back( aFlavor );
157  }
158 
159  if ( !m_aSelectedEntries.empty() )
160  {
162  m_aCurrentFormats.push_back( aFlavor );
163  }
164  }
165 
167  {
168  auto aIter = std::find_if(m_aSelectedEntries.begin(), m_aSelectedEntries.end(),
169  [pView, _pEntry](const auto& rElem) {
170  return pView->iter_compare(*rElem, *_pEntry) == 0;
171  });
172  if (aIter != m_aSelectedEntries.end())
173  m_aSelectedEntries.erase(aIter);
174 
175  return m_aSelectedEntries.size();
176  }
177 
178  void OControlTransferData::addSelectedEntry(std::unique_ptr<weld::TreeIter> xEntry)
179  {
180  m_aSelectedEntries.emplace(std::move(xEntry));
181  }
182 
183  void OControlTransferData::setFocusEntry(bool _bFocusEntry)
184  {
185  m_bFocusEntry = _bFocusEntry;
186  }
187 
188  void OControlTransferData::addHiddenControlsFormat(const css::uno::Sequence< css::uno::Reference< css::uno::XInterface > >& seqInterfaces)
189  {
190  m_aHiddenControlModels = seqInterfaces;
191  }
192 
194  {
195  m_aControlPaths.realloc(0);
196 
197  sal_Int32 nEntryCount = m_aSelectedEntries.size();
198  if (nEntryCount == 0)
199  return;
200 
201  m_aControlPaths.realloc(nEntryCount);
202  css::uno::Sequence<sal_uInt32>* pAllPaths = m_aControlPaths.getArray();
203  for (const auto& rCurrentEntry : m_aSelectedEntries)
204  {
205  // first we collect the path in an array
206  ::std::vector< sal_uInt32 > aCurrentPath;
207 
208  std::unique_ptr<weld::TreeIter> xLoop(pTreeBox->make_iterator(rCurrentEntry.get()));
209  while (pTreeBox->iter_compare(*xLoop, *pRoot) != 0)
210  {
211  aCurrentPath.push_back(pTreeBox->get_iter_index_in_parent(*xLoop));
212  bool bLoop = pTreeBox->iter_parent(*xLoop);
213  assert(bLoop && "OControlTransferData::buildPathFormat: invalid root or entry !"); (void)bLoop;
214  }
215 
216  // then we can transfer it into css::uno::Sequence
217  Sequence<sal_uInt32>& rCurrentPath = *pAllPaths;
218  sal_Int32 nDepth = aCurrentPath.size();
219 
220  rCurrentPath.realloc(nDepth);
221  sal_uInt32* pSeq = rCurrentPath.getArray();
222  sal_Int32 j,k;
223  for (j = nDepth - 1, k = 0; k<nDepth; --j, ++k)
224  pSeq[j] = aCurrentPath[k];
225  ++pAllPaths;
226  }
227  }
228 
230  {
232 
233  for (const css::uno::Sequence<sal_uInt32>& rPaths : std::as_const(m_aControlPaths))
234  {
235  std::unique_ptr<weld::TreeIter> xSearch(pTreeBox->make_iterator(pRoot));
236  for (const sal_uInt32 nThisPath : rPaths)
237  pTreeBox->iter_nth_child(*xSearch, nThisPath);
238  m_aSelectedEntries.emplace(std::move(xSearch));
239  }
240  }
241 
243  {
244  }
245 
246  bool OControlExchange::GetData( const DataFlavor& _rFlavor, const OUString& rDestDoc )
247  {
248  const SotClipboardFormatId nFormatId = SotExchange::GetFormat( _rFlavor );
249 
250  if ( getControlPathFormatId( ) == nFormatId )
251  {
252  // ugly. We have to pack all the info into one object
253  Sequence< Any > aCompleteInfo( 2 );
254  OSL_ENSURE( m_xFormsRoot.is(), "OLocalExchange::GetData: invalid forms root for this format!" );
255  aCompleteInfo.getArray()[ 0 ] <<= m_xFormsRoot;
256  aCompleteInfo.getArray()[ 1 ] <<= m_aControlPaths;
257 
258  SetAny( makeAny( aCompleteInfo ) );
259  }
260  else if ( getHiddenControlModelsFormatId() == nFormatId )
261  {
262  // just need to transfer the models
263  SetAny( makeAny( m_aHiddenControlModels ) );
264  }
265  else
266  return OLocalExchange::GetData(_rFlavor, rDestDoc);
267 
268  return true;
269  }
270 
272  {
273  if (m_bFocusEntry && !m_aSelectedEntries.empty())
274  AddFormat(getFieldExchangeFormatId());
275 
276  if (m_aControlPaths.hasElements())
277  AddFormat(getControlPathFormatId());
278 
279  if (m_aHiddenControlModels.hasElements())
280  AddFormat(getHiddenControlModelsFormatId());
281  }
282 
284  {
285  static SotClipboardFormatId s_nFormat =
286  SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"svxform.ControlPathExchange\"");
287  DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OControlExchange::getControlPathFormatId: bad exchange id!");
288  return s_nFormat;
289  }
290 
292  {
293  static SotClipboardFormatId s_nFormat =
294  SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"svxform.HiddenControlModelsExchange\"");
295  DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OControlExchange::getHiddenControlModelsFormatId: bad exchange id!");
296  return s_nFormat;
297  }
298 
299 
301  {
302  static SotClipboardFormatId s_nFormat =
303  SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"svxform.FieldNameExchange\"");
304  DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OControlExchange::getFieldExchangeFormatId: bad exchange id!");
305  return s_nFormat;
306  }
307 
308  //= OControlExchangeHelper
310  {
311  return new OControlExchange;
312  }
313 
314  OLocalExchangeHelper::OLocalExchangeHelper()
315  {
316  }
317 
318  OLocalExchangeHelper::~OLocalExchangeHelper()
319  {
320  implReset();
321  }
322 
323  void OLocalExchangeHelper::copyToClipboard( ) const
324  {
325  DBG_ASSERT( m_xTransferable.is(), "OLocalExchangeHelper::copyToClipboard: not prepared!" );
326  m_xTransferable->copyToClipboard(OLocalExchange::GrantAccess());
327  }
328 
329  void OLocalExchangeHelper::implReset()
330  {
331  if (m_xTransferable.is())
332  {
333  m_xTransferable->setClipboardListener( Link<OLocalExchange&,void>() );
334  m_xTransferable.clear();
335  }
336  }
337 
338  void OLocalExchangeHelper::prepareDrag( )
339  {
340  DBG_ASSERT(!m_xTransferable.is() || !m_xTransferable->isDragging(), "OLocalExchangeHelper::prepareDrag: recursive DnD?");
341 
342  implReset();
343  m_xTransferable = createExchange();
344  }
345 }
346 
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual int get_iter_index_in_parent(const TreeIter &rIter) const =0
virtual void AddSupportedFormats() override
Definition: fmexch.cxx:271
static SotClipboardFormatId RegisterFormatName(const OUString &rName)
size_t onEntryRemoved(const weld::TreeView *pView, const weld::TreeIter *_pEntry)
notifies the data transfer object that a certain entry has been removed from the owning tree ...
Definition: fmexch.cxx:166
static SotClipboardFormatId getHiddenControlModelsFormatId()
Definition: fmexch.cxx:291
virtual bool iter_parent(TreeIter &rIter) const =0
::std::set< std::unique_ptr< weld::TreeIter > > ListBoxEntrySet
Definition: fmexch.hxx:38
signed char sal_Int8
::std::vector< DataFlavorEx > DataFlavorExVector
virtual void DragFinished(sal_Int8 nDropAction) override
css::uno::Reference< css::datatransfer::clipboard::XClipboard > VCL_DLLPUBLIC GetSystemClipboard()
css::uno::Sequence< css::uno::Sequence< sal_uInt32 > > m_aControlPaths
Definition: fmexch.hxx:121
virtual bool GetData(const css::datatransfer::DataFlavor &rFlavor, const OUString &rDestDoc) override
Definition: fmexch.cxx:246
css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > m_aHiddenControlModels
Definition: fmexch.hxx:123
virtual std::unique_ptr< TreeIter > make_iterator(const TreeIter *pOrig=nullptr) const =0
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static bool lcl_fillDataFlavorEx(SotClipboardFormatId nId, DataFlavorEx &_rFlavor)
Definition: fmexch.cxx:133
SotClipboardFormatId
static SotClipboardFormatId getFieldExchangeFormatId()
Definition: fmexch.cxx:300
#define DBG_UNHANDLED_EXCEPTION(...)
ListBoxEntrySet m_aSelectedEntries
Definition: fmexch.hxx:119
void implCallOwnLostOwnership(const css::uno::Reference< css::datatransfer::clipboard::XClipboard > &_rxClipboard, const css::uno::Reference< css::datatransfer::XTransferable > &_rxTrans)
#define DBG_ASSERT(sCon, aError)
void addHiddenControlsFormat(const css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > &seqInterfaces)
Definition: fmexch.cxx:188
static bool hasHiddenControlModelsFormat(const DataFlavorExVector &_rFormats)
Definition: fmexch.hxx:232
void buildPathFormat(const weld::TreeView *pTreeBox, const weld::TreeIter *pRoot)
Definition: fmexch.cxx:193
static SotClipboardFormatId GetFormat(const css::datatransfer::DataFlavor &rFlavor)
bool iter_nth_child(TreeIter &rIter, int nChild) const
static bool hasControlPathFormat(const DataFlavorExVector &_rFormats)
Definition: fmexch.hxx:227
void addSelectedEntry(std::unique_ptr< weld::TreeIter > xEntry)
Definition: fmexch.cxx:178
void setFocusEntry(bool _bFocusEntry)
Definition: fmexch.cxx:183
void buildListFromPath(const weld::TreeView *pTreeBox, const weld::TreeIter *pRoot)
Definition: fmexch.cxx:229
class FmSearchEngine - Impl class for FmSearchDialog
SotClipboardFormatId mnSotId
static SotClipboardFormatId getControlPathFormatId()
Definition: fmexch.cxx:283
css::uno::Reference< css::form::XForms > m_xFormsRoot
Definition: fmexch.hxx:126
virtual rtl::Reference< OLocalExchange > createExchange() const override
Definition: fmexch.cxx:309
virtual int iter_compare(const TreeIter &a, const TreeIter &b) const =0
static bool GetFormatDataFlavor(SotClipboardFormatId nFormat, css::datatransfer::DataFlavor &rFlavor)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)
DataFlavorExVector m_aCurrentFormats
Definition: fmexch.hxx:116