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  {
231  ListBoxEntrySet aEmpty;
232  m_aSelectedEntries.swap( aEmpty );
233 
234  for (const css::uno::Sequence<sal_uInt32>& rPaths : std::as_const(m_aControlPaths))
235  {
236  std::unique_ptr<weld::TreeIter> xSearch(pTreeBox->make_iterator(pRoot));
237  for (const sal_uInt32 nThisPath : rPaths)
238  pTreeBox->iter_nth_child(*xSearch, nThisPath);
239  m_aSelectedEntries.emplace(std::move(xSearch));
240  }
241  }
242 
244  {
245  }
246 
247  bool OControlExchange::GetData( const DataFlavor& _rFlavor, const OUString& rDestDoc )
248  {
249  const SotClipboardFormatId nFormatId = SotExchange::GetFormat( _rFlavor );
250 
251  if ( getControlPathFormatId( ) == nFormatId )
252  {
253  // ugly. We have to pack all the info into one object
254  Sequence< Any > aCompleteInfo( 2 );
255  OSL_ENSURE( m_xFormsRoot.is(), "OLocalExchange::GetData: invalid forms root for this format!" );
256  aCompleteInfo.getArray()[ 0 ] <<= m_xFormsRoot;
257  aCompleteInfo.getArray()[ 1 ] <<= m_aControlPaths;
258 
259  SetAny( makeAny( aCompleteInfo ) );
260  }
261  else if ( getHiddenControlModelsFormatId() == nFormatId )
262  {
263  // just need to transfer the models
264  SetAny( makeAny( m_aHiddenControlModels ) );
265  }
266  else
267  return OLocalExchange::GetData(_rFlavor, rDestDoc);
268 
269  return true;
270  }
271 
273  {
274  if (m_bFocusEntry && !m_aSelectedEntries.empty())
275  AddFormat(getFieldExchangeFormatId());
276 
277  if (m_aControlPaths.hasElements())
278  AddFormat(getControlPathFormatId());
279 
280  if (m_aHiddenControlModels.hasElements())
281  AddFormat(getHiddenControlModelsFormatId());
282  }
283 
285  {
286  static SotClipboardFormatId s_nFormat =
287  SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"svxform.ControlPathExchange\"");
288  DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OControlExchange::getControlPathFormatId: bad exchange id!");
289  return s_nFormat;
290  }
291 
293  {
294  static SotClipboardFormatId s_nFormat =
295  SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"svxform.HiddenControlModelsExchange\"");
296  DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OControlExchange::getHiddenControlModelsFormatId: bad exchange id!");
297  return s_nFormat;
298  }
299 
300 
302  {
303  static SotClipboardFormatId s_nFormat =
304  SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"svxform.FieldNameExchange\"");
305  DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OControlExchange::getFieldExchangeFormatId: bad exchange id!");
306  return s_nFormat;
307  }
308 
309  //= OControlExchangeHelper
311  {
312  return new OControlExchange;
313  }
314 
315  OLocalExchangeHelper::OLocalExchangeHelper()
316  {
317  }
318 
319  OLocalExchangeHelper::~OLocalExchangeHelper()
320  {
321  implReset();
322  }
323 
324  void OLocalExchangeHelper::copyToClipboard( ) const
325  {
326  DBG_ASSERT( m_xTransferable.is(), "OLocalExchangeHelper::copyToClipboard: not prepared!" );
327  m_xTransferable->copyToClipboard(OLocalExchange::GrantAccess());
328  }
329 
330  void OLocalExchangeHelper::implReset()
331  {
332  if (m_xTransferable.is())
333  {
334  m_xTransferable->setClipboardListener( Link<OLocalExchange&,void>() );
335  m_xTransferable.clear();
336  }
337  }
338 
339  void OLocalExchangeHelper::prepareDrag( )
340  {
341  DBG_ASSERT(!m_xTransferable.is() || !m_xTransferable->isDragging(), "OLocalExchangeHelper::prepareDrag: recursive DnD?");
342 
343  implReset();
344  m_xTransferable = createExchange();
345  }
346 }
347 
348 /* 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:272
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:292
virtual bool iter_parent(TreeIter &rIter) const =0
::std::set< std::unique_ptr< weld::TreeIter > > ListBoxEntrySet
Definition: fmexch.hxx:39
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:122
virtual bool GetData(const css::datatransfer::DataFlavor &rFlavor, const OUString &rDestDoc) override
Definition: fmexch.cxx:247
css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > m_aHiddenControlModels
Definition: fmexch.hxx:124
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:301
virtual OLocalExchange * createExchange() const override
Definition: fmexch.cxx:310
#define DBG_UNHANDLED_EXCEPTION(...)
ListBoxEntrySet m_aSelectedEntries
Definition: fmexch.hxx:120
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:233
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:228
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:284
css::uno::Reference< css::form::XForms > m_xFormsRoot
Definition: fmexch.hxx:127
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:117