LibreOffice Module sc (master)  1
charthelper.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 <charthelper.hxx>
21 #include <document.hxx>
22 #include <drwlayer.hxx>
23 #include <rangelst.hxx>
24 #include <chartlis.hxx>
25 #include <docuno.hxx>
26 
27 #include <svx/svditer.hxx>
28 #include <svx/svdoole2.hxx>
29 #include <svx/svdpage.hxx>
30 #include <svtools/embedhlp.hxx>
31 #include <tools/diagnose_ex.h>
32 
33 #include <com/sun/star/chart2/XChartDocument.hpp>
34 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
35 #include <com/sun/star/embed/XEmbeddedObject.hpp>
36 #include <com/sun/star/util/XModifiable.hpp>
37 
38 using namespace com::sun::star;
39 using ::com::sun::star::uno::Reference;
40 
41 namespace
42 {
43 
44 sal_uInt16 lcl_DoUpdateCharts( ScDocument& rDoc )
45 {
46  ScDrawLayer* pModel = rDoc.GetDrawLayer();
47  if (!pModel)
48  return 0;
49 
50  sal_uInt16 nFound = 0;
51 
52  sal_uInt16 nPageCount = pModel->GetPageCount();
53  for (sal_uInt16 nPageNo=0; nPageNo<nPageCount; nPageNo++)
54  {
55  SdrPage* pPage = pModel->GetPage(nPageNo);
56  OSL_ENSURE(pPage,"Page ?");
57 
58  SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
59  SdrObject* pObject = aIter.Next();
60  while (pObject)
61  {
62  if ( pObject->GetObjIdentifier() == OBJ_OLE2 && ScDocument::IsChart( pObject ) )
63  {
64  OUString aName = static_cast<SdrOle2Obj*>(pObject)->GetPersistName();
65  rDoc.UpdateChart( aName );
66  ++nFound;
67  }
68  pObject = aIter.Next();
69  }
70  }
71  return nFound;
72 }
73 
74 bool lcl_AdjustRanges( ScRangeList& rRanges, SCTAB nSourceTab, SCTAB nDestTab, SCTAB nTabCount )
75 {
76  //TODO: if multiple sheets are copied, update references into the other copied sheets?
77 
78  bool bChanged = false;
79 
80  for ( size_t i=0, nCount = rRanges.size(); i < nCount; i++ )
81  {
82  ScRange & rRange = rRanges[ i ];
83  if ( rRange.aStart.Tab() == nSourceTab && rRange.aEnd.Tab() == nSourceTab )
84  {
85  rRange.aStart.SetTab( nDestTab );
86  rRange.aEnd.SetTab( nDestTab );
87  bChanged = true;
88  }
89  if ( rRange.aStart.Tab() >= nTabCount )
90  {
91  rRange.aStart.SetTab( nTabCount > 0 ? ( nTabCount - 1 ) : 0 );
92  bChanged = true;
93  }
94  if ( rRange.aEnd.Tab() >= nTabCount )
95  {
96  rRange.aEnd.SetTab( nTabCount > 0 ? ( nTabCount - 1 ) : 0 );
97  bChanged = true;
98  }
99  }
100 
101  return bChanged;
102 }
103 
104 }//end anonymous namespace
105 
106 // ScChartHelper
107 //static
109 {
110  return lcl_DoUpdateCharts( rDoc );
111 }
112 
113 void ScChartHelper::AdjustRangesOfChartsOnDestinationPage( const ScDocument& rSrcDoc, ScDocument& rDestDoc, const SCTAB nSrcTab, const SCTAB nDestTab )
114 {
115  ScDrawLayer* pDrawLayer = rDestDoc.GetDrawLayer();
116  if( !pDrawLayer )
117  return;
118 
119  SdrPage* pDestPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nDestTab));
120  if( !pDestPage )
121  return;
122 
123  SdrObjListIter aIter( pDestPage, SdrIterMode::Flat );
124  SdrObject* pObject = aIter.Next();
125  while( pObject )
126  {
127  if( pObject->GetObjIdentifier() == OBJ_OLE2 && static_cast<SdrOle2Obj*>(pObject)->IsChart() )
128  {
129  OUString aChartName = static_cast<SdrOle2Obj*>(pObject)->GetPersistName();
130 
131  Reference< chart2::XChartDocument > xChartDoc( rDestDoc.GetChartByName( aChartName ) );
132  Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
133  if( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider() )
134  {
135  ::std::vector< ScRangeList > aRangesVector;
136  rDestDoc.GetChartRanges( aChartName, aRangesVector, rSrcDoc );
137 
138  for( ScRangeList& rScRangeList : aRangesVector )
139  {
140  lcl_AdjustRanges( rScRangeList, nSrcTab, nDestTab, rDestDoc.GetTableCount() );
141  }
142  rDestDoc.SetChartRanges( aChartName, aRangesVector );
143  }
144  }
145  pObject = aIter.Next();
146  }
147 }
148 
150 {
151  ScDrawLayer* pDrawLayer = rDestDoc.GetDrawLayer();
152  if( !pDrawLayer )
153  return;
154 
155  SdrPage* pDestPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nDestTab));
156  if( !pDestPage )
157  return;
158 
159  SdrObjListIter aIter( pDestPage, SdrIterMode::Flat );
160  SdrObject* pObject = aIter.Next();
161  while( pObject )
162  {
163  if( pObject->GetObjIdentifier() == OBJ_OLE2 && static_cast<SdrOle2Obj*>(pObject)->IsChart() )
164  {
165  OUString aChartName = static_cast<SdrOle2Obj*>(pObject)->GetPersistName();
166  Reference< chart2::XChartDocument > xChartDoc( rDestDoc.GetChartByName( aChartName ) );
167  Reference< util::XModifiable > xModif(xChartDoc, uno::UNO_QUERY_THROW);
168  xModif->setModified( true);
169  }
170  pObject = aIter.Next();
171  }
172 }
173 
174 uno::Reference< chart2::XChartDocument > ScChartHelper::GetChartFromSdrObject( const SdrObject* pObject )
175 {
176  uno::Reference< chart2::XChartDocument > xReturn;
177  if( pObject )
178  {
179  if( pObject->GetObjIdentifier() == OBJ_OLE2 && static_cast<const SdrOle2Obj*>(pObject)->IsChart() )
180  {
181  uno::Reference< embed::XEmbeddedObject > xIPObj = static_cast<const SdrOle2Obj*>(pObject)->GetObjRef();
182  if( xIPObj.is() )
183  {
185  uno::Reference< util::XCloseable > xComponent = xIPObj->getComponent();
186  xReturn.set( uno::Reference< chart2::XChartDocument >( xComponent, uno::UNO_QUERY ) );
187  }
188  }
189  }
190  return xReturn;
191 }
192 
193 void ScChartHelper::GetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartDoc,
194  std::vector< OUString >& rRanges )
195 {
196  rRanges.clear();
197  uno::Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
198  if( !xDataSource.is() )
199  return;
200 
201  const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledDataSequences( xDataSource->getDataSequences() );
202  rRanges.reserve(2*aLabeledDataSequences.getLength());
203  for(const uno::Reference<chart2::data::XLabeledDataSequence>& xLabeledSequence : aLabeledDataSequences)
204  {
205  if(!xLabeledSequence.is())
206  continue;
207  uno::Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel());
208  uno::Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues());
209 
210  if (xLabel.is())
211  rRanges.push_back( xLabel->getSourceRangeRepresentation() );
212  if (xValues.is())
213  rRanges.push_back( xValues->getSourceRangeRepresentation() );
214  }
215 }
216 
217 void ScChartHelper::SetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartDoc,
218  const uno::Sequence< OUString >& rRanges )
219 {
220  uno::Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
221  if( !xDataSource.is() )
222  return;
223  uno::Reference< chart2::data::XDataProvider > xDataProvider = xChartDoc->getDataProvider();
224  if( !xDataProvider.is() )
225  return;
226 
227  xChartDoc->lockControllers();
228 
229  try
230  {
231  OUString aPropertyNameRole( "Role" );
232 
233  uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledDataSequences( xDataSource->getDataSequences() );
234  sal_Int32 nRange=0;
235  for( uno::Reference<chart2::data::XLabeledDataSequence>& xLabeledSequence : aLabeledDataSequences )
236  {
237  if( nRange >= rRanges.getLength() )
238  break;
239 
240  if(!xLabeledSequence.is())
241  continue;
242  uno::Reference< beans::XPropertySet > xLabel( xLabeledSequence->getLabel(), uno::UNO_QUERY );
243  uno::Reference< beans::XPropertySet > xValues( xLabeledSequence->getValues(), uno::UNO_QUERY );
244 
245  if( xLabel.is())
246  {
247  uno::Reference< chart2::data::XDataSequence > xNewSeq(
248  xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] ));
249 
250  uno::Reference< beans::XPropertySet > xNewProps( xNewSeq, uno::UNO_QUERY );
251  if( xNewProps.is() )
252  xNewProps->setPropertyValue( aPropertyNameRole, xLabel->getPropertyValue( aPropertyNameRole ) );
253 
254  xLabeledSequence->setLabel( xNewSeq );
255  }
256 
257  if( nRange >= rRanges.getLength() )
258  break;
259 
260  if( xValues.is())
261  {
262  uno::Reference< chart2::data::XDataSequence > xNewSeq(
263  xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] ));
264 
265  uno::Reference< beans::XPropertySet > xNewProps( xNewSeq, uno::UNO_QUERY );
266  if( xNewProps.is() )
267  xNewProps->setPropertyValue( aPropertyNameRole, xValues->getPropertyValue( aPropertyNameRole ) );
268 
269  xLabeledSequence->setValues( xNewSeq );
270  }
271  }
272  }
273  catch (const uno::Exception&)
274  {
275  TOOLS_WARN_EXCEPTION( "sc", "Exception in ScChartHelper::SetChartRanges - invalid range string?");
276  }
277 
278  xChartDoc->unlockControllers();
279 }
280 
281 void ScChartHelper::AddRangesIfProtectedChart( ScRangeListVector& rRangesVector, const ScDocument& rDocument, SdrObject* pObject )
282 {
283  if ( !(pObject && ( pObject->GetObjIdentifier() == OBJ_OLE2 )) )
284  return;
285 
286  SdrOle2Obj* pSdrOle2Obj = dynamic_cast< SdrOle2Obj* >( pObject );
287  if ( !(pSdrOle2Obj && pSdrOle2Obj->IsChart()) )
288  return;
289 
290  const uno::Reference< embed::XEmbeddedObject >& xEmbeddedObj = pSdrOle2Obj->GetObjRef();
291  if ( !xEmbeddedObj.is() )
292  return;
293 
294  bool bDisableDataTableDialog = false;
295  sal_Int32 nOldState = xEmbeddedObj->getCurrentState();
297  uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
298  if ( xProps.is() &&
299  ( xProps->getPropertyValue("DisableDataTableDialog") >>= bDisableDataTableDialog ) &&
300  bDisableDataTableDialog )
301  {
302  ScChartListenerCollection* pCollection = rDocument.GetChartListenerCollection();
303  if (pCollection)
304  {
305  const OUString& aChartName = pSdrOle2Obj->GetPersistName();
306  const ScChartListener* pListener = pCollection->findByName(aChartName);
307  if (pListener)
308  {
309  const ScRangeListRef& rRangeList = pListener->GetRangeList();
310  if ( rRangeList.is() )
311  {
312  rRangesVector.push_back( *rRangeList );
313  }
314  }
315  }
316  }
317  if ( xEmbeddedObj->getCurrentState() != nOldState )
318  {
319  xEmbeddedObj->changeState( nOldState );
320  }
321 }
322 
323 void ScChartHelper::FillProtectedChartRangesVector( ScRangeListVector& rRangesVector, const ScDocument& rDocument, const SdrPage* pPage )
324 {
325  if ( pPage )
326  {
327  SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
328  SdrObject* pObject = aIter.Next();
329  while ( pObject )
330  {
331  AddRangesIfProtectedChart( rRangesVector, rDocument, pObject );
332  pObject = aIter.Next();
333  }
334  }
335 }
336 
337 void ScChartHelper::GetChartNames( ::std::vector< OUString >& rChartNames, const SdrPage* pPage )
338 {
339  if ( !pPage )
340  return;
341 
342  SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
343  SdrObject* pObject = aIter.Next();
344  while ( pObject )
345  {
346  if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
347  {
348  SdrOle2Obj* pSdrOle2Obj = dynamic_cast< SdrOle2Obj* >( pObject );
349  if ( pSdrOle2Obj && pSdrOle2Obj->IsChart() )
350  {
351  rChartNames.push_back( pSdrOle2Obj->GetPersistName() );
352  }
353  }
354  pObject = aIter.Next();
355  }
356 }
357 
359  const ScRangeListVector& rRangesVector, const ::std::vector< OUString >& rExcludedChartNames, bool bSameDoc )
360 {
361  if ( !(pPage && pModelObj) )
362  return;
363 
364  size_t nRangeListCount = rRangesVector.size();
365  size_t nRangeList = 0;
366  SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
367  SdrObject* pObject = aIter.Next();
368  while ( pObject )
369  {
370  if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
371  {
372  SdrOle2Obj* pSdrOle2Obj = dynamic_cast< SdrOle2Obj* >( pObject );
373  if ( pSdrOle2Obj && pSdrOle2Obj->IsChart() )
374  {
375  const OUString& aChartName = pSdrOle2Obj->GetPersistName();
376  ::std::vector< OUString >::const_iterator aEnd = rExcludedChartNames.end();
377  ::std::vector< OUString >::const_iterator aFound = ::std::find( rExcludedChartNames.begin(), aEnd, aChartName );
378  if ( aFound == aEnd )
379  {
380  const uno::Reference< embed::XEmbeddedObject >& xEmbeddedObj = pSdrOle2Obj->GetObjRef();
381  if ( xEmbeddedObj.is() && ( nRangeList < nRangeListCount ) )
382  {
383  bool bDisableDataTableDialog = false;
385  uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
386  if ( xProps.is() &&
387  ( xProps->getPropertyValue("DisableDataTableDialog") >>= bDisableDataTableDialog ) &&
388  bDisableDataTableDialog )
389  {
390  if ( bSameDoc )
391  {
393  if (pCollection && !pCollection->findByName(aChartName))
394  {
395  ScRangeList aRangeList( rRangesVector[ nRangeList++ ] );
396  ScRangeListRef rRangeList( new ScRangeList( aRangeList ) );
397  ScChartListener* pChartListener = new ScChartListener( aChartName, rDoc, rRangeList );
398  pCollection->insert( pChartListener );
399  pChartListener->StartListeningTo();
400  }
401  }
402  else
403  {
404  xProps->setPropertyValue("DisableDataTableDialog",
405  uno::makeAny( false ) );
406  xProps->setPropertyValue("DisableComplexChartTypes",
407  uno::makeAny( false ) );
408  }
409  }
410  }
411 
412  if (pModelObj->HasChangesListeners())
413  {
414  tools::Rectangle aRectangle = pSdrOle2Obj->GetSnapRect();
415  ScRange aRange( rDoc.GetRange( nTab, aRectangle ) );
416  ScRangeList aChangeRanges( aRange );
417 
418  uno::Sequence< beans::PropertyValue > aProperties( 1 );
419  aProperties[ 0 ].Name = "Name";
420  aProperties[ 0 ].Value <<= aChartName;
421 
422  pModelObj->NotifyChanges( "insert-chart", aChangeRanges, aProperties );
423  }
424  }
425  }
426  }
427  pObject = aIter.Next();
428  }
429 }
430 
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool is() const
bool IsChart() const
static void FillProtectedChartRangesVector(ScRangeListVector &rRangesVector, const ScDocument &rDocument, const SdrPage *pPage)
ScAddress aStart
Definition: address.hxx:499
css::uno::Reference< css::embed::XEmbeddedObject > const & GetObjRef() const
static css::uno::Reference< css::chart2::XChartDocument > GetChartFromSdrObject(const SdrObject *pObject)
bool insert(ScChartListener *pListener)
Definition: chartlis.cxx:385
ScRangeListRef GetRangeList() const
Definition: chartlis.cxx:184
ScAddress aEnd
Definition: address.hxx:500
SC_DLLPUBLIC ScRange GetRange(SCTAB nTab, const tools::Rectangle &rMMRect, bool bHiddenAsZero=true) const
Definition: documen3.cxx:1806
virtual SdrObjKind GetObjIdentifier() const
virtual const tools::Rectangle & GetSnapRect() const override
EmbeddedObjectRef * pObject
css::uno::Reference< css::chart2::XChartDocument > GetChartByName(std::u16string_view rChartName)
Definition: documen5.cxx:137
void UpdateChart(const OUString &rName)
Definition: documen5.cxx:335
static void CreateProtectedChartListenersAndNotify(ScDocument &rDoc, const SdrPage *pPage, ScModelObj *pModelObj, SCTAB nTab, const ScRangeListVector &rRangesVector, const ::std::vector< OUString > &rExcludedChartNames, bool bSameDoc=true)
PropertiesInfo aProperties
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:314
int nCount
SCTAB Tab() const
Definition: address.hxx:270
void StartListeningTo()
Definition: chartlis.cxx:262
static void AddRangesIfProtectedChart(ScRangeListVector &rRangesVector, const ScDocument &rDocument, SdrObject *pObject)
static void AdjustRangesOfChartsOnDestinationPage(const ScDocument &rSrcDoc, ScDocument &rDestDoc, const SCTAB nSrcTab, const SCTAB nDestTab)
static void GetChartNames(::std::vector< OUString > &rChartNames, const SdrPage *pPage)
void SetTab(SCTAB nTabP)
Definition: address.hxx:282
ScChartListener * findByName(const OUString &rName)
Definition: chartlis.cxx:400
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1057
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
static void GetChartRanges(const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc, std::vector< OUString > &rRanges)
const SdrPage * GetPage(sal_uInt16 nPgNum) const
size_t size() const
Definition: rangelst.hxx:89
static void UpdateChartsOnDestinationPage(ScDocument &rDestDoc, const SCTAB nDestTab)
::std::vector< ScRangeList > ScRangeListVector
Definition: charthelper.hxx:29
void NotifyChanges(const OUString &rOperation, const ScRangeList &rRanges, const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Definition: docuno.cxx:3155
SdrObject * Next()
Any makeAny(Color const &value)
OUString aName
const OUString & GetPersistName() const
SC_DLLPUBLIC ScChartListenerCollection * GetChartListenerCollection() const
Definition: document.hxx:2155
SC_DLLPUBLIC void GetChartRanges(std::u16string_view rChartName, std::vector< ScRangeList > &rRanges, const ScDocument &rSheetNameDoc)
Definition: documen5.cxx:167
static bool IsChart(const SdrObject *pObject)
Definition: documen9.cxx:203
static bool TryRunningState(const css::uno::Reference< css::embed::XEmbeddedObject > &)
bool HasChangesListeners() const
Definition: docuno.cxx:3146
void SetChartRanges(std::u16string_view rChartName, const std::vector< ScRangeList > &rRanges)
Definition: documen5.cxx:184
OBJ_OLE2
static void SetChartRanges(const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc, const css::uno::Sequence< OUString > &rRanges)
static sal_uInt16 DoUpdateAllCharts(ScDocument &rDoc)
sal_uInt16 GetPageCount() const
sal_Int16 SCTAB
Definition: types.hxx:22