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