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